Conversation
…1147) When a file's metadata carries no time zone, getDates() stored it as UTC even when the server's TZ is set, although the docs describe TZ as the fallback. West of UTC this moved evening photos to the next day. Two paths: - Files with no date (e.g. WhatsApp, which strips EXIF) fell back to the earliest file timestamp as a bare instant, with a null time zone. - QuickTime videos with no zone (e.g. Android camera videos with location off) are parsed by exiftool as UTC (defaultVideosToUTC), and that assumed zone was stored as if it came from the file. Videos whose zone exiftool only assumed now use the server's zone, and the no-date fallback keeps its local time in the file's zone if known, else the server's. exiftool-vendored reports the source as `tzSource`, not `zoneSource`, so the check (and the existing log line) use that field. getServerTimeZone() returns null for UTC under any alias, so installs without TZ store the same values as before. Photos with a capture time but no offset (the #607 path) are unchanged. Tests: unit cases for both paths plus the guards, medium cases that run the real exiftool on a dateless image and a zone-less mp4, and TZ is pinned to UTC in the medium config as it already is in the unit config, so results no longer depend on the machine's zone.
…ames Review follow-ups to the server TZ fallback: - exiftool reports tzSource 'defaultVideosToUTC' even when the video's date says +00:00 or Z outright, e.g. an iPhone video recorded in Lisbon, where Keys:CreationDate carries the local offset. That UTC came from the file, so it is no longer replaced by the server's zone. - Node resolves TZ=Asia/Kolkata to the legacy ICU name Asia/Calcutta (also Europe/Kyiv -> Europe/Kiev, Asia/Ho_Chi_Minh -> Asia/Saigon), which the mobile app's zone database does not have. getServerTimeZone() now keeps the configured spelling when it names the same zone, matching the current names geo-tz stores for GPS-located photos. - exiftool-vendored's types deprecate tzSource in favour of zoneSource while 35.x only sets tzSource at runtime; read either, and strip zoneSource along with the other zone tags when a sidecar supplies the date. - The unit helper for assumed-UTC video tags now builds the date with ExifDateTime.fromEXIF, matching the raw value real exiftool returns.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1147.
What was wrong
When a file's metadata carries no time zone,
getDates()inmetadata.service.tsstored it as UTC even when the server'sTZis set. The docs describeTZas the fallback. West of UTC this moved evening photos to the next day in the timeline and the viewer. Two paths did this:timeZone: null, so the local time was lost.defaultVideosToUTC), and that assumed zone was stored as if the file said so.What changed
+00:00orZoutright keep UTC. exiftool reports the samedefaultVideosToUTCsource for these (verified on a real file). iPhones write the local offset intoKeys:CreationDate, so a video recorded in Lisbon or Reykjavik really is UTC+0.getServerTimeZone()(src/utils/date.ts):nullwhen the server runs in UTC under any alias (UTC,Etc/UTC,GMT, which Node reports as+00:00, …) orTZis unusable. Installs withoutTZstore exactly what they did before.TZ. Node would otherwise report legacy ICU names (Asia/Kolkata→Asia/Calcutta,Europe/Kyiv→Europe/Kiev,Asia/Ho_Chi_Minh→Asia/Saigon), which the mobile app'stimezonedatabase doesn't have. It validates first, soTZ=:America/New_YorkstoresAmerica/New_York.tzSourceforzoneSource, but 35.x only setstzSourceat runtime. The fix reads either. When a sidecar supplies the date,zoneSourceis now stripped along withzone/tz/tzSource, so the video's assumed UTC can't be applied to a sidecar date. The fix proposed in the issue checkedzoneSourceonly, which never matches on 35.x; the existing verbose log line had the same problem and always printed "via undefined".Existing assets are not rewritten; they pick up the fix when their metadata is re-extracted. On a non-UTC server, re-extracting all metadata will therefore move dateless files and zone-less videos to their local day. That is the intended correction.
Tests
Unit,
metadata.service.spec.ts:tzSourceorzoneSource+00:00andZvideo dates stay UTCUnit,
date.spec.ts:getServerTimeZone()for UTC aliases, Europe/London, legacy-renamed zones, a:-prefixedTZand an invalidTZ.Medium, real exiftool and database:
short.mp4with a zone-less QuickTimeCreateDate, on non-UTC and UTC serversshort.mp4with an explicit+00:00Keys:CreationDateshort.mp4with no date at allAgainst the original code the first two fail with exactly the rows from the issue (
null/ 01:07,UTC/ 20:57).Mutation check: 12 targeted mutations of the fix (each guard removed or weakened), and every one fails at least one test.
Harness:
TZinbeforeEach, which let the machine's zone leak into tests. It now resetsTZtoUTC.TZ, soexif-date-time.spec.ts > should ignore the TimeCreated tagdepended on the machine's zone once this fix landed. It is now pinned toUTC, as the unit config already is.MediaRepositoryis added to the medium harness's mockable repositories.Local: unit 201 files / 6460 tests, medium 181 files / 3223 tests,
tsc, eslint and prettier clean.