{"version":3,"sources":["../src/timezone.ts","../src/temporalProvider.ts","../src/isoWeek.ts","../src/calendarUtils.ts","../src/arithmetic.ts"],"sourcesContent":["/*\n * Copyright 2026 DirazCoder\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Time-zone subsystem. Wraps Temporal.ZonedDateTime's\n// timezone introspection surface in temporal-fmt's field-based convention.\n// Includes disambiguation modes (compatible/earlier/later/reject) for\n// DST gaps and overlaps, plus transition queries (getNextTransition,\n// getPreviousTransition, getTransitions).\n\nimport { getTemporal, type TemporalNamespace } from './temporalProvider.js';\nimport { add } from './arithmetic.js';\n\nexport type DisambiguationMode = 'compatible' | 'earlier' | 'later' | 'reject';\n\nexport interface ResolveZonedOptions {\n  disambiguation?: DisambiguationMode;\n  overflow?: 'constrain' | 'reject';\n  offset?: 'use' | 'ignore' | 'prefer' | 'reject';\n}\n\n// Resolves a wall-clock time in a timezone, applying disambiguation\n// for DST gaps and overlaps.\nexport function resolveZoned(\n  fields: { year: number; month: number; day: number; hour?: number; minute?: number; second?: number; millisecond?: number; microsecond?: number; nanosecond?: number },\n  timeZone: string,\n  options: ResolveZonedOptions = {},\n): unknown {\n  const temporal = getTemporal();\n  const disambiguation = options.disambiguation ?? 'compatible';\n  const overflow = options.overflow ?? 'constrain';\n  // Cast options to a permissive record — Temporal.ZonedDateTime.from\n  // accepts disambiguation/offset options, but the existing\n  // TemporalFactory.from() signature in temporalProvider.ts is narrower.\n  // The runtime accepts the wider shape; this cast bypasses the type\n  // narrowing without changing runtime behavior.\n  const fromOptions = {\n    overflow,\n    disambiguation,\n    offset: options.offset ?? 'prefer',\n  } as unknown as Parameters<typeof temporal.ZonedDateTime.from>[1];\n  try {\n    return temporal.ZonedDateTime.from(\n      {\n        year: fields.year,\n        month: fields.month,\n        day: fields.day,\n        hour: fields.hour ?? 0,\n        minute: fields.minute ?? 0,\n        second: fields.second ?? 0,\n        millisecond: fields.millisecond ?? 0,\n        microsecond: fields.microsecond ?? 0,\n        nanosecond: fields.nanosecond ?? 0,\n        timeZone,\n      },\n      fromOptions,\n    );\n  } catch (err) {\n    // Surface DST gap / overlap errors with a clearer message.\n    const msg = (err as Error).message;\n    if (/no such (wall-clock )?time/i.test(msg) && disambiguation === 'reject') {\n      throw new Error(\n        `temporal-fmt: \"${timeZone}\" has no such wall-clock time on ${fields.year}-${fields.month}-${fields.day}T${fields.hour ?? 0}:${fields.minute ?? 0} — ` +\n        `it falls in a DST gap. Pass { disambiguation: 'compatible' | 'earlier' | 'later' } to pick an instant.`\n      );\n    }\n    throw err;\n  }\n}\n\nexport function getTimeZone(value: unknown): string {\n  const v = value as { timeZoneId?: string };\n  if (typeof v?.timeZoneId !== 'string') {\n    throw new Error(`temporal-fmt: getTimeZone() expected a ZonedDateTime, got ${typeof value}.`);\n  }\n  return v.timeZoneId;\n}\n\nexport function getOffset(value: unknown): string {\n  const v = value as { offset?: string };\n  if (typeof v?.offset !== 'string') {\n    throw new Error(`temporal-fmt: getOffset() expected a ZonedDateTime, got ${typeof value}.`);\n  }\n  return v.offset;\n}\n\nexport function getOffsetNanoseconds(value: unknown): number {\n  const v = value as { offsetNanoseconds?: number; offset?: string };\n  if (typeof v?.offsetNanoseconds === 'number') return v.offsetNanoseconds;\n  if (typeof v?.offset === 'string') {\n    // Parse ±HH:MM → nanoseconds.\n    const m = v.offset.match(/^([+-])(\\d{2}):(\\d{2})$/);\n    if (!m) throw new Error(`temporal-fmt: getOffsetNanoseconds() couldn't parse offset \"${v.offset}\".`);\n    const sign = m[1] === '-' ? -1 : 1;\n    return sign * (Number(m[2]) * 3600 + Number(m[3]) * 60) * 1_000_000_000;\n  }\n  throw new Error(`temporal-fmt: getOffsetNanoseconds() expected a ZonedDateTime, got ${typeof value}.`);\n}\n\n// DST detection: a ZonedDateTime is in DST iff the offset is different\n// from the timezone's standard offset at the same instant. The standard\n// offset is the SMALLER of the zone's Jan 1 and Jul 1 offsets of the\n// same year — DST always shifts toward the sun-facing hemisphere, so\n// whichever of the two mid-winter/mid-summer probes has the smaller\n// offset is standard time, regardless of which hemisphere the zone is\n// in. (The old January-only comparison assumed northern hemisphere and\n// was inverted year-round for Australia/NZ/South America/southern\n// Africa: Sydney in December (AEDT, genuinely DST) reported false,\n// Sydney in July (AEST, standard) reported true.)\nexport function isDST(value: unknown): boolean {\n  const v = value as { timeZoneId?: string; offset?: string; year?: number; toInstant?: () => unknown };\n  if (typeof v?.timeZoneId !== 'string' || typeof v?.offset !== 'string' || typeof v?.year !== 'number') {\n    throw new Error(`temporal-fmt: isDST() expected a ZonedDateTime, got ${typeof value}.`);\n  }\n  const temporal = getTemporal();\n  try {\n    const options = { disambiguation: 'compatible' } as unknown as Parameters<typeof temporal.ZonedDateTime.from>[1];\n    const jan = temporal.ZonedDateTime.from(\n      { year: v.year, month: 1, day: 1, hour: 12, timeZone: v.timeZoneId }, options,\n    ) as { offset: string; offsetNanoseconds?: bigint };\n    const jul = temporal.ZonedDateTime.from(\n      { year: v.year, month: 7, day: 1, hour: 12, timeZone: v.timeZoneId }, options,\n    ) as { offset: string; offsetNanoseconds?: bigint };\n    // Standard = the smaller of the two offsets. If they're equal the\n    // zone has no DST at all — never in DST. Both arms are normalized to\n    // SECONDS: the offsetNanoseconds path divides by 1e9 (exact for real\n    // zones, whose offsets are whole seconds), so the string-offset\n    // fallback below compares like with like — the two paths used to mix\n    // seconds and nanoseconds, which could never compare equal on the\n    // fallback path and made every non-equal-offset zone read as \"in DST\".\n    const janOff = jan.offsetNanoseconds !== undefined ? Number(jan.offsetNanoseconds) / 1e9 : offsetToSeconds(jan.offset);\n    const julOff = jul.offsetNanoseconds !== undefined ? Number(jul.offsetNanoseconds) / 1e9 : offsetToSeconds(jul.offset);\n    if (janOff === julOff) return false;\n    const standardOff = Math.min(janOff, julOff);\n    return offsetToSeconds(v.offset) !== standardOff;\n  } catch {\n    return false;\n  }\n}\n\n// Parses \"+HH:MM\" (with optional \":SS\" or \".ffffff\" tail) into seconds.\n// Used by isDST's string-offset fallback when the Temporal\n// implementation doesn't expose offsetNanoseconds.\nfunction offsetToSeconds(offset: string): number {\n  const m = /^([+-])(\\d{2}):(\\d{2})(?::(\\d{2}))?(?:\\.\\d+)?$/.exec(offset);\n  if (!m) return 0;\n  const sign = m[1] === '-' ? -1 : 1;\n  return sign * (Number(m[2]) * 3600 + Number(m[3]) * 60 + Number(m[4] ?? 0));\n}\n\n// Returns the next DST transition strictly after `value`, or undefined\n// if no transition occurs within the next 2 years. Implemented by\n// walking day-by-day checking for offset changes — slow but simple,\n// and correct across all IANA zones.\nexport function getNextTransition(value: unknown): unknown | undefined {\n  return findTransition(value, 1);\n}\n\nexport function getPreviousTransition(value: unknown): unknown | undefined {\n  return findTransition(value, -1);\n}\n\nfunction findTransition(value: unknown, direction: 1 | -1): unknown | undefined {\n  const v = value as { timeZoneId?: string; offset?: string; toInstant?: () => unknown; year?: number; month?: number; day?: number; hour?: number; minute?: number; second?: number; millisecond?: number };\n  if (typeof v?.timeZoneId !== 'string') {\n    throw new Error(`temporal-fmt: ${direction > 0 ? 'getNextTransition' : 'getPreviousTransition'}() expected a ZonedDateTime, got ${typeof value}.`);\n  }\n  const temporal = getTemporal();\n  const timeZone = v.timeZoneId;\n  let candidateFields = add(value, direction, 'days');\n  // Duck-typed input with no `offset` used to hit a non-null lie\n  // (`v.offset!`) and find a spurious \"transition\" on the first\n  // candidate day; derive the real starting offset instead.\n  const startOffset = typeof v.offset === 'string'\n    ? v.offset\n    : (() => {\n        try {\n          return (temporal.ZonedDateTime.from(\n            { year: v.year, month: v.month, day: v.day, hour: v.hour ?? 12, timeZone },\n            { disambiguation: 'compatible' } as unknown as Parameters<typeof temporal.ZonedDateTime.from>[1],\n          ) as { offset: string }).offset;\n        } catch {\n          return undefined;\n        }\n      })();\n  if (startOffset === undefined) return undefined;\n  for (let i = 0; i < 365 * 2; i++) {\n    // Rebuild a real ZonedDateTime for this candidate day, in this\n    // timezone, so `.offset` reflects the actual UTC offset on that\n    // day rather than being absent. add() only produces a plain field\n    // bag (it has no notion of timezone), so re-attaching timeZone via\n    // ZonedDateTime.from is what actually lets us detect a DST change\n    // here — using the field bag's own (nonexistent) offset would make\n    // every call \"find\" a transition on the very first day checked.\n    const cf = candidateFields as { year: number; month: number; day: number; hour: number; minute: number; second: number; millisecond: number };\n    const candidateZdt = temporal.ZonedDateTime.from(\n      { ...cf, timeZone },\n      { disambiguation: 'compatible' } as unknown as Parameters<typeof temporal.ZonedDateTime.from>[1],\n    ) as { offset: string; year: number; month: number; day: number; hour: number; minute: number; second: number; millisecond: number };\n    if (candidateZdt.offset !== startOffset) {\n      // Found a transition day. Bisect the actual transition instant\n      // within the day: the day-before/day-of boundary is somewhere in\n      // the 24h before this candidate. Stepping the reconstruction at\n      // the input's wall-clock time used to return \"2026-03-08T12:00\"\n      // for a spring-forward that actually happens at 02:00 — the\n      // right day, ten hours late.\n      return bisectTransition(temporal, timeZone, candidateZdt, startOffset, direction);\n    }\n    candidateFields = add(candidateFields, direction, 'days');\n  }\n  return undefined;\n}\n\n// Narrows a transition down to the actual boundary minute by binary\n// search over a 24-hour window, probed via a minute-index cursor.\n// `direction` is 1 when scanning forward: the transition lies inside\n// `day` (whose 12:00 already shows the new offset), so the window is\n// [day 00:00, day 24:00). `direction` is -1 when scanning backward:\n// `day` is the last day whose 12:00 still shows the OLD offset, so the\n// transition lies in (day 12:00, day+1 12:00]. Returns a ZonedDateTime\n// at the first minute on the new side. (The old code returned the\n// candidate day reconstructed at the INPUT's wall-clock time — e.g.\n// \"2026-03-08T12:00\" for a spring-forward that happens at 02:00.)\nfunction bisectTransition(\n  temporal: TemporalNamespace,\n  timeZone: string,\n  day: { year: number; month: number; day: number; offset: string },\n  beforeOffset: string,\n  direction: 1 | -1,\n): unknown {\n  const zonedFrom = temporal.ZonedDateTime.from.bind(temporal.ZonedDateTime) as (f: unknown, o?: unknown) => unknown;\n  const options = { disambiguation: 'compatible' } as unknown as Parameters<typeof temporal.ZonedDateTime.from>[1];\n  // Window anchor: midnight of `day` for forward scans; noon of `day`\n  // for backward scans (the day's noon is known to still be old-side).\n  const windowStart = direction > 0\n    ? { year: day.year, month: day.month, day: day.day, hour: 0, minute: 0 }\n    : { year: day.year, month: day.month, day: day.day, hour: 12, minute: 0 };\n  // Minute m of the window → wall-clock fields via add() (handles\n  // rolling past midnight at the window's end).\n  const fieldsAt = (m: number) => add(windowStart, m, 'minutes') as { year: number; month: number; day: number; hour: number; minute: number };\n  const offsetAt = (m: number): string | undefined => {\n    try {\n      const f = fieldsAt(m);\n      return (zonedFrom({ ...f, timeZone }, options) as { offset: string }).offset;\n    } catch {\n      return undefined;\n    }\n  };\n  // The old side's offset: `beforeOffset` for forward scans, `day`'s own\n  // (still-old) offset for backward scans.\n  const oldOffset = direction > 0 ? beforeOffset : day.offset;\n  // Binary search over minutes [0, 1440): find the first minute whose\n  // offset differs from oldOffset. Unresolvable probes count as\n  // old-side so the search converges to a real boundary.\n  let lo = 0;\n  let hi = 1440;\n  while (hi - lo > 1) {\n    const mid = Math.floor((lo + hi) / 2);\n    const off = offsetAt(mid);\n    if (off === undefined || off === oldOffset) lo = mid;\n    else hi = mid;\n  }\n  // `hi` is the first new-side minute (1440 = the boundary exactly at\n  // the window's end — normalize to the following midnight).\n  const boundary = hi >= 1440 ? fieldsAt(1439) : fieldsAt(hi);\n  try {\n    return zonedFrom({\n      year: boundary.year, month: boundary.month, day: boundary.day,\n      hour: boundary.hour, minute: boundary.minute, timeZone,\n    }, options);\n  } catch {\n    return day;\n  }\n}\n\nexport function getTransitions(start: unknown, end: unknown): unknown[] {\n  const result: unknown[] = [];\n  const startV = start as { timeZoneId?: string; offset?: string; year?: number; month?: number; day?: number };\n  if (typeof startV?.timeZoneId !== 'string') {\n    throw new Error(`temporal-fmt: getTransitions() expected a ZonedDateTime for start, got ${typeof start}.`);\n  }\n  // `end` used to be dereferenced raw (`endV.year`) with no guard —\n  // passing undefined crashed with a bare V8 TypeError.\n  const endV = end as { year?: number; month?: number; day?: number };\n  if (typeof endV?.year !== 'number' || typeof endV?.month !== 'number' || typeof endV?.day !== 'number') {\n    throw new Error(`temporal-fmt: getTransitions() expected a date-carrying value for end, got ${typeof end}.`);\n  }\n  const endYear = endV.year, endMonth = endV.month, endDay = endV.day;\n  const temporal = getTemporal();\n  const timeZone = startV.timeZoneId;\n  let cursorFields = add(start, 1, 'days');\n  let lastOffset = startV.offset!;\n  for (let i = 0; i < 365 * 5; i++) {\n    // Same reconstruction as findTransition() above — add() strips\n    // timezone/offset info, so we rebuild a real ZonedDateTime each\n    // iteration to read its actual offset instead of comparing against\n    // a field bag that never has one.\n    const cf = cursorFields as { year: number; month: number; day: number; hour: number; minute: number; second: number; millisecond: number };\n    const cursorZdt = temporal.ZonedDateTime.from(\n      { ...cf, timeZone },\n      { disambiguation: 'compatible' } as unknown as Parameters<typeof temporal.ZonedDateTime.from>[1],\n    ) as { offset: string; year: number; month: number; day: number };\n    if (cursorZdt.offset !== lastOffset) {\n      // Found a transition.\n      if (cursorZdt.year > endYear || (cursorZdt.year === endYear && (cursorZdt.month > endMonth || (cursorZdt.month === endMonth && cursorZdt.day > endDay)))) break;\n      result.push(cursorZdt);\n      lastOffset = cursorZdt.offset;\n    }\n    cursorFields = add(cursorFields, 1, 'days');\n  }\n  return result;\n}\n\n// Returns the list of possible instants for a wall-clock time in a\n// zone — used to detect gaps (0 instants) and overlaps (2 instants).\nexport function possibleInstantsFor(\n  fields: { year: number; month: number; day: number; hour: number; minute: number; second: number; millisecond: number },\n  timeZone: string,\n): unknown[] {\n  const temporal = getTemporal();\n  // Resolve the same wall-clock fields twice, forcing disambiguation\n  // toward the earlier and later side of any DST boundary. Comparing\n  // the two results tells us which of the three cases we're in:\n  //  - gap (e.g. 2:30am on a spring-forward day): neither result's own\n  //    wall-clock fields match what was requested, since Temporal has\n  //    to shift off the nonexistent time in both directions — 0 instants.\n  //  - overlap (e.g. 1:30am on a fall-back day): both results keep the\n  //    requested wall-clock time but land on different instants (one\n  //    per side of the boundary) — 2 instants.\n  //  - normal time: both results match the requested wall-clock time\n  //    and resolve to the same instant — 1 instant.\n  const earlier = temporal.ZonedDateTime.from(\n    { ...fields, timeZone },\n    { disambiguation: 'earlier', offset: 'ignore' } as unknown as Parameters<typeof temporal.ZonedDateTime.from>[1],\n  ) as { year: number; month: number; day: number; hour: number; minute: number; second: number; millisecond: number; toInstant: () => { epochNanoseconds: bigint } };\n  const later = temporal.ZonedDateTime.from(\n    { ...fields, timeZone },\n    { disambiguation: 'later', offset: 'ignore' } as unknown as Parameters<typeof temporal.ZonedDateTime.from>[1],\n  ) as { year: number; month: number; day: number; hour: number; minute: number; second: number; millisecond: number; toInstant: () => { epochNanoseconds: bigint } };\n\n  const matchesRequestedWallClock = (z: typeof earlier) =>\n    z.year === fields.year && z.month === fields.month && z.day === fields.day &&\n    z.hour === fields.hour && z.minute === fields.minute &&\n    z.second === fields.second && z.millisecond === fields.millisecond;\n\n  if (!matchesRequestedWallClock(earlier) || !matchesRequestedWallClock(later)) {\n    // Gap — the requested wall-clock time doesn't exist in this zone.\n    return [];\n  }\n  if (earlier.toInstant().epochNanoseconds === later.toInstant().epochNanoseconds) {\n    // Normal time — both disambiguation directions agree on the instant.\n    return [earlier];\n  }\n  // Overlap — same wall-clock time, two distinct instants.\n  return [earlier, later];\n}","/*\n * Copyright 2026 DirazCoder\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// tsconfig here is lib: [\"ESNext\"] only, so there's no ambient Temporal\n// namespace type to lean on. everywhere else in the codebase we just read\n// fields off whatever Temporal-like object gets passed in (see TemporalLike\n// in tokens.ts) but this file is the one place that actually touches the\n// Temporal namespace itself — PlainDate.from and friends. parse() uses it\n// to build results, tokens.ts uses it to check native Intl<->Temporal\n// support. you can hand us your own implementation via setTemporal(), or\n// we just grab globalThis.Temporal if there is one\ninterface TemporalFactory {\n  from(fields: Record<string, number | string | undefined>, options?: { overflow?: 'constrain' | 'reject'; disambiguation?: 'compatible' | 'earlier' | 'later' | 'reject'; offset?: 'use' | 'ignore' | 'prefer' | 'reject' }): unknown;\n  // compare() is on the namespace, not instances (Temporal.PlainDate.compare).\n  // made optional since someone might hand us a stripped-down shim that\n  // doesn't bother implementing it\n  compare?(one: unknown, two: unknown): number;\n}\n\n// Instant doesn't use from(fields) like the others, it's\n// fromEpochMilliseconds / fromEpochNanoseconds. needs its own shape.\ninterface InstantFactory {\n  from(iso: string): unknown;\n  fromEpochMilliseconds(ms: number): unknown;\n  fromEpochMicroseconds(µs: number): unknown;\n  fromEpochNanoseconds(ns: bigint): unknown;\n}\n\n// Duration uses from(fields) too, but also has round() and compare()\ninterface DurationFactory extends TemporalFactory {\n  compare?(one: unknown, two: unknown): number;\n  prototype?: { round(options: unknown): unknown };\n}\n\n// PlainYearMonth / PlainMonthDay also just use from(fields) — same shape\n// as TemporalFactory really, kept as its own type so callers can narrow\nexport interface TemporalNamespace {\n  PlainDate: TemporalFactory;\n  PlainTime: TemporalFactory;\n  PlainDateTime: TemporalFactory;\n  ZonedDateTime: TemporalFactory;\n  Instant?: InstantFactory;\n  Duration?: DurationFactory;\n  PlainYearMonth?: TemporalFactory;\n  PlainMonthDay?: TemporalFactory;\n}\n\nlet injectedTemporal: TemporalNamespace | undefined;\n\n// anything caching something tied to WHICH Temporal impl is active\n// (right now just tokens.ts's native-Intl probe) registers a listener\n// here so it knows to invalidate when setTemporal() swaps things out —\n// see setTemporal() below for why that matters. kept this as a plain\n// array instead of a full event emitter since all we need is \"call\n// everyone back, in order, no payload\" — didn't need unsubscribe either\nconst onTemporalChanged: Array<() => void> = [];\n\nexport function subscribeToTemporalChanges(listener: () => void): void {\n  onTemporalChanged.push(listener);\n}\n\n/**\n * Explicitly hand temporal-fmt the Temporal implementation to use, instead\n * of relying on a global `Temporal`. Call this once, before your first\n * `format()`/`parse()`/`parseISO()`/etc.\n *\n * Call with no argument (or `undefined`) to clear the override and fall\n * back to `globalThis.Temporal` again.\n *\n * @example\n * import { Temporal } from 'temporal-polyfill';\n * import { setTemporal } from 'temporal-fmt';\n * setTemporal(Temporal);\n */\nexport function setTemporal(temporal?: TemporalNamespace): void {\n  injectedTemporal = temporal;\n  // tokens.ts caches its native-Intl probe result based on whatever\n  // Temporal was active the first time it ran. if that changes later\n  // (native -> polyfill, say) the cached result goes stale. so just reset\n  // everyone on any setTemporal() call — costs one extra probe re-run,\n  // worth it to not silently use a stale answer\n  for (const listener of onTemporalChanged) listener();\n}\n\nfunction resolveTemporal(): TemporalNamespace | undefined {\n  return injectedTemporal ?? (globalThis as unknown as { Temporal?: TemporalNamespace }).Temporal;\n}\n\nexport function getTemporal(): TemporalNamespace {\n  const temporal = resolveTemporal();\n  if (!temporal) {\n    throw new Error(\n      'temporal-fmt: parse() needs a Temporal implementation to construct its result. ' +\n      'Call setTemporal(Temporal) once at startup, or assign one to globalThis.Temporal ' +\n      '(native on Node 26+, or a polyfill like temporal-polyfill).'\n    );\n  }\n  return temporal;\n}\n","/*\n * Copyright 2026 DirazCoder\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// ISO week stuff. week runs Mon-Sun, and week 1 is whichever week has\n// the year's first Thursday in it (same as saying \"the week with Jan 4\").\n// took me a minute to wrap my head around this but the upshot is late-Dec\n// dates can land in week 1 of NEXT year, and early-Jan dates can land in\n// week 52/53 of the PREVIOUS year. that adjacent year is what RRRR prints,\n// not the plain calendar year.\n//\n// doing this with plain year/month/day + dayOfWeek math instead of asking\n// Temporal for it, since format() only has whatever fields got handed in\n// and dragging in a whole Temporal implementation just for week numbers\n// felt like overkill (also breaks for people not on setTemporal()).\n\nconst DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\nconst CUMULATIVE_DAYS_BY_MONTH = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];\n\nexport function isGregorianLeapYear(year: number): boolean {\n  // divisible by 4, unless it's a century, then it also needs /400.\n  // Temporal's iso8601 calendar never switches to Julian, so this rule\n  // just applies all the way back, even for BCE years.\n  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n}\n\nfunction daysInYear(year: number): 365 | 366 {\n  return isGregorianLeapYear(year) ? 366 : 365;\n}\n\nexport function dayOfYear(year: number, month: number, day: number): number {\n  let doy = CUMULATIVE_DAYS_BY_MONTH[month - 1]! + day;\n  if (month > 2 && isGregorianLeapYear(year)) doy += 1;\n  return doy;\n}\n\n// Jan 1 2000 was a Saturday (ISO dow 6). picked this as an anchor point\n// since it's easier than reaching for Zeller's congruence every time,\n// and obviously this fact about Jan 1 2000 isn't going to change on us\nconst REFERENCE_YEAR = 2000;\nconst REFERENCE_JAN1_DAY_OF_WEEK = 6;\n\n// Howard Hinnant's days_from_civil: O(1) day count for a proleptic\n// Gregorian y/m/d, correct for negative years and year 0 (the (y2>=0?\n// y2 : y2-399)/400 offset form relies on truncating division, which JS\n// doesn't have — Math.floor on the *un-offset* numerator is the exact\n// JS equivalent, see the matching formulas in arithmetic.ts). Shared by\n// dayOfWeekOfJan1 and any caller needing days between two arbitrary\n// dates without a year-by-year walk (those walks were O(|year − 2000|)\n// per call — a field bag claiming year 2e8 hung formatDistance for\n// ~400ms per call and worse for bigger values).\nexport function daysFromCivil(year: number, month: number, day: number): number {\n  const y2 = month <= 2 ? year - 1 : year;\n  const era = Math.floor(y2 / 400);\n  const yoe = y2 - era * 400; // [0, 399]\n  const m2 = month > 2 ? month - 3 : month + 9; // [0, 11]\n  const doy = Math.floor((153 * m2 + 2) / 5) + day - 1; // [0, 365]\n  const doe = yoe * 365 + Math.floor(yoe / 4) - Math.floor(yoe / 100) + doy; // [0, 146096]\n  return era * 146097 + doe - 719468;\n}\n\n// Day of week (ISO, 1=Mon..7=Sun) for a proleptic Gregorian y/m/d, in\n// O(1). 1970-01-01 was a Thursday (dow 4), so dow = (days + 3) mod 7\n// shifted to 1..7. Replaces the Date.UTC(year, month-1, day) idiom used\n// elsewhere in this library, which silently remaps years 0-99 to\n// 1900-1999 per the ECMAScript spec and produces the wrong weekday for\n// first-century dates.\nexport function dayOfWeekFromCivil(year: number, month: number, day: number): number {\n  const days = daysFromCivil(year, month, day);\n  // days=0 is 1970-01-01 (Thursday, dow 4): (0 + 3) % 7 = 3 → 4 ✓\n  return (((days + 3) % 7) + 7) % 7 + 1;\n}\n\nfunction dayOfWeekOfJan1(year: number): number {\n  // O(1) via daysFromCivil: Jan 1 of `year` is `days` after Jan 1 2000\n  // (a Saturday, dow 6), so dow = (6 - 1 + days) mod 7, bumped to 1-indexed.\n  // The old year-by-year walk from 2000 was O(|year − 2000|) — correct\n  // but linear, and unbounded for hostile field-bag years.\n  const days = daysFromCivil(year, 1, 1) - daysFromCivil(REFERENCE_YEAR, 1, 1);\n  const zeroIndexed = (((REFERENCE_JAN1_DAY_OF_WEEK - 1 + days) % 7) + 7) % 7;\n  return zeroIndexed + 1;\n}\n\nexport interface IsoWeekDate {\n  isoYear: number;\n  week: number; // goes 1 to 53\n}\n\nexport function isoWeekYearAndWeek(year: number, month: number, day: number, dayOfWeek: number): IsoWeekDate {\n  // step 1: figure out the Thursday of this week — whatever calendar year\n  // that Thursday's in IS the ISO week-numbering year. doing this with\n  // day-of-year offsets so we don't need an actual Temporal.PlainDate here\n  const doy = dayOfYear(year, month, day);\n  const thursdayDoyRelative = doy + (4 - dayOfWeek); // can go negative or past daysInYear, that's fine\n\n  let isoYear: number;\n  let thursdayDoy: number;\n  if (thursdayDoyRelative < 1) {\n    isoYear = year - 1;\n    thursdayDoy = thursdayDoyRelative + daysInYear(isoYear);\n  } else if (thursdayDoyRelative > daysInYear(year)) {\n    isoYear = year + 1;\n    thursdayDoy = thursdayDoyRelative - daysInYear(year);\n  } else {\n    isoYear = year;\n    thursdayDoy = thursdayDoyRelative;\n  }\n\n  // step 2: find the first Thursday of isoYear, that one's week 1 by definition.\n  // depends entirely on which weekday Jan 1 lands on\n  const jan1Dow = dayOfWeekOfJan1(isoYear);\n  const firstThursdayDoy = 1 + ((4 - jan1Dow + 7) % 7); // always lands somewhere 1-7\n\n  // step 3: just count how many full weeks between the two Thursdays\n  const week = 1 + Math.floor((thursdayDoy - firstThursdayDoy) / 7);\n  return { isoYear, week };\n}\n","/*\n * Copyright 2026 DirazCoder\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Calendar utility helpers. These are pure functions\n// over the TemporalLike shape — no Temporal namespace needed, same\n// approach as isoWeek.ts and the field-reading helpers in format.ts.\n// Letting callers compute dayOfYear/weekOfYear/etc. without going\n// through format() means they can build their own derived values\n// without committing to a string format.\n//\n// Calendar-sensitivity: the helpers in this module assume the\n// iso8601 (Gregorian) calendar — that's what TemporalLike fields\n// carry for the overwhelming majority of callers. Non-Gregorian\n// calendars (hebrew, islamic, etc.) need their own helpers; this\n// module doesn't try to be calendar-polymorphic the way Temporal\n// itself is. Documented limitation, not a design choice — see\n// VERIFICATION.md for the rationale.\n\nimport { isGregorianLeapYear, dayOfYear, isoWeekYearAndWeek, dayOfWeekFromCivil } from './isoWeek.js';\n\n// A subset of TemporalLike that has the date fields these helpers need,\n// plus optional time fields. PlainTime isn't a DateFieldView (no\n// year/month/day), but PlainDateTime / ZonedDateTime / PlainDate all\n// match. Time fields are optional so callers can pass a PlainDate\n// to startOf(value, 'month') without having to populate hour/minute/etc.\n// Exported so the comparison/arithmetic modules can use the same\n// narrowing.\nexport interface DateFieldView {\n  year?: number;\n  month?: number;\n  day?: number;\n  hour?: number;\n  minute?: number;\n  second?: number;\n  millisecond?: number;\n  dayOfWeek?: number;\n  calendarId?: string;\n}\n\nfunction requireFields(view: DateFieldView, fields: Array<keyof DateFieldView>): void {\n  for (const f of fields) {\n    if (typeof view[f] !== 'number') {\n      throw new Error(\n        `temporal-fmt: calendar helper requires \"${String(f)}\", which this value doesn't have. ` +\n        `Pass a Temporal.PlainDate / PlainDateTime / ZonedDateTime.`\n      );\n    }\n  }\n}\n\nexport function daysInMonth(view: DateFieldView): number {\n  requireFields(view, ['year', 'month']);\n  const { year, month } = view;\n  // Standard Gregorian month lengths. February's length depends on\n  // whether `year` is a leap year — the same isGregorianLeapYear check\n  // isoWeek.ts uses for dayOfYear arithmetic.\n  const LENGTHS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n  if (month === 2 && isGregorianLeapYear(year!)) return 29;\n  return LENGTHS[(month! - 1)!]!;\n}\n\nexport function daysInYear(view: DateFieldView): 365 | 366 {\n  requireFields(view, ['year']);\n  return isGregorianLeapYear(view.year!) ? 366 : 365;\n}\n\nexport function monthsInYear(_view: DateFieldView): 12 {\n  // Gregorian always has 12 months. Other calendars (Hebrew leap years\n  // have 13) need calendar-aware logic this module doesn't carry — see\n  // the file-level comment. The `_view` parameter is kept so the\n  // signature mirrors the other helpers and a future calendar-aware\n  // implementation can use it without changing call sites.\n  return 12;\n}\n\nexport function isLeapYear(view: DateFieldView): boolean {\n  requireFields(view, ['year']);\n  return isGregorianLeapYear(view.year!);\n}\n\n// `isLeapMonth` would require knowing which month of a leap-year-aware\n// calendar is the leap month — Gregorian doesn't have one, so this\n// returns false unconditionally. Kept here so the public surface\n// matches the module's listing; non-Gregorian calendars need\n// a different implementation.\nexport function isLeapMonth(_view: DateFieldView): boolean {\n  return false;\n}\n\nexport function dayOfYearHelper(view: DateFieldView): number {\n  requireFields(view, ['year', 'month', 'day']);\n  return dayOfYear(view.year!, view.month!, view.day!);\n}\n\n// ISO 8601 week and week-year. Delegates to isoWeek.ts's\n// isoWeekYearAndWeek, which does the full Thursday-of-week\n// computation to handle the year-boundary cases (Dec 29-31 belonging\n// to week 1 of next year, Jan 1-3 belonging to week 52/53 of the\n// previous year).\nexport function weekOfYear(view: DateFieldView): number {\n  requireFields(view, ['year', 'month', 'day', 'dayOfWeek']);\n  return isoWeekYearAndWeek(view.year!, view.month!, view.day!, view.dayOfWeek!).week;\n}\n\nexport function weekYear(view: DateFieldView): number {\n  requireFields(view, ['year', 'month', 'day', 'dayOfWeek']);\n  return isoWeekYearAndWeek(view.year!, view.month!, view.day!, view.dayOfWeek!).isoYear;\n}\n\n/**\n * Fiscal-quarter options. `startMonth` is the calendar month (1-12) the\n * fiscal year begins on — e.g. `7` for a fiscal year starting in July.\n * Omitted or `1` gives the calendar-quarter behavior getQuarter() has\n * always had (Jan-Mar = Q1, etc.), so existing callers passing nothing\n * see no change.\n */\nexport interface QuarterOptions {\n  startMonth?: number;\n}\n\nfunction validateStartMonth(startMonth: number): void {\n  if (!Number.isInteger(startMonth) || startMonth < 1 || startMonth > 12) {\n    throw new Error(\n      `temporal-fmt: getQuarter's startMonth must be an integer from 1 to 12 (got ${startMonth}).`\n    );\n  }\n}\n\nexport function getQuarter(view: DateFieldView, options: QuarterOptions = {}): number {\n  requireFields(view, ['month']);\n  const startMonth = options.startMonth ?? 1;\n  validateStartMonth(startMonth);\n  if (startMonth === 1) {\n    // Mirrors the Q token: months 1-3 → Q1, 4-6 → Q2, 7-9 → Q3, 10-12 → Q4.\n    return Math.ceil(view.month! / 3);\n  }\n  // Fiscal case: shift the month so startMonth becomes month 1 of the\n  // fiscal year (mod 12, 1-indexed), then apply the same ceil(/3) rule.\n  // E.g. startMonth=7 (fiscal year starts July): July→1, Aug→2, ...,\n  // Dec→6, Jan→7, ..., June→12. Then Q1 = fiscal months 1-3 (Jul-Sep),\n  // matching the common \"FY starts in July\" convention where Q1 is the\n  // first quarter of the fiscal year, not a quarter numbered by which\n  // calendar quarter it falls in.\n  const shifted = ((view.month! - startMonth + 12) % 12) + 1;\n  return Math.ceil(shifted / 3);\n}\n\n// `getMonth` / `getWeekday` look trivial (just read the field) but\n// they're kept as real functions for API surface consistency with the\n// rest of this module. They also normalize: getWeekday returns 1-7\n// (Mon-Sun, matching Temporal's spec) regardless of what numbering the\n// caller's underlying value uses.\nexport function getMonth(view: DateFieldView): number {\n  requireFields(view, ['month']);\n  return view.month!;\n}\n\nexport function getWeekday(view: DateFieldView): number {\n  requireFields(view, ['dayOfWeek']);\n  return view.dayOfWeek!;\n}\n\n// startOf / endOf return new field bags (not Temporal objects — this\n// module is polyfill-free) with the relevant fields zeroed/extended.\n// Callers can pass the result to a Temporal constructor if they want\n// a typed value.\nexport type StartOfUnit = 'day' | 'month' | 'year' | 'hour' | 'minute' | 'second';\n\n// Returns true if the given unit (when used with startOf/endOf) should\n// also touch the time fields. 'day', 'month', 'year' all imply a\n// resolution coarser than an hour, so startOf zeroes the time fields\n// and endOf maxes them. Sub-hour units (hour/minute/second) only touch\n// the fields finer than themselves.\nfunction touchesTime(unit: StartOfUnit): boolean {\n  return unit === 'day' || unit === 'month' || unit === 'year';\n}\n\n// startOf/endOf reassign year/month/day, which invalidates any\n// dayOfWeek carried over from the input — a plain { ...view } spread\n// leaves the old value sitting there unchanged. Same failure mode\n// businessCalendar.ts's isBusinessDay() works around for add(); we\n// recompute here rather than trust the copied field.\nfunction recomputeDayOfWeek(view: DateFieldView): void {\n  if (typeof view.dayOfWeek !== 'number') return;\n  /* c8 ignore start @preserve -- unreachable: startOf()/endOf() both call\n   * asDateFieldView() before this, which already throws if year/month/day\n   * aren't all numbers — so by the time a value with a numeric dayOfWeek\n   * reaches here, year/month/day are guaranteed present too. */\n  if (typeof view.year !== 'number' || typeof view.month !== 'number' || typeof view.day !== 'number') return;\n  /* c8 ignore stop @preserve */\n  // dayOfWeekFromCivil: O(1) proleptic-Gregorian weekday. The old\n  // Date.UTC(year, month-1, day) form remapped years 0-99 to 1900-1999\n  // (ECMAScript spec), so startOf/endOf of a first-century date carried\n  // a weekday from the wrong century.\n  view.dayOfWeek = dayOfWeekFromCivil(view.year, view.month, view.day);\n}\n\nexport function startOf(value: unknown, unit: StartOfUnit): DateFieldView {\n  const view = asDateFieldView(value);\n  const result: DateFieldView = { ...view };\n  if (unit === 'year') {\n    result.month = 1;\n    result.day = 1;\n  } else if (unit === 'month') {\n    result.day = 1;\n  }\n  recomputeDayOfWeek(result);\n  if (touchesTime(unit)) {\n    result.hour = 0;\n    result.minute = 0;\n    result.second = 0;\n    result.millisecond = 0;\n  } else if (unit === 'hour') {\n    result.minute = 0;\n    result.second = 0;\n    result.millisecond = 0;\n  } else if (unit === 'minute') {\n    result.second = 0;\n    result.millisecond = 0;\n  } else if (unit === 'second') {\n    result.millisecond = 0;\n  }\n  return result;\n}\n\nexport function endOf(value: unknown, unit: StartOfUnit): DateFieldView {\n  const view = asDateFieldView(value);\n  const result: DateFieldView = { ...view };\n  if (unit === 'year') {\n    result.month = 12;\n    result.day = daysInMonth({ year: result.year!, month: 12 });\n  } else if (unit === 'month') {\n    result.day = daysInMonth({ year: result.year!, month: result.month! });\n  }\n  recomputeDayOfWeek(result);\n  if (touchesTime(unit)) {\n    result.hour = 23;\n    result.minute = 59;\n    result.second = 59;\n    result.millisecond = 999;\n  } else if (unit === 'hour') {\n    result.minute = 59;\n    result.second = 59;\n    result.millisecond = 999;\n  } else if (unit === 'minute') {\n    result.second = 59;\n    result.millisecond = 999;\n  } else if (unit === 'second') {\n    result.millisecond = 999;\n  }\n  return result;\n}\n\n// Type-narrowing helpers used by the comparison/arithmetic modules.\n// Lets them accept any of the four date-carrying Temporal types without\n// importing Temporal itself.\nexport function asDateFieldView(value: unknown): DateFieldView {\n  if (typeof value !== 'object' || value === null) {\n    throw new Error(`temporal-fmt: expected a date-carrying Temporal value, got ${String(value)}.`);\n  }\n  // Temporal instances expose year/month/day/etc. as prototype getters,\n  // not own enumerable properties — so `{ ...value }` would lose them.\n  // Read them explicitly. Only the fields actually present on this\n  // value type end up in the returned view.\n  const v = value as Record<string, unknown>;\n  const out: DateFieldView = {};\n  if (typeof v.year === 'number') out.year = v.year;\n  if (typeof v.month === 'number') out.month = v.month;\n  if (typeof v.day === 'number') out.day = v.day;\n  if (typeof v.hour === 'number') out.hour = v.hour;\n  if (typeof v.minute === 'number') out.minute = v.minute;\n  if (typeof v.second === 'number') out.second = v.second;\n  if (typeof v.millisecond === 'number') out.millisecond = v.millisecond;\n  if (typeof v.dayOfWeek === 'number') out.dayOfWeek = v.dayOfWeek;\n  if (typeof v.calendarId === 'string') out.calendarId = v.calendarId;\n  if (out.year === undefined || out.month === undefined || out.day === undefined) {\n    throw new Error(\n      `temporal-fmt: value is missing year/month/day fields — pass a Temporal.PlainDate / PlainDateTime / ZonedDateTime.`\n    );\n  }\n  return out;\n}\n\n// Re-export the TemporalType alias so callers can import everything\n// from one place.\nexport type { TemporalType } from './tokenMetadata.js';\n// Re-export TemporalLike for the same reason.\nexport type { TemporalLike } from './tokens.js';","/*\n * Copyright 2026 DirazCoder\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Date arithmetic helpers. Pure functions returning\n// field bags, same convention as calendarUtils.ts/comparison.ts — no\n// Temporal namespace needed. Callers can pass the result back into a\n// Temporal constructor to get a typed value, or chain operations\n// without committing to a Temporal implementation.\n\nimport { asDateFieldView, daysInMonth, type DateFieldView } from './calendarUtils.js';\nimport { dayOfWeekFromCivil, daysFromCivil } from './isoWeek.js';\n\nexport type AddUnit = 'years' | 'months' | 'weeks' | 'days' | 'hours' | 'minutes' | 'seconds' | 'milliseconds';\n\ninterface DateTimeFieldView extends DateFieldView {\n  hour?: number;\n  minute?: number;\n  second?: number;\n  millisecond?: number;\n}\n\nfunction asDateTime(value: unknown): DateTimeFieldView {\n  return asDateFieldView(value) as DateTimeFieldView;\n}\n\n// Recomputes dayOfWeek after year/month/day change. Mirrors\n// calendarUtils.ts's recomputeDayOfWeek — same fix, needed here too\n// since add()/subtract() mutate the date fields via a shallow spread\n// that otherwise leaves the old dayOfWeek sitting there, silently wrong.\nfunction recomputeDayOfWeek(view: DateTimeFieldView): void {\n  if (typeof view.dayOfWeek !== 'number') return;\n  /* c8 ignore start @preserve -- unreachable: every call site (add()'s\n     'years'/'months' cases, shiftDays()) passes a `result` whose\n     year/month/day were just explicitly set, and the value originally\n     came from asDateTime()/asDateFieldView(), which throws unless\n     year/month/day are all present as numbers. So by the time this guard\n     runs, all three are guaranteed valid. Kept in case a future caller\n     constructs a DateTimeFieldView bypassing that validation. */\n  if (typeof view.year !== 'number' || typeof view.month !== 'number' || typeof view.day !== 'number') return;\n  /* c8 ignore stop @preserve */\n  // dayOfWeekFromCivil: O(1) proleptic-Gregorian weekday. The old\n  // Date.UTC(year, month-1, day) form silently remaps years 0-99 to\n  // 1900-1999 (ECMAScript spec behavior), computing the weekday of the\n  // wrong century — e.g. add(PlainDate('0050-01-01'), 1, 'days') used\n  // to report dayOfWeek 1 (Mon) for a date that's a Sunday.\n  view.dayOfWeek = dayOfWeekFromCivil(view.year, view.month, view.day);\n}\n\n// Adds the requested amount to the value's specified unit. Returns a\n// new field bag; the input is not mutated. Handles month/year overflow\n// by clamping to the last valid day of the target month (Feb 29 + 1\n// year on a non-leap year → Feb 28) — Temporal's `constrain` overflow\n// mode, which is the closest match to \"do the obvious thing\" callers\n// expect from arithmetic.\nexport function add(value: unknown, amount: number, unit: AddUnit): DateTimeFieldView {\n  const v = asDateTime(value);\n  let result: DateTimeFieldView = { ...v };\n  switch (unit) {\n    case 'years': {\n      /* c8 ignore start @preserve -- the `?? 0` fallback is unreachable:\n         asDateTime()/asDateFieldView() (called at the top of add()) throws\n         unless year is present as a number, so result.year is never\n         undefined here. Kept as a guard against a future change that\n         relaxes that validation. */\n      result.year = (result.year ?? 0) + amount;\n      /* c8 ignore stop @preserve */\n      // Clamp day-of-month to the new month's length.\n      const maxDay = daysInMonth({ year: result.year!, month: result.month! });\n      if (result.day! > maxDay) result.day = maxDay;\n      recomputeDayOfWeek(result);\n      break;\n    }\n    case 'months': {\n      // Total months = year*12 + month + amount, then split back with\n      // floor division/modulo. JS's % keeps the sign of the dividend, so\n      // a hand-rolled negative-modulo fixup used to double-borrow the\n      // year for totals < 0: add(PlainDate('0001-01-15'), -13, 'months')\n      // returned year -2 / month 12 instead of Temporal's -0001-12-15\n      // (floorDiv already accounted for the borrow; the fixup took\n      // another year off on top).\n      /* c8 ignore start @preserve -- both `??` fallbacks are unreachable\n         for the same reason as the 'years' case above: asDateFieldView()\n         guarantees year and month are present numbers before add() ever\n         reaches here. */\n      const total = (result.year ?? 0) * 12 + (result.month ?? 1) - 1 + amount;\n      /* c8 ignore stop @preserve */\n      result.year = Math.floor(total / 12);\n      result.month = total - result.year * 12 + 1; // floorMod(total, 12) + 1, always in 1..12\n      const maxDay = daysInMonth({ year: result.year!, month: result.month! });\n      if (result.day! > maxDay) result.day = maxDay;\n      recomputeDayOfWeek(result);\n      break;\n    }\n    case 'weeks':\n      result = shiftDays(result, amount * 7);\n      break;\n    case 'days':\n      result = shiftDays(result, amount);\n      break;\n    case 'hours':\n      result = shiftTime(result, amount * 3_600_000);\n      break;\n    case 'minutes':\n      result = shiftTime(result, amount * 60_000);\n      break;\n    case 'seconds':\n      result = shiftTime(result, amount * 1_000);\n      break;\n    case 'milliseconds':\n      result = shiftTime(result, amount);\n      break;\n  }\n  return result;\n}\n\nfunction shiftDays(v: DateTimeFieldView, days: number): DateTimeFieldView {\n  // Convert Y/M/D to a day count, add, convert back. The forward\n  // direction uses isoWeek.ts's daysFromCivil — the era term previously\n  // inlined here applied Math.floor to Hinnant's -399-offset numerator,\n  // which double-corrects for negative years (the offset form assumes\n  // truncating division; JS's is flooring), shifting every pre-year-0\n  // date by one day. The inverse (civil_from_days) below is floor-safe\n  // as written (its out-of-range `doe` cases self-compensate through the\n  // yoe formula — property-tested over years -1000..3000, all months,\n  // round-trip identity holds).\n  const totalDays = daysFromCivil(v.year!, v.month!, v.day!) + days;\n\n  // Invert: totalDays → Y/M/D. Same source (Howard Hinnant's\n  // civil_from_days). The era term MUST use truncating division — the\n  // -146096 offset exists so that trunc lands the era correctly; with\n  // Math.floor every z < 0 came out one day early (the forward formula's\n  // matching error used to hide this on round-trips; now that the\n  // forward direction is exact, the inverse has to be too).\n  const z = totalDays + 719468;\n  const era2 = Math.trunc((z >= 0 ? z : z - 146096) / 146097);\n  const doe2 = z - era2 * 146097;\n  const yoe2 = Math.floor((doe2 - Math.floor(doe2 / 1460) + Math.floor(doe2 / 36524) - Math.floor(doe2 / 146096)) / 365);\n  const y2out = yoe2 + era2 * 400;\n  const doy2 = doe2 - (365 * yoe2 + Math.floor(yoe2 / 4) - Math.floor(yoe2 / 100));\n  const mp = Math.floor((5 * doy2 + 2) / 153);\n  const d2 = doy2 - Math.floor((153 * mp + 2) / 5) + 1;\n  const m2out = mp < 10 ? mp + 3 : mp - 9;\n  const yOut = m2out <= 2 ? y2out + 1 : y2out;\n\n  const result: DateTimeFieldView = { ...v, year: yOut, month: m2out, day: d2 };\n  recomputeDayOfWeek(result);\n  return result;\n}\n\nfunction shiftTime(v: DateTimeFieldView, msDelta: number): DateTimeFieldView {\n  // Convert all time fields to ms, add, then split back. Day overflow\n  // propagates to shiftDays; sub-second precision is preserved (caller\n  // asking for hours/minutes/seconds/milliseconds gets ms-resolution\n  // arithmetic, which is the limit of these helpers — nanoseconds\n  // aren't supported here, only via Temporal.Duration's own add).\n  const MS_PER_DAY = 86_400_000;\n  const MS_PER_HOUR = 3_600_000;\n  const MS_PER_MINUTE = 60_000;\n  const MS_PER_SECOND = 1_000;\n\n  const totalMs = (v.hour ?? 0) * MS_PER_HOUR\n    + (v.minute ?? 0) * MS_PER_MINUTE\n    + (v.second ?? 0) * MS_PER_SECOND\n    + (v.millisecond ?? 0)\n    + msDelta;\n\n  // Split into day-overflow + within-day ms.\n  const dayOverflow = Math.floor(totalMs / MS_PER_DAY);\n  let withinDay = totalMs % MS_PER_DAY;\n  if (withinDay < 0) { withinDay += MS_PER_DAY; }\n\n  const hour = Math.floor(withinDay / MS_PER_HOUR);\n  const minute = Math.floor((withinDay % MS_PER_HOUR) / MS_PER_MINUTE);\n  const second = Math.floor((withinDay % MS_PER_MINUTE) / MS_PER_SECOND);\n  const millisecond = withinDay % MS_PER_SECOND;\n\n  const result: DateTimeFieldView = { ...v, hour, minute, second, millisecond };\n  if (dayOverflow !== 0) {\n    return shiftDays(result, dayOverflow);\n  }\n  return result;\n}\n\nexport function subtract(value: unknown, amount: number, unit: AddUnit): DateTimeFieldView {\n  return add(value, -amount, unit);\n}\n\n// Per-unit convenience wrappers — matches the grouping of\n// addYears / addMonths / ... / subtractNanoseconds. Nanosecond variants\n// aren't provided here because these helpers operate on field bags, and\n// the millisecond/microsecond/nanosecond split isn't preserved through\n// arithmetic at sub-millisecond precision the way Temporal.Duration's\n// own add preserves it. For ns-precision arithmetic, use Temporal.Duration\n// directly.\nexport const addYears = (v: unknown, n: number) => add(v, n, 'years');\nexport const addMonths = (v: unknown, n: number) => add(v, n, 'months');\nexport const addWeeks = (v: unknown, n: number) => add(v, n, 'weeks');\nexport const addDays = (v: unknown, n: number) => add(v, n, 'days');\nexport const addHours = (v: unknown, n: number) => add(v, n, 'hours');\nexport const addMinutes = (v: unknown, n: number) => add(v, n, 'minutes');\nexport const addSeconds = (v: unknown, n: number) => add(v, n, 'seconds');\nexport const addMilliseconds = (v: unknown, n: number) => add(v, n, 'milliseconds');\n\nexport const subtractYears = (v: unknown, n: number) => subtract(v, n, 'years');\nexport const subtractMonths = (v: unknown, n: number) => subtract(v, n, 'months');\nexport const subtractWeeks = (v: unknown, n: number) => subtract(v, n, 'weeks');\nexport const subtractDays = (v: unknown, n: number) => subtract(v, n, 'days');\nexport const subtractHours = (v: unknown, n: number) => subtract(v, n, 'hours');\nexport const subtractMinutes = (v: unknown, n: number) => subtract(v, n, 'minutes');\nexport const subtractSeconds = (v: unknown, n: number) => subtract(v, n, 'seconds');\nexport const subtractMilliseconds = (v: unknown, n: number) => subtract(v, n, 'milliseconds');\n\n// difference(): returns the count of `unit` boundaries between two values.\n// Pure-integer math, no Temporal.Duration involved. For sub-day\n// precision the result is an integer count of the requested unit (not\n// a Duration field bag) — matches the most common caller expectation\n// (\"how many days between these two dates?\").\nexport type DiffUnit = 'years' | 'months' | 'weeks' | 'days' | 'hours' | 'minutes' | 'seconds' | 'milliseconds';\n\nexport function difference(a: unknown, b: unknown, unit: DiffUnit): number {\n  const av = asDateTime(a);\n  const bv = asDateTime(b);\n\n  // For day-granular units (years/months/weeks/days), compute via\n  // calendar arithmetic on the date fields. For sub-day units, compute\n  // via total-ms and divide.\n  if (unit === 'years') {\n    return bv.year! - av.year!;\n  }\n  if (unit === 'months') {\n    return (bv.year! * 12 + bv.month! - 1) - (av.year! * 12 + av.month! - 1);\n  }\n  if (unit === 'weeks' || unit === 'days') {\n    const aDays = toDayCount(av);\n    const bDays = toDayCount(bv);\n    const days = bDays - aDays;\n    return unit === 'weeks' ? Math.trunc(days / 7) : days;\n  }\n\n  // Sub-day units: total-ms math.\n  const MS_PER_HOUR = 3_600_000;\n  const MS_PER_MINUTE = 60_000;\n  const MS_PER_SECOND = 1_000;\n  const aMs = toTotalMs(av);\n  const bMs = toTotalMs(bv);\n  const diffMs = bMs - aMs;\n  switch (unit) {\n    case 'hours': return Math.trunc(diffMs / MS_PER_HOUR);\n    case 'minutes': return Math.trunc(diffMs / MS_PER_MINUTE);\n    case 'seconds': return Math.trunc(diffMs / MS_PER_SECOND);\n    case 'milliseconds': return diffMs;\n  }\n}\n\nfunction toDayCount(v: DateTimeFieldView): number {\n  // daysFromCivil (isoWeek.ts): the O(1) Hinnant day count, correct for\n  // negative years. The era term previously inlined here double-shifted\n  // pre-year-0 dates by one day (see shiftDays).\n  return daysFromCivil(v.year!, v.month!, v.day!);\n}\n\nfunction toTotalMs(v: DateTimeFieldView): number {\n  const MS_PER_DAY = 86_400_000;\n  const MS_PER_HOUR = 3_600_000;\n  const MS_PER_MINUTE = 60_000;\n  const MS_PER_SECOND = 1_000;\n  return toDayCount(v) * MS_PER_DAY\n    + (v.hour ?? 0) * MS_PER_HOUR\n    + (v.minute ?? 0) * MS_PER_MINUTE\n    + (v.second ?? 0) * MS_PER_SECOND\n    + (v.millisecond ?? 0);\n}\n\n// Per-unit difference wrappers — same convenience pattern as the add*\n// wrappers above.\nexport const differenceInYears = (a: unknown, b: unknown) => difference(a, b, 'years');\nexport const differenceInMonths = (a: unknown, b: unknown) => difference(a, b, 'months');\nexport const differenceInWeeks = (a: unknown, b: unknown) => difference(a, b, 'weeks');\nexport const differenceInDays = (a: unknown, b: unknown) => difference(a, b, 'days');\nexport const differenceInHours = (a: unknown, b: unknown) => difference(a, b, 'hours');\nexport const differenceInMinutes = (a: unknown, b: unknown) => difference(a, b, 'minutes');\nexport const differenceInSeconds = (a: unknown, b: unknown) => difference(a, b, 'seconds');\nexport const differenceInMilliseconds = (a: unknown, b: unknown) => difference(a, b, 'milliseconds');"],"mappings":"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","names":[]}