exiftool-vendored 33.2.0 → 33.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,9 +25,105 @@ export declare const UnsetZone: Zone<boolean>;
25
25
  * Zone instances with this name are a placeholder for being "unset".
26
26
  */
27
27
  export declare const UnsetZoneName: string;
28
+ /**
29
+ * Check if a timezone value represents UTC.
30
+ *
31
+ * Handles multiple UTC representations including Zone instances, strings, and
32
+ * numeric offsets. Recognizes common UTC aliases like "GMT", "Z", "Zulu",
33
+ * "+0", "+00:00", etc.
34
+ *
35
+ * @param zone - Timezone to check (Zone, string, or number)
36
+ * @returns true if the zone represents UTC/GMT/Zulu
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * isUTC("UTC") // true
41
+ * isUTC("GMT") // true
42
+ * isUTC("Z") // true
43
+ * isUTC("Zulu") // true
44
+ * isUTC(0) // true
45
+ * isUTC("+00:00") // true
46
+ * isUTC("UTC+0") // true
47
+ * isUTC("America/New_York") // false
48
+ * isUTC("+08:00") // false
49
+ * ```
50
+ */
28
51
  export declare function isUTC(zone: unknown): boolean;
52
+ /**
53
+ * Check if a Zone is the library's sentinel "unset" value.
54
+ *
55
+ * The library uses a special Zone instance to represent unknown/unset
56
+ * timezones since Luxon doesn't officially support unset zones.
57
+ *
58
+ * @param zone - Zone instance to check
59
+ * @returns true if the zone is the UnsetZone sentinel value
60
+ *
61
+ * @see {@link UnsetZone}
62
+ * @see {@link UnsetZoneName}
63
+ * @see {@link UnsetZoneOffsetMinutes}
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * isZoneUnset(UnsetZone) // true
68
+ * isZoneUnset(Info.normalizeZone("UTC")) // false
69
+ * isZoneUnset(Info.normalizeZone("UTC+8")) // false
70
+ * ```
71
+ */
29
72
  export declare function isZoneUnset(zone: Zone): boolean;
73
+ /**
74
+ * Type guard to check if a Zone is valid and usable.
75
+ *
76
+ * A zone is considered valid if it:
77
+ * - Is not null/undefined
78
+ * - Has `isValid === true` (Luxon requirement)
79
+ * - Is not the library's UnsetZone sentinel
80
+ * - Has an offset within ±14 hours (the valid range for real-world timezones)
81
+ *
82
+ * This is the canonical validation check used throughout the library.
83
+ *
84
+ * @param zone - Zone to validate
85
+ * @returns true if the zone is valid and usable (type guard)
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const zone = Info.normalizeZone("America/Los_Angeles")
90
+ * if (isZoneValid(zone)) {
91
+ * // TypeScript knows zone is Zone (not Zone | undefined)
92
+ * console.log(zone.name)
93
+ * }
94
+ *
95
+ * isZoneValid(Info.normalizeZone("invalid")) // false
96
+ * isZoneValid(Info.normalizeZone("UTC+8")) // true
97
+ * isZoneValid(UnsetZone) // false
98
+ * isZoneValid(Info.normalizeZone("UTC+20")) // false (beyond ±14 hours)
99
+ * ```
100
+ */
30
101
  export declare function isZoneValid(zone: Maybe<Zone>): zone is Zone;
102
+ /**
103
+ * Type guard to check if a value is a Luxon Zone instance.
104
+ *
105
+ * Checks both `instanceof Zone` and constructor name to handle cross-module
106
+ * Zone instances that may not pass instanceof checks.
107
+ *
108
+ * @param zone - Value to check
109
+ * @returns true if the value is a Zone instance (type guard)
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * import { Info } from "luxon"
114
+ *
115
+ * const zone = Info.normalizeZone("UTC+8")
116
+ * if (isZone(zone)) {
117
+ * // TypeScript knows zone is Zone (not unknown)
118
+ * console.log(zone.offset(Date.now()))
119
+ * }
120
+ *
121
+ * isZone(Info.normalizeZone("UTC")) // true
122
+ * isZone("UTC") // false
123
+ * isZone(480) // false
124
+ * isZone(null) // false
125
+ * ```
126
+ */
31
127
  export declare function isZone(zone: unknown): zone is Zone;
32
128
  /**
33
129
  * If `tzSource` matches this value, the tags are from a video, and we had to
@@ -36,16 +132,119 @@ export declare function isZone(zone: unknown): zone is Zone;
36
132
  */
37
133
  export declare const defaultVideosToUTC = "defaultVideosToUTC";
38
134
  /**
39
- * @param input must be either a number, which is the offset in minutes, or a
40
- * string in the format "UTC+H" or "UTC+HH:mm"
135
+ * Normalize a timezone input to a valid Luxon Zone.
136
+ *
137
+ * Accepts multiple input formats and returns a validated Zone instance, or
138
+ * undefined if the input cannot be normalized to a valid timezone.
139
+ *
140
+ * Supported input formats:
141
+ * - **Numbers**: Timezone offset in minutes (e.g., 480 = UTC+8, -300 = UTC-5)
142
+ * - **Strings**: ISO offsets ("+08:00", "-05:00"), IANA zones
143
+ * ("America/Los_Angeles"), UTC variants ("UTC", "GMT", "Z", "Zulu")
144
+ * - **Zone instances**: Validated and returned if valid
145
+ *
146
+ * The function respects Settings:
147
+ * - {@link Settings.allowArchaicTimezoneOffsets} for pre-1982 offsets
148
+ * - {@link Settings.allowBakerIslandTime} for UTC-12:00
149
+ *
150
+ * @param input - Timezone in various formats
151
+ * @returns Valid Zone instance, or undefined if invalid
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * // Numbers (offset in minutes)
156
+ * normalizeZone(480)?.name // "UTC+8"
157
+ * normalizeZone(-300)?.name // "UTC-5"
158
+ * normalizeZone(0)?.name // "UTC"
159
+ *
160
+ * // ISO offset strings
161
+ * normalizeZone("+08:00")?.name // "UTC+8"
162
+ * normalizeZone("-05:30")?.name // "UTC-5:30"
163
+ * normalizeZone("UTC+7")?.name // "UTC+7"
164
+ *
165
+ * // IANA timezone names
166
+ * normalizeZone("America/Los_Angeles")?.name // "America/Los_Angeles"
167
+ * normalizeZone("Asia/Tokyo")?.name // "Asia/Tokyo"
168
+ *
169
+ * // UTC aliases
170
+ * normalizeZone("UTC")?.name // "UTC"
171
+ * normalizeZone("GMT")?.name // "UTC"
172
+ * normalizeZone("Z")?.name // "UTC"
173
+ * normalizeZone("Zulu")?.name // "UTC"
174
+ *
175
+ * // Invalid inputs return undefined
176
+ * normalizeZone("invalid") // undefined
177
+ * normalizeZone("+25:00") // undefined (beyond ±14 hours)
178
+ * normalizeZone(null) // undefined
179
+ * ```
41
180
  */
42
181
  export declare function normalizeZone(input: unknown): Maybe<Zone>;
43
182
  /**
44
- * @param ts must be provided if the zone is not a fixed offset
45
- * @return the zone offset (in "±HH:MM" format) for the given zone, or "" if
46
- * the zone is invalid
183
+ * Convert a timezone to its short offset format (e.g., "+08:00", "-05:00").
184
+ *
185
+ * Useful for displaying timezone offsets in a standardized format. For IANA
186
+ * zones with daylight saving time, provide a timestamp to get the correct
187
+ * offset for that moment.
188
+ *
189
+ * @param zone - Timezone as Zone, string, or offset in minutes
190
+ * @param ts - Optional timestamp (milliseconds) for IANA zone offset calculation.
191
+ * Defaults to current time if not provided.
192
+ * @returns Zone offset in "+HH:MM" format, or "" if zone is invalid
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * // Fixed offsets
197
+ * zoneToShortOffset("UTC+8") // "+08:00"
198
+ * zoneToShortOffset(480) // "+08:00"
199
+ * zoneToShortOffset("UTC-5:30") // "-05:30"
200
+ *
201
+ * // IANA zones (offset depends on DST)
202
+ * const winter = new Date("2023-01-15").getTime()
203
+ * const summer = new Date("2023-07-15").getTime()
204
+ * zoneToShortOffset("America/Los_Angeles", winter) // "-08:00" (PST)
205
+ * zoneToShortOffset("America/Los_Angeles", summer) // "-07:00" (PDT)
206
+ *
207
+ * // Invalid zones return empty string
208
+ * zoneToShortOffset("invalid") // ""
209
+ * zoneToShortOffset(null) // ""
210
+ * ```
47
211
  */
48
212
  export declare function zoneToShortOffset(zone: Maybe<string | number | Zone>, ts?: number): string;
213
+ /**
214
+ * Type guard to check if a numeric offset (in minutes) represents a valid timezone.
215
+ *
216
+ * Validates that the offset:
217
+ * - Is a number (not null/undefined)
218
+ * - Is not the UnsetZone sentinel value (-1)
219
+ * - Matches a real-world timezone offset (respects Settings for archaic offsets)
220
+ *
221
+ * Use this for exact validation without rounding. For error-tolerant rounding to
222
+ * the nearest valid offset, use {@link inferLikelyOffsetMinutes} instead.
223
+ *
224
+ * @param tzOffsetMinutes - Offset in minutes to validate (e.g., 480 for UTC+8)
225
+ * @returns true if the offset is exactly valid (type guard)
226
+ *
227
+ * @see {@link inferLikelyOffsetMinutes} for error-tolerant rounding
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * validTzOffsetMinutes(480) // true (UTC+8)
232
+ * validTzOffsetMinutes(-300) // true (UTC-5)
233
+ * validTzOffsetMinutes(330) // true (UTC+5:30, India)
234
+ * validTzOffsetMinutes(345) // true (UTC+5:45, Nepal)
235
+ *
236
+ * validTzOffsetMinutes(481) // false (not a valid timezone)
237
+ * validTzOffsetMinutes(-1) // false (UnsetZone sentinel)
238
+ * validTzOffsetMinutes(null) // false
239
+ *
240
+ * // Archaic offsets require Settings
241
+ * Settings.allowArchaicTimezoneOffsets.value = false
242
+ * validTzOffsetMinutes(-630) // false (Hawaii -10:30, archaic)
243
+ *
244
+ * Settings.allowArchaicTimezoneOffsets.value = true
245
+ * validTzOffsetMinutes(-630) // true (Hawaii -10:30, archaic)
246
+ * ```
247
+ */
49
248
  export declare function validTzOffsetMinutes(tzOffsetMinutes: Maybe<number>): tzOffsetMinutes is number;
50
249
  /**
51
250
  * Returns a "zone name" (used by `luxon`) that encodes the given offset.
@@ -71,24 +270,284 @@ export interface TzSrc {
71
270
  src: string;
72
271
  }
73
272
  /**
74
- * Parse a timezone offset and return the offset minutes
273
+ * Extract timezone information from various value types.
274
+ *
275
+ * Handles multiple input formats and performs intelligent parsing:
276
+ * - **Strings**: ISO offsets ("+08:00"), IANA zones, UTC variants, timestamps
277
+ * with embedded timezones ("2023:01:15 10:30:00-08:00")
278
+ * - **Numbers**: Hour offsets (e.g., -8 for UTC-8)
279
+ * - **Arrays**: Uses first non-null value
280
+ * - **ExifDateTime/ExifTime instances**: Extracts their zone property
281
+ *
282
+ * By default, strips timezone abbreviations (PST, PDT, etc.) as they are
283
+ * ambiguous. Returns provenance information indicating which parsing method
284
+ * succeeded.
285
+ *
286
+ * Supports Unicode minus signs (−, U+2212) and plus-minus signs (±, U+00B1)
287
+ * in addition to ASCII +/-.
288
+ *
289
+ * @param value - Value to extract timezone from
290
+ * @param opts.stripTZA - Whether to strip timezone abbreviations (default: true).
291
+ * TZAs like "PST" are ambiguous and usually stripped.
292
+ * @returns TzSrc with zone name and provenance, or undefined if no timezone found
75
293
  *
76
- * @param opts.stripTZA If false, do not strip off the timezone abbreviation
77
- * (TZA) from the value. Defaults to true.
294
+ * @example
295
+ * ```typescript
296
+ * // ISO offset strings
297
+ * extractZone("+08:00")
298
+ * // { zone: "UTC+8", tz: "UTC+8", src: "offsetMinutesToZoneName" }
78
299
  *
79
- * @return undefined if the value cannot be parsed as a valid timezone offset
300
+ * extractZone("UTC-5:30")
301
+ * // { zone: "UTC-5:30", tz: "UTC-5:30", src: "normalizeZone" }
302
+ *
303
+ * // IANA zone names
304
+ * extractZone("America/Los_Angeles")
305
+ * // { zone: "America/Los_Angeles", tz: "America/Los_Angeles", src: "normalizeZone" }
306
+ *
307
+ * // Timestamps with embedded timezones
308
+ * extractZone("2023:01:15 10:30:00-08:00")
309
+ * // { zone: "UTC-8", tz: "UTC-8", src: "offsetMinutesToZoneName",
310
+ * // leftovers: "2023:01:15 10:30:00" }
311
+ *
312
+ * // Unicode minus signs
313
+ * extractZone("−08:00") // Unicode minus (U+2212)
314
+ * // { zone: "UTC-8", tz: "UTC-8", src: "offsetMinutesToZoneName" }
315
+ *
316
+ * // Numeric hour offsets
317
+ * extractZone(-8)
318
+ * // { zone: "UTC-8", tz: "UTC-8", src: "hourOffset" }
319
+ *
320
+ * // Arrays (uses first non-null)
321
+ * extractZone([null, "+05:30", undefined])
322
+ * // { zone: "UTC+5:30", tz: "UTC+5:30", src: "offsetMinutesToZoneName" }
323
+ *
324
+ * // Strips timezone abbreviations by default
325
+ * extractZone("2023:01:15 10:30:00-08:00 PST")
326
+ * // { zone: "UTC-8", tz: "UTC-8", src: "offsetMinutesToZoneName",
327
+ * // leftovers: "2023:01:15 10:30:00" }
328
+ *
329
+ * // Invalid inputs return undefined
330
+ * extractZone("invalid") // undefined
331
+ * extractZone(null) // undefined
332
+ * ```
80
333
  */
81
334
  export declare function extractZone(value: unknown, opts?: {
82
335
  stripTZA?: boolean;
83
336
  }): Maybe<TzSrc>;
84
337
  export declare const TimezoneOffsetTagnames: readonly ["TimeZone", "OffsetTimeOriginal", "OffsetTimeDigitized", "TimeZoneOffset"];
85
338
  export declare function incrementZone(z: string | Zone | number, minutes: number): Maybe<Zone>;
339
+ /**
340
+ * Extract timezone offset from standard EXIF timezone tags.
341
+ *
342
+ * Checks timezone tags in priority order:
343
+ * 1. TimeZone
344
+ * 2. OffsetTimeOriginal (for DateTimeOriginal)
345
+ * 3. OffsetTimeDigitized (for CreateDate)
346
+ * 4. TimeZoneOffset
347
+ *
348
+ * Handles camera-specific quirks like Nikon's DaylightSavings tag, which
349
+ * requires adjusting the TimeZone offset forward by one hour during DST.
350
+ *
351
+ * @param t - EXIF tags object
352
+ * @param opts.adjustTimeZoneIfDaylightSavings - Optional function to adjust
353
+ * timezone for DST. Defaults to handling Nikon's DaylightSavings quirk.
354
+ * @returns TzSrc with zone and provenance, or undefined if no timezone found
355
+ *
356
+ * @see {@link TimezoneOffsetTagnames} for the list of tags checked
357
+ * @see https://github.com/photostructure/exiftool-vendored.js/issues/215
358
+ *
359
+ * @example
360
+ * ```typescript
361
+ * const tags = await exiftool.read("photo.jpg")
362
+ *
363
+ * const tzSrc = extractTzOffsetFromTags(tags)
364
+ * if (tzSrc) {
365
+ * console.log(`Timezone: ${tzSrc.zone}`)
366
+ * console.log(`Source: ${tzSrc.src}`) // e.g., "OffsetTimeOriginal"
367
+ * }
368
+ *
369
+ * // Nikon DST handling
370
+ * const nikonTags = {
371
+ * TimeZone: "-08:00",
372
+ * DaylightSavings: "Yes",
373
+ * Make: "NIKON CORPORATION"
374
+ * }
375
+ * extractTzOffsetFromTags(nikonTags)
376
+ * // { zone: "UTC-7", tz: "UTC-7",
377
+ * // src: "TimeZone (adjusted for DaylightSavings)" }
378
+ * ```
379
+ */
86
380
  export declare function extractTzOffsetFromTags(t: Tags, opts?: Pick<ExifToolOptions, "adjustTimeZoneIfDaylightSavings">): Maybe<TzSrc>;
87
381
  export declare function extractTzOffsetFromDatestamps(t: Tags, opts: Partial<Pick<ExifToolOptions, "inferTimezoneFromDatestamps" | "inferTimezoneFromDatestampTags">>): Maybe<TzSrc>;
88
382
  export declare function extractTzOffsetFromTimeStamp(t: Tags, opts: Partial<Pick<ExifToolOptions, "inferTimezoneFromTimeStamp" | "inferTimezoneFromDatestampTags">>): Maybe<TzSrc>;
89
- export declare function inferLikelyOffsetMinutes(deltaMinutes: number): Maybe<number>;
383
+ /**
384
+ * Round an arbitrary offset to the nearest valid timezone offset.
385
+ *
386
+ * This is error-tolerant timezone inference, useful for:
387
+ * - GPS-based timezone calculation (where GPS time drift may cause errors)
388
+ * - Handling clock drift in timestamp comparisons
389
+ * - Fuzzy timezone matching
390
+ *
391
+ * By default, uses {@link Settings.maxValidOffsetMinutes} (30 minutes) as the
392
+ * maximum distance from a valid timezone. This threshold handles GPS acquisition
393
+ * lag and clock drift while preventing false matches.
394
+ *
395
+ * Respects Settings for archaic offsets, Baker Island time, and max offset tolerance.
396
+ *
397
+ * @param deltaMinutes - Offset in minutes to round (can be fractional)
398
+ * @param maxValidOffsetMinutes - Maximum distance (in minutes) from a valid
399
+ * timezone to accept. Defaults to {@link Settings.maxValidOffsetMinutes}.
400
+ * @returns Nearest valid offset in minutes, or undefined if too far from any
401
+ * valid timezone
402
+ *
403
+ * @see {@link validTzOffsetMinutes} for exact validation without rounding
404
+ * @see {@link Settings.maxValidOffsetMinutes} to configure the default threshold
405
+ *
406
+ * @example
407
+ * ```typescript
408
+ * // Exact matches
409
+ * inferLikelyOffsetMinutes(480) // 480 (UTC+8, exact)
410
+ * inferLikelyOffsetMinutes(-300) // -300 (UTC-5, exact)
411
+ *
412
+ * // Rounding within default threshold (30 minutes)
413
+ * inferLikelyOffsetMinutes(485) // 480 (UTC+8, rounded from 485)
414
+ * inferLikelyOffsetMinutes(-295) // -300 (UTC-5, rounded from -295)
415
+ * inferLikelyOffsetMinutes(330.5) // 330 (UTC+5:30, rounded)
416
+ *
417
+ * // GPS-based inference with clock drift (within 30 min default)
418
+ * const gpsTime = "2023:01:15 19:30:45" // UTC
419
+ * const localTime = "2023:01:15 11:32:12" // Local with 1.5min drift
420
+ * const deltaMinutes = 480 + 1.5 // ~481.5 minutes
421
+ * inferLikelyOffsetMinutes(deltaMinutes) // 480 (UTC+8)
422
+ *
423
+ * // GPS lag up to 23 minutes still works (within 30 min threshold)
424
+ * inferLikelyOffsetMinutes(443) // 420 (UTC-7, ~23 min from actual)
425
+ *
426
+ * // Beyond threshold returns undefined
427
+ * inferLikelyOffsetMinutes(100) // undefined (not near any valid offset)
428
+ *
429
+ * // Custom threshold
430
+ * inferLikelyOffsetMinutes(495, 30) // 480 (UTC+8 with 30min threshold)
431
+ * inferLikelyOffsetMinutes(495, 15) // undefined (beyond 15min threshold)
432
+ *
433
+ * // Adjust global default
434
+ * Settings.maxValidOffsetMinutes.value = 15 // Stricter matching
435
+ * inferLikelyOffsetMinutes(443) // undefined (beyond 15min threshold)
436
+ * ```
437
+ */
438
+ export declare function inferLikelyOffsetMinutes(deltaMinutes: number, maxValidOffsetMinutes?: number): Maybe<number>;
439
+ /**
440
+ * Infer timezone offset by comparing local time with GPS/UTC time.
441
+ *
442
+ * Calculates the timezone by finding the difference between:
443
+ * - A "captured at" timestamp (DateTimeOriginal, CreateDate, etc.) assumed to
444
+ * be in local time
445
+ * - A UTC timestamp (GPSDateTime, DateTimeUTC, or combined GPSDateStamp +
446
+ * GPSTimeStamp)
447
+ *
448
+ * Uses {@link inferLikelyOffsetMinutes} to handle minor clock drift and round
449
+ * to the nearest valid timezone offset.
450
+ *
451
+ * This is a fallback when explicit timezone tags are not available.
452
+ *
453
+ * @param t - Tags object with timestamp fields
454
+ * @returns TzSrc with inferred timezone and provenance, or undefined if
455
+ * inference is not possible
456
+ *
457
+ * @see {@link extractTzOffsetFromTags} to check explicit timezone tags first
458
+ *
459
+ * @example
460
+ * ```typescript
461
+ * // GPS-based inference
462
+ * const tags = {
463
+ * DateTimeOriginal: "2023:01:15 11:30:00", // Local time (PST)
464
+ * GPSDateTime: "2023:01:15 19:30:00" // UTC
465
+ * }
466
+ * extractTzOffsetFromUTCOffset(tags)
467
+ * // { zone: "UTC-8", tz: "UTC-8",
468
+ * // src: "offset between DateTimeOriginal and GPSDateTime" }
469
+ *
470
+ * // DateTimeUTC-based inference
471
+ * const tags2 = {
472
+ * CreateDate: "2023:07:20 14:15:30", // Local time (JST)
473
+ * DateTimeUTC: "2023:07:20 05:15:30" // UTC
474
+ * }
475
+ * extractTzOffsetFromUTCOffset(tags2)
476
+ * // { zone: "UTC+9", tz: "UTC+9",
477
+ * // src: "offset between CreateDate and DateTimeUTC" }
478
+ *
479
+ * // Handles clock drift
480
+ * const tags3 = {
481
+ * DateTimeOriginal: "2023:01:15 11:30:45", // Local with drift
482
+ * GPSDateTime: "2023:01:15 19:29:58" // UTC (old GPS fix)
483
+ * }
484
+ * extractTzOffsetFromUTCOffset(tags3)
485
+ * // Still infers UTC-8 despite ~1 minute drift
486
+ *
487
+ * // No UTC timestamp available
488
+ * const tags4 = {
489
+ * DateTimeOriginal: "2023:01:15 11:30:00"
490
+ * // No GPS or UTC timestamp
491
+ * }
492
+ * extractTzOffsetFromUTCOffset(tags4) // undefined
493
+ * ```
494
+ */
90
495
  export declare function extractTzOffsetFromUTCOffset(t: Pick<Tags, (typeof CapturedAtTagNames)[number] | "GPSDateTime" | "DateTimeUTC" | "GPSDateStamp" | "GPSTimeStamp" | "SonyDateTime2">): Maybe<TzSrc>;
91
- export declare function equivalentZones(a: Maybe<string | number | Zone>, b: Maybe<string | number | Zone>): boolean;
496
+ /**
497
+ * Check if two timezone values are equivalent at a specific point in time.
498
+ *
499
+ * Two zones are considered equivalent if they:
500
+ * - Are the same zone (via Luxon's Zone.equals()), OR
501
+ * - Have the same offset at the specified timestamp
502
+ *
503
+ * This is useful for:
504
+ * - De-duplicating timezone records
505
+ * - Comparing zones in different formats ("UTC+5" vs "UTC+05:00")
506
+ * - Matching IANA zones to their offset at a specific time
507
+ *
508
+ * For IANA zones with DST, you can specify a timestamp to evaluate equivalence
509
+ * at that moment. This is important when comparing historical records or future
510
+ * events where DST transitions matter.
511
+ *
512
+ * @param a - First timezone (Zone, string, or offset in minutes)
513
+ * @param b - Second timezone (Zone, string, or offset in minutes)
514
+ * @param at - Timestamp in milliseconds to evaluate zone offsets.
515
+ * Defaults to current time (Date.now()).
516
+ * @returns true if zones are equivalent at the specified time
517
+ *
518
+ * @example
519
+ * ```typescript
520
+ * // Same zone, different formats
521
+ * equivalentZones("UTC+5", "UTC+05:00") // true
522
+ * equivalentZones("UTC-8", -480) // true (480 minutes = 8 hours)
523
+ * equivalentZones("GMT", "UTC") // true
524
+ * equivalentZones("Z", 0) // true
525
+ *
526
+ * // IANA zones matched by current offset (default behavior)
527
+ * equivalentZones("America/New_York", "UTC-5") // true in winter (EST)
528
+ * equivalentZones("America/New_York", "UTC-4") // true in summer (EDT)
529
+ *
530
+ * // IANA zones at specific times
531
+ * const winter = new Date("2023-01-15").getTime()
532
+ * const summer = new Date("2023-07-15").getTime()
533
+ * equivalentZones("America/New_York", "UTC-5", winter) // true (EST)
534
+ * equivalentZones("America/New_York", "UTC-4", winter) // false (not EDT in winter)
535
+ * equivalentZones("America/New_York", "UTC-4", summer) // true (EDT)
536
+ * equivalentZones("America/New_York", "UTC-5", summer) // false (not EST in summer)
537
+ *
538
+ * // Compare two IANA zones at a specific time
539
+ * equivalentZones("America/New_York", "America/Toronto", winter) // true (both EST)
540
+ * equivalentZones("America/New_York", "America/Los_Angeles", winter) // false (EST vs PST)
541
+ *
542
+ * // Different zones
543
+ * equivalentZones("UTC+8", "UTC+9") // false
544
+ *
545
+ * // Invalid zones return false
546
+ * equivalentZones("invalid", "UTC") // false
547
+ * equivalentZones(null, "UTC") // false
548
+ * ```
549
+ */
550
+ export declare function equivalentZones(a: Maybe<string | number | Zone>, b: Maybe<string | number | Zone>, at?: number): boolean;
92
551
  export declare function getZoneName(args?: {
93
552
  zone?: Zone;
94
553
  zoneName?: Maybe<string>;