Skip to content

Conversation

@kao-byte
Copy link
Contributor

@kao-byte kao-byte commented Dec 1, 2025

Description

Fixes
#12650

This fix does not change any behaviour regarding the handling of date & time at the server side.

With this fix, both the metadata display and edit dialog show dates in the actual timezone where photos were taken, matching the web app's behavior exactly, regardless of the mobile devices' current timezone setting.

1. mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart

Why: The metadata sheet was displaying dates in the device's system timezone instead of the timezone where the photo was actually taken.

What changed:

  • Added imports for timezone package and duration_extensions
  • Rewrote the _getDateTime() method to use EXIF timezone information (dateTimeOriginal and timeZone fields)
  • Implemented the same timezone conversion logic as the web app, handling both named timezones (e.g., "Asia/Hong_Kong") and UTC offset formats (e.g., "UTC+08:00")
  • Updated the method signature to accept ExifInfo parameter
  • Changed timezone display format from manual string formatting to use formatAsOffset() extension with "GMT" prefix (same as the web app)

2. mobile/lib/services/action.service.dart
Why: The edit date/time dialog was also using the device's timezone when pre-filling the initial date, causing inconsistency between the displayed date and the editable date.

What changed:

  • Added import for timezone package
  • Rewrote the editDateTime() method to apply EXIF timezone conversion before showing the date picker
  • Used a local non-nullable DateTime variable to handle transformations safely
  • Applied the same EXIF timezone logic as the display method to ensure consistency
  • Properly set both timeZone and offset parameters for the date picker

How Has This Been Tested?

  • Tested on real iOS devices, it works as expected

Screenshots (if appropriate)

Checklist:

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation if applicable
  • I have no unrelated changes in the PR.
  • I have confirmed that any new dependencies are strictly necessary.
  • I have written tests for new code (if applicable)
  • I have followed naming conventions/patterns in the surrounding code
  • All code in src/services/ uses repositories implementations for database calls, filesystem operations, etc.
  • All code in src/repositories/ is pretty basic/simple and does not have any immich specific logic (that belongs in src/services/)

Please describe to which degree, if any, an LLM was used in creating this pull request.

Some codes are generated by Claude Code under human supervision and verification
...

@immich-push-o-matic
Copy link

immich-push-o-matic bot commented Dec 1, 2025

Label error. Requires exactly 1 of: changelog:.*. Found: 📱mobile. A maintainer will add the required label.

DateTime dt = asset.createdAt.toLocal();
offset = dt.timeZoneOffset;

if (exifData?.dateTimeOriginal != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you help refactor this method to a utils file so we don't have duplicate code here?

Comment on lines +90 to +96
String _getDateTime(BuildContext ctx, BaseAsset asset, ExifInfo? exifInfo) {
DateTime dateTime = asset.createdAt.toLocal();
Duration timeZoneOffset = dateTime.timeZoneOffset;

// Use EXIF timezone information if available (matching web app behavior)
if (exifInfo?.dateTimeOriginal != null) {
dateTime = exifInfo!.dateTimeOriginal!;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a method for this in asset_extensions.dart named getTZAdjustedTimeAndOffset

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants