From 6c9c4a8653e2bcf36da00b030edd30f854a6427a Mon Sep 17 00:00:00 2001 From: Matthew McEachen Date: Sun, 22 Sep 2024 11:21:58 -0700 Subject: [PATCH] Update for #208: use improved ValidTimezoneOffsets. Use new leastBy --- src/Timezones.spec.ts | 15 +++++++++++++-- src/Timezones.ts | 26 ++++++++++---------------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/Timezones.spec.ts b/src/Timezones.spec.ts index e1b833b..b94361b 100644 --- a/src/Timezones.spec.ts +++ b/src/Timezones.spec.ts @@ -161,6 +161,17 @@ describe("Timezones", () => { }) describe("extractTzOffsetFromUTCOffset", () => { + it("with DateTimeUTC offset by 4 hours and preceding by one second from DateTimeOriginal", () => { + expect( + extractTzOffsetFromUTCOffset({ + DateTimeOriginal: "2024:09:14 12:00:00", + DateTimeUTC: "2024:09:14 15:59:00", // from a prior GPS fix? + }) + ).to.eql({ + tz: "UTC-4", + src: "offset between DateTimeOriginal and DateTimeUTC", + }) + }) it("with DateTimeUTC offset by 4 hours and lagging by one second from DateTimeOriginal", () => { expect( extractTzOffsetFromUTCOffset({ @@ -211,14 +222,14 @@ describe("Timezones", () => { src: "offset between CreateDate and " + tagname, }) }) - it(`with lagging ${tagname} and SubSecCreateDate in positive half-hour offset`, () => { + it(`with lagging ${tagname} and SubSecCreateDate in positive :20 offset`, () => { const obj: Tags = { SubSecCreateDate: "2016:07:18 09:54:03", } obj[tagname] = "2016:07:18 04:16:01" expect(extractTzOffsetFromUTCOffset(obj)).to.eql({ - tz: "UTC+5:30", + tz: "UTC+5:45", src: "offset between SubSecCreateDate and " + tagname, }) }) diff --git a/src/Timezones.ts b/src/Timezones.ts index ff3a0eb..3e892bc 100644 --- a/src/Timezones.ts +++ b/src/Timezones.ts @@ -1,4 +1,5 @@ import { FixedOffsetZone, Info, Zone } from "luxon" +import { leastBy } from "./Array" import { BinaryField } from "./BinaryField" import { CapturedAtTagNames } from "./CapturedAtTagNames" import { ExifDate } from "./ExifDate" @@ -38,7 +39,6 @@ const ValidTimezoneOffsets = [ // "-00:25:21", // Ireland 1880-1916 https://en.wikipedia.org/wiki/UTC%E2%88%9200:25:21 "+00:00", // "+00:20", // used by Netherlands until 1940 - // "+00:30", // used by Switzerland until 1936 "+01:00", // "+01:24", // used by Warsaw until 1915 @@ -53,7 +53,7 @@ const ValidTimezoneOffsets = [ "+05:00", "+05:30", // "+05:40", // used by Nepal until 1920 - "+05:45", + "+05:45", // Nepal "+06:00", "+06:30", "+07:00", @@ -409,20 +409,14 @@ export function extractTzOffsetFromDatestamps( // old, this can be spurious. We get less mistakes with a larger multiple, so // we're using 30 minutes instead of 15. See // https://www.timeanddate.com/time/time-zones-interesting.html -const LikelyOffsetMinutes = ValidTimezoneOffsets - .filter((offset) => offset.endsWith(":00") || offset.endsWith(":30")) - .map(offsetToMinutes) - -export function inferLikelyOffsetMinutes(deltaMinutes: number): number { - // More then a day away? nothing is likely - if (Math.abs(deltaMinutes) > (24 * 60)) return deltaMinutes - - return LikelyOffsetMinutes - .reduce((prev, curr) => - Math.abs(curr - deltaMinutes) < Math.abs(prev - deltaMinutes) - ? curr - : prev - ) +const LikelyOffsetMinutes = ValidTimezoneOffsets.map(offsetToMinutes) + +export function inferLikelyOffsetMinutes(deltaMinutes: number): Maybe { + const nearest = leastBy(LikelyOffsetMinutes, (ea) => + Math.abs(ea - deltaMinutes) + )! + // Reject timezone offsets more than 30 minutes away from the nearest: + return Math.abs(nearest - deltaMinutes) < 30 ? nearest : undefined } /**