diff --git a/server/src/services/metadata.service.spec.ts b/server/src/services/metadata.service.spec.ts index 88b2498e91b87..4158b72e7b8e9 100644 --- a/server/src/services/metadata.service.spec.ts +++ b/server/src/services/metadata.service.spec.ts @@ -1,4 +1,5 @@ import { BinaryField, ExifDateTime } from 'exiftool-vendored'; +import { DateTime } from 'luxon'; import { randomBytes } from 'node:crypto'; import { Stats } from 'node:fs'; import { constants } from 'node:fs/promises'; @@ -871,10 +872,30 @@ describe(MetadataService.name, () => { metadataMock.readTags.mockResolvedValue(tags); await sut.handleMetadataExtraction({ id: assetStub.image.id }); - expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id]); expect(assetMock.upsertExif).toHaveBeenCalledWith( expect.objectContaining({ timeZone: 'UTC+0', + dateTimeOriginal: DateTime.fromISO('2024-09-01T00:00:00.000Z').toJSDate(), + }), + ); + }); + + it('should extract +00:00 timezone from raw value despite conflicting GPS location/timezone', async () => { + // exiftool-vendored returns a timezone derived from GPS coordinates even though "+00:00" might be set explicitly + // https://github.com/photostructure/exiftool-vendored.js/issues/203 + + const tags: ImmichTags = { + DateTimeOriginal: ExifDateTime.fromISO('2024-09-15T00:00:00.000+00:00'), + tz: 'America/Santiago', + }; + assetMock.getByIds.mockResolvedValue([assetStub.image]); + metadataMock.readTags.mockResolvedValue(tags); + + await sut.handleMetadataExtraction({ id: assetStub.image.id }); + expect(assetMock.upsertExif).toHaveBeenCalledWith( + expect.objectContaining({ + timeZone: 'UTC+0', + dateTimeOriginal: DateTime.fromISO('2024-09-15T00:00:00.000Z').toJSDate(), }), ); }); diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index 3995c72f770e5..910e130777305 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -623,12 +623,10 @@ export class MetadataService extends BaseService { } // timezone - let timeZone = exifTags.tz ?? null; - if (timeZone == null && dateTime?.rawValue?.endsWith('+00:00')) { - // exiftool-vendored returns "no timezone" information even though "+00:00" might be set explicitly - // https://github.com/photostructure/exiftool-vendored.js/issues/203 - timeZone = 'UTC+0'; - } + // exiftool-vendored returns "no timezone" information or one derived from GPS coordinates even though "+00:00" + // might be set explicitly + // https://github.com/photostructure/exiftool-vendored.js/issues/203 + const timeZone = dateTime?.rawValue?.endsWith('+00:00') ? 'UTC+0' : (exifTags.tz ?? null); if (timeZone) { this.logger.debug(`Asset ${asset.id} timezone is ${timeZone} (via ${exifTags.tzSource})`);