{"version":3,"sources":["../src/recurrence.ts","../src/isoWeek.ts","../src/calendarUtils.ts","../src/arithmetic.ts","../src/comparison.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// Recurrence engine. Deterministic RRULE-like\n// recurrence without pulling in a runtime dependency. Supports\n// secondly/minutely/hourly/daily/weekly/monthly/yearly frequencies,\n// interval, count, until, weekdays (incl. ordinal BYDAY like 2MO/-1FR\n// for monthly/yearly), monthDays (incl. negative end-of-month values),\n// exclusions, inclusions.\n//\n// RRULE interop: parseRRule() / formatRRule() convert to/from the\n// standard iCalendar RRULE string format (RFC 5545). Implemented\n// without depending on a RRULE library — the grammar is small enough\n// to handle inline. Not enforced (documented limitation, same as\n// before): BYSETPOS, BYHOUR, BYMINUTE, BYSECOND, WKST.\n\nimport { add } from './arithmetic.js';\nimport { compare } from './comparison.js';\nimport { daysFromCivil } from './isoWeek.js';\nimport { asDateFieldView } from './calendarUtils.js';\n\nexport type RecurrenceFrequency = 'secondly' | 'minutely' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly';\n\nexport interface WeekdayOrdinal {\n  // 2 = \"2nd such weekday of the month\", -1 = \"last such weekday\".\n  // Only meaningful with monthly/yearly frequency (RFC 5545 3.3.10:\n  // the numeric prefix is invalid with WEEKLY, where it's ignored).\n  ordinal: number;\n  weekday: number; // ISO 1=Mon..7=Sun\n}\n\nexport interface RecurrenceRule {\n  frequency: RecurrenceFrequency;\n  interval: number; // default 1 — omitted/null now means 1 (used to mean NaN)\n  count?: number; // max occurrences\n  until?: unknown; // Temporal value (or RRULE UNTIL date form) — recurrence ends after this\n  // For weekly: ISO weekdays to include (1=Mon..7=Sun). Empty = all.\n  byWeekday?: number[];\n  // Ordinal BYDAY parts (2MO, -1FR) parsed from RRULE strings — the nth\n  // weekday of each month/year. Matched in addition to plain byWeekday.\n  byWeekdayOrdinal?: WeekdayOrdinal[];\n  // For monthly/yearly: days of month to include (1-31, or negative\n  // for end-of-month: -1 = last day).\n  byMonthDay?: number[];\n  // For yearly: months to include (1-12).\n  byMonth?: number[];\n  // For weekly: which week of the year (1-53).\n  byWeek?: number[];\n  // Exclusions: dates to skip even if they match the rule.\n  exDates?: unknown[];\n  // Inclusions: dates to add even if they don't match the rule.\n  rDates?: unknown[];\n}\n\nexport interface RecurrenceIterator {\n  next(): { value: unknown; done: boolean } | { value: undefined; done: true };\n  previous(): { value: unknown; done: boolean } | { value: undefined; done: true };\n}\n\nfunction daysInMonthOf(year: number, month: number): number {\n  const LENGTHS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n  const leap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n  return month === 2 && leap ? 29 : LENGTHS[month - 1]!;\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) + 1.\nfunction weekdayOf(year: number, month: number, day: number): number {\n  const days = daysFromCivil(year, month, day);\n  return (((days + 3) % 7) + 7) % 7 + 1;\n}\n\n// Day-of-month of the `ordinal`-th `weekday` in the given month\n// (ordinal < 0 counts from the end, -1 = last). Returns null when no\n// such day exists in this month (e.g. 5th Monday of a 4-Monday month).\nfunction nthWeekdayDay(year: number, month: number, weekday: number, ordinal: number): number | null {\n  const last = daysInMonthOf(year, month);\n  if (ordinal > 0) {\n    const firstDow = weekdayOf(year, month, 1);\n    const first = 1 + ((weekday - firstDow + 7) % 7);\n    const day = first + (ordinal - 1) * 7;\n    return day <= last ? day : null;\n  }\n  const lastDow = weekdayOf(year, month, last);\n  const lastOccurrence = last - ((lastDow - weekday + 7) % 7);\n  const day = lastOccurrence + (ordinal + 1) * 7;\n  return day >= 1 ? day : null;\n}\n\n// Creates a recurrence iterator starting from `start`. The first call\n// to next() returns `start` itself (if it matches the rule); subsequent\n// calls return the next matching occurrence.\nexport function recurrence(start: unknown, rule: RecurrenceRule): RecurrenceIterator {\n  if (rule.count !== undefined && (!Number.isSafeInteger(rule.count) || rule.count < 1)) {\n    throw new RangeError(`temporal-fmt: recurrence rule count must be a positive safe integer (got ${String(rule.count)}).`);\n  }\n  // The interface documents interval as \"default 1\" — normalize it here\n  // so a rule object omitting it (or passing undefined) behaves as 1\n  // instead of poisoning every candidate with NaN arithmetic.\n  const interval = rule.interval !== undefined && rule.interval !== null\n    ? rule.interval\n    : 1;\n  if (!Number.isSafeInteger(interval) || interval < 1) {\n    throw new RangeError(`temporal-fmt: recurrence rule interval must be a positive safe integer (got ${String(rule.interval)}).`);\n  }\n  // Programmatic rules skip parseRRule's validation, so re-check the\n  // BY* lists here — garbage used to fall through to `?? 0` fallbacks\n  // in matches() and quietly match nothing (a rule like byMonthDay:[0]\n  // produced an empty sequence with no hint why). Real rules from\n  // parseRRule always pass.\n  if (rule.byMonthDay && rule.byMonthDay.some((d) => !Number.isSafeInteger(d) || d === 0 || d < -31 || d > 31)) {\n    throw new RangeError('temporal-fmt: recurrence rule byMonthDay entries must be nonzero integers in [-31, 31].');\n  }\n  if (rule.byWeekday && rule.byWeekday.some((d) => !Number.isSafeInteger(d) || d < 1 || d > 7)) {\n    throw new RangeError('temporal-fmt: recurrence rule byWeekday entries must be ISO weekdays 1 (Mon) through 7 (Sun).');\n  }\n  if (rule.byMonth && rule.byMonth.some((m) => !Number.isSafeInteger(m) || m < 1 || m > 12)) {\n    throw new RangeError('temporal-fmt: recurrence rule byMonth entries must be months 1 through 12.');\n  }\n  if (rule.byWeekdayOrdinal && rule.byWeekdayOrdinal.some((o) =>\n    !Number.isSafeInteger(o.ordinal) || o.ordinal === 0 || o.ordinal < -53 || o.ordinal > 53 ||\n    !Number.isSafeInteger(o.weekday) || o.weekday < 1 || o.weekday > 7)) {\n    throw new RangeError('temporal-fmt: recurrence rule byWeekdayOrdinal entries need a nonzero ordinal in [-53, 53] and an ISO weekday 1-7.');\n  }\n  // Track past values for previous() — keeps a ring buffer of the last\n  // N occurrences so previous() can walk back without recomputing.\n  const history: unknown[] = [];\n  const MAX_HISTORY = 10_000;\n  let atEnd = false;\n  let atStart = true;\n\n  // Anchor: the ORIGINAL start, as a field view. Monthly/yearly\n  // candidates are derived from this (not from the previous occurrence)\n  // so the day-of-month never drifts: advancing Jan 31 by months used\n  // to go 01-31 → 02-28 → 03-28 → 04-28 …, permanently stuck on day 28\n  // after the first February clamp. Deriving each period's candidates\n  // from the anchor keeps the original day and skips (rather than\n  // clamps) periods that lack it — RFC 5545 semantics.\n  const anchor = asDateFieldView(start);\n  const originDayCount = daysFromCivil(anchor.year!, anchor.month!, anchor.day!);\n\n  // A plain field-bag start without dayOfWeek used to make every\n  // byWeekday-dependent rule silently produce nothing: matches()'s\n  // `?? 0` never equals a real weekday, and add()'s dayOfWeek\n  // recompute only refreshes a field that already exists — so the\n  // chain never picks one up (a Temporal start works because its\n  // dayOfWeek getter seeds it). Derive it once here so bag starts and\n  // Temporal starts behave identically for BYDAY rules.\n  let current: unknown = start;\n  if (rule.byWeekday && rule.byWeekday.length > 0 && typeof (start as { dayOfWeek?: unknown }).dayOfWeek !== 'number') {\n    current = { ...anchor, dayOfWeek: weekdayOf(anchor.year!, anchor.month!, anchor.day!) };\n  }\n  let count = 0;\n\n  function matches(value: unknown): boolean {\n    // The `?? 0` / `?? []` fallbacks on the lines flagged below are\n    // defensive only and unreachable through the public API: recurrence()\n    // rejects starts missing year/month/day, every generated candidate is\n    // a full field view (fillNextPeriod sets dayOfWeek; add()'s\n    // recomputeDayOfWeek refreshes one seeded at the top), and the\n    // byWeekday gate above runs before plainOk is ever evaluated — so\n    // dayOfWeek is defined whenever `?? 0` would fire, and year/month/day\n    // are always present. The lines they sit on are otherwise live and\n    // test-covered; only the fallback arms need the ignore.\n    const v = value as { dayOfWeek?: number; year?: number; month?: number; day?: number; hour?: number; minute?: number; second?: number };\n    if (rule.byWeekday && rule.byWeekday.length > 0) {\n      // `?? 0` is defensive only since the dayOfWeek seeding above: every\n      // value a byWeekday rule tests (seeded start, generated candidates)\n      // carries a number.\n      /* c8 ignore next @preserve */\n      if (!rule.byWeekday.includes(v.dayOfWeek ?? 0)) return false;\n    }\n    if (rule.byWeekdayOrdinal && rule.byWeekdayOrdinal.length > 0\n      && (rule.frequency === 'monthly' || rule.frequency === 'yearly')) {\n      // Union with the plain-byWeekday check above per RFC: any BYDAY\n      // entry matching is enough. (Monthly/yearly candidates are\n      // generated from the ordinal itself, so this re-check is about\n      // rules that mix plain and ordinal entries.)\n      /* c8 ignore next @preserve */\n      const plainOk = !!rule.byWeekday && rule.byWeekday.length > 0 && rule.byWeekday.includes(v.dayOfWeek ?? 0);\n      /* c8 ignore next @preserve */\n      const ordinalOk = (rule.byWeekdayOrdinal ?? []).some((o) =>\n      /* c8 ignore next @preserve */\n        nthWeekdayDay(v.year ?? 0, v.month ?? 0, o.weekday, o.ordinal) === (v.day ?? 0));\n      if (!plainOk && !ordinalOk) return false;\n    }\n    if (rule.byMonthDay && rule.byMonthDay.length > 0) {\n      // Negative values count back from the end of the month\n      // (-1 = last day). They used to be accepted by parseRRule but\n      // never matched anything — a day-of-month is never negative.\n      /* c8 ignore next @preserve */\n      const day = v.day ?? 0;\n      /* c8 ignore next @preserve */\n      const last = daysInMonthOf(v.year ?? 0, v.month ?? 0);\n      // `?? []` is defensive only: the enclosing if guards byMonthDay\n      // non-empty.\n      /* c8 ignore next @preserve */\n      const hit = (rule.byMonthDay ?? []).some((d) => (d > 0 ? d === day : d + last + 1 === day));\n      if (!hit) return false;\n    }\n    if (rule.byMonth && rule.byMonth.length > 0) {\n      /* c8 ignore next @preserve */\n      if (!rule.byMonth.includes(v.month ?? 0)) return false;\n    }\n    if (rule.exDates && rule.exDates.some((d) => compare(d, value) === 0)) return false;\n    return true;\n  }\n\n  // ---- Monthly/yearly candidate generation ------------------------------\n  // Each interval step yields one period (a month, or a year with its\n  // byMonth months). The period's candidate days are:\n  //   - byMonthDay values, if present (negatives resolved to real days);\n  //   - else ordinal BYDAY days, if present;\n  //   - else the anchor's day (periods lacking it yield nothing).\n  // Candidates carry the anchor's time-of-day and a recomputed\n  // dayOfWeek, and are yielded in chronological order.\n  let pending: unknown[] = [];\n  // Starts at 0: the start's OWN period gets generated first (RFC —\n  // FREQ=MONTHLY;BYMONTHDAY=15 from Jan 1 yields Jan 15 before Feb 15),\n  // with candidates at or before `start` skipped by nextMatch.\n  let periodIndex = 0;\n\n  function fillNextPeriod(): void {\n    // k starts at 0 (the start's own period) and increments AFTER use,\n    // so every period from the anchor's onward is generated exactly once.\n    const k = periodIndex;\n    periodIndex++;\n    let year: number;\n    let months: number[];\n    if (rule.frequency === 'monthly') {\n      const totalMonths = anchor.year! * 12 + anchor.month! - 1 + k * interval;\n      year = Math.floor(totalMonths / 12);\n      months = [totalMonths - year * 12 + 1];\n    } else {\n      year = anchor.year! + k * interval;\n      months = rule.byMonth && rule.byMonth.length > 0\n        ? [...rule.byMonth].sort((a, b) => a - b)\n        : [anchor.month!];\n    }\n    const days: Array<{ month: number; day: number }> = [];\n    for (const m of months) {\n      const last = daysInMonthOf(year, m);\n      if (rule.byMonthDay && rule.byMonthDay.length > 0) {\n        for (const d of rule.byMonthDay) {\n          const real = d > 0 ? d : last + 1 + d;\n          if (real >= 1 && real <= last) days.push({ month: m, day: real });\n        }\n      } else if (rule.byWeekdayOrdinal && rule.byWeekdayOrdinal.length > 0) {\n        for (const o of rule.byWeekdayOrdinal) {\n          const real = nthWeekdayDay(year, m, o.weekday, o.ordinal);\n          if (real !== null) days.push({ month: m, day: real });\n        }\n      } else {\n        if (anchor.day! <= last) days.push({ month: m, day: anchor.day! });\n      }\n    }\n    days.sort((a, b) => a.month - b.month || a.day - b.day);\n    pending = days.map(({ month, day }) => ({\n      ...anchor,\n      year,\n      month,\n      day,\n      dayOfWeek: weekdayOf(year, month, day),\n    }));\n  }\n\n  // Steps to the next candidate after `value`, by the frequency's own\n  // granularity:\n  //  - monthly/yearly: pop the period queue (refilling as needed);\n  //  - weekly + BYDAY: one day at a time (stepping whole weeks preserves\n  //    the weekday, so a start not already on a BYDAY weekday could\n  //    never match — FREQ=WEEKLY;BYDAY=SA from a Monday used to produce\n  //    an empty sequence), gated to the interval's week windows;\n  //  - everything else: one `interval` step from the current value, the\n  //    same way the original implementation did.\n  function nextMatch(value: unknown): { value: unknown; found: boolean } {\n    let candidate = value;\n    let safetyCounter = 0;\n    const daywise = rule.frequency === 'weekly' && !!rule.byWeekday && rule.byWeekday.length > 0;\n    const periodwise = rule.frequency === 'monthly' || rule.frequency === 'yearly';\n    const unit = rule.frequency === 'secondly' ? 'seconds'\n      : rule.frequency === 'minutely' ? 'minutes'\n      : rule.frequency === 'hourly' ? 'hours'\n      : rule.frequency === 'daily' ? 'days'\n      : 'weeks';\n\n    while (true) {\n      // Count EVERY iteration, including the two `continue` paths below\n      // (empty periods, candidates at/before the start): those used to\n      // skip the increment, so a rule whose every period is empty — e.g.\n      // monthly BYDAY=-6MO, which no month can ever satisfy — spun the\n      // loop forever. The cap is a total-work bound per next() call, not\n      // a candidates-produced bound.\n      safetyCounter++;\n      if (safetyCounter > 2000) {\n        // Defensive — if the rule is so restrictive no match exists\n        // within 2000 steps, give up rather than spin forever. The\n        // caller must treat this as \"no more occurrences\", not as a\n        // real match — returning the unmatched candidate here used to\n        // get handed back to next()'s caller as if it were valid.\n        // (1000 previously; doubled because day-granular stepping for\n        // weekly BYDAY rules legitimately needs up to 7 steps per\n        // occurrence, and monthly skips can chain across short months.)\n        atEnd = true;\n        return { value: candidate, found: false };\n      }\n      if (daywise) {\n        candidate = add(candidate, 1, 'days');\n        // INTERVAL > 1 on a weekly BYDAY rule: only weeks that are a\n        // whole multiple of `interval` away from the anchor's week emit\n        // occurrences (WKST unsupported — the window anchors on the\n        // start's own day).\n        if (interval > 1) {\n          const v = asDateFieldView(candidate);\n          const dayCount = daysFromCivil(v.year!, v.month!, v.day!);\n          if (Math.floor((dayCount - originDayCount) / 7) % interval !== 0) continue;\n        }\n      } else if (periodwise) {\n        if (pending.length === 0) {\n          fillNextPeriod();\n          if (pending.length === 0) continue; // period had no valid days\n        }\n        candidate = pending.shift()!;\n        // The start's own period can contain candidate days at or before\n        // the start itself (BYMONTHDAY=15 generating Jan 15 for a Jan 1\n        // start, where Jan 1..14 precede it) — those aren't occurrences.\n        if (compare(candidate, value) <= 0) continue;\n      } else {\n        candidate = add(candidate, interval, unit as Parameters<typeof add>[2]);\n      }\n      if (rule.until && compare(candidate, rule.until) > 0) {\n        atEnd = true;\n        return { value: candidate, found: false };\n      }\n      if (matches(candidate)) break;\n    }\n    return { value: candidate, found: true };\n  }\n\n  function recordHistory(value: unknown): void {\n    history.push(value);\n    if (history.length > MAX_HISTORY) history.shift();\n  }\n\n  return {\n    next() {\n      if (atEnd) return { value: undefined, done: true };\n      if (atStart) {\n        atStart = false;\n        if (matches(current)) {\n          count++;\n          if (rule.count !== undefined && count >= rule.count) atEnd = true;\n          if (rule.until && compare(current, rule.until) > 0) {\n            atEnd = true;\n            return { value: undefined, done: true };\n          }\n          // Include rDates that match the current value.\n          recordHistory(current);\n          return { value: current, done: false };\n        }\n        // If start doesn't match, advance to first match.\n        const advanced = nextMatch(current);\n        if (!advanced.found) return { value: undefined, done: true };\n        current = advanced.value;\n        count++;\n        if (rule.count !== undefined && count >= rule.count) atEnd = true;\n        recordHistory(current);\n        return { value: current, done: false };\n      }\n      const advanced = nextMatch(current);\n      if (!advanced.found) return { value: undefined, done: true };\n      current = advanced.value;\n      count++;\n      if (rule.count !== undefined && count >= rule.count) atEnd = true;\n      recordHistory(current);\n      return { value: current, done: false };\n    },\n    previous() {\n      if (history.length === 0) return { value: undefined, done: true };\n      const v = history.pop()!;\n      return { value: v, done: false };\n    },\n  };\n}\n\n// Take N occurrences from a recurrence iterator.\nexport function take(iter: RecurrenceIterator, n: number): unknown[] {\n  const result: unknown[] = [];\n  for (let i = 0; i < n; i++) {\n    const r = iter.next();\n    if (r.done) break;\n    result.push(r.value);\n  }\n  return result;\n}\n\n// Upper bound on how many occurrences skip() will collect after its\n// skip phase. skip() used to call take(iter, Number.MAX_SAFE_INTEGER),\n// and an iterator over an unbounded rule (no count, no until — e.g.\n// { frequency: 'daily', interval: 1 }) never returns done: next() always\n// has another day. The call then looped forever, pushing into a result\n// array until the process OOM'd. Same cap style as businessCalendar.ts.\nconst MAX_SKIP_COLLECTION = 100_000;\n// Upper bound on skip()'s skip phase too: skip(iter, 1e9) on an\n// unbounded rule used to burn a billion next() calls before the\n// collection cap was ever reached.\nconst MAX_SKIP_STEPS = 1_000_000;\n\n// Skip N occurrences from a recurrence iterator, returning the ones\n// that follow. Throws a RangeError when the iterator is still producing\n// occurrences after MAX_SKIP_COLLECTION — that means the rule is\n// unbounded (no count/until) and \"everything after the skip\" has no\n// finite answer.\nexport function skip(iter: RecurrenceIterator, n: number): unknown[] {\n  for (let i = 0; i < n; i++) {\n    if (i >= MAX_SKIP_STEPS) {\n      throw new RangeError(\n        `temporal-fmt: skip() was asked to skip more than ${MAX_SKIP_STEPS} occurrences — that's not a bounded operation; use take() on a count/until-bounded rule instead.`\n      );\n    }\n    const r = iter.next();\n    if (r.done) break;\n  }\n  const result: unknown[] = [];\n  while (result.length < MAX_SKIP_COLLECTION) {\n    const r = iter.next();\n    if (r.done) return result;\n    result.push(r.value);\n  }\n  throw new RangeError(\n    `temporal-fmt: skip() collected ${MAX_SKIP_COLLECTION} occurrences and the rule is still ` +\n    `producing — add a count or until to the rule, or use take(iter, n) for a bounded read.`\n  );\n}\n\n// All occurrences between two dates (inclusive of start, exclusive of end).\nexport function between(start: unknown, rule: RecurrenceRule, rangeStart: unknown, rangeEnd: unknown): unknown[] {\n  const iter = recurrence(start, rule);\n  const result: unknown[] = [];\n  // Traversal cap: a fine-grained rule anchored far before rangeEnd\n  // (e.g. daily from year -2000) walks every occurrence since `start`\n  // — bounded work instead of an unbounded loop, same style as skip().\n  const MAX_TRAVERSAL = 1_000_000;\n  let traversed = 0;\n  while (true) {\n    if (traversed++ > MAX_TRAVERSAL) {\n      throw new RangeError(\n        `temporal-fmt: between() walked more than ${MAX_TRAVERSAL} occurrences without reaching rangeEnd — ` +\n        `pass a start closer to the range, or bound the rule with count/until.`\n      );\n    }\n    const r = iter.next();\n    if (r.done) break;\n    if (compare(r.value, rangeEnd) >= 0) break;\n    if (compare(r.value, rangeStart) >= 0) result.push(r.value);\n  }\n  return result;\n}\n\n// Parses an RRULE UNTIL value (RFC 5545 date \"20240110\" or UTC\n// date-time \"20240110T153000Z\") into a comparable field bag. Stored raw\n// previously, so iterating a parsed rule threw \"expected a date-carrying\n// Temporal value\" on the first next() — a parsed RRULE was unusable\n// with UNTIL, the single most common termination form.\nfunction parseUntil(value: string): { year: number; month: number; day: number; hour?: number; minute?: number; second?: number } {\n  const m = /^(\\d{4})(\\d{2})(\\d{2})(?:T(\\d{2})(\\d{2})(\\d{2})Z?)?$/.exec(value.trim());\n  if (!m) {\n    throw new RangeError(\n      `temporal-fmt: RRULE UNTIL must be a date (\"20240110\") or UTC date-time (\"20240110T153000Z\") — got \"${value}\".`\n    );\n  }\n  const year = Number(m[1]);\n  const month = Number(m[2]);\n  const day = Number(m[3]);\n  if (month < 1 || month > 12 || day < 1 || day > 31) {\n    throw new RangeError(`temporal-fmt: RRULE UNTIL carries an out-of-range date \"${value}\".`);\n  }\n  const hour = m[4] !== undefined ? Number(m[4]) : undefined;\n  const minute = m[5] !== undefined ? Number(m[5]) : undefined;\n  const second = m[6] !== undefined ? Number(m[6]) : undefined;\n  if (hour !== undefined && (hour > 23 || minute! > 59 || second! > 59)) {\n    throw new RangeError(`temporal-fmt: RRULE UNTIL carries an out-of-range time \"${value}\".`);\n  }\n  return { year, month, day, hour, minute, second };\n}\n\n// Parses an RRULE string like \"FREQ=DAILY;INTERVAL=2;COUNT=5\" into a\n// RecurrenceRule. Doesn't support every RRULE feature (BYSETPOS,\n// BYHOUR, BYMINUTE, BYSECOND, WKST are not enforced by the recurrence\n// iterator above), but covers the common cases.\nexport function parseRRule(input: string): RecurrenceRule {\n  const parts = input.trim().toUpperCase().replace(/^RRULE:/, '').split(';');\n  const rule: RecurrenceRule = { frequency: 'daily', interval: 1 };\n  const frequencies: ReadonlySet<string> = new Set([\n    'SECONDLY', 'MINUTELY', 'HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY', 'YEARLY',\n  ]);\n  for (const part of parts) {\n    if (!part) continue;\n    const eq = part.indexOf('=');\n    if (eq < 0) continue;\n    const key = part.slice(0, eq);\n    const value = part.slice(eq + 1);\n    switch (key) {\n      case 'FREQ':\n        if (!frequencies.has(value)) {\n          throw new RangeError(`temporal-fmt: unsupported RRULE frequency \"${value}\".`);\n        }\n        rule.frequency = value.toLowerCase() as RecurrenceFrequency;\n        break;\n      case 'INTERVAL': {\n        const interval = Number(value);\n        if (!Number.isSafeInteger(interval) || interval < 1) {\n          throw new RangeError(`temporal-fmt: RRULE INTERVAL must be a positive safe integer (got \"${value}\").`);\n        }\n        rule.interval = interval;\n        break;\n      }\n      case 'COUNT': {\n        const count = Number(value);\n        if (!Number.isSafeInteger(count) || count < 1) {\n          throw new RangeError(`temporal-fmt: RRULE COUNT must be a positive safe integer (got \"${value}\").`);\n        }\n        rule.count = count;\n        break;\n      }\n      case 'UNTIL':\n        rule.until = parseUntil(value);\n        break;\n      case 'BYDAY': {\n        const WEEKDAY_MAP: Record<string, number> = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };\n        const plain: number[] = [];\n        const ordinals: WeekdayOrdinal[] = [];\n        for (const d of value.split(',')) {\n          // RFC 5545 ordinals run -53..53 — two digits are legal, so the\n          // pattern must accept them (it used to cap at one digit, which\n          // made valid rules like BYDAY=53MO throw \"invalid weekday\" and\n          // pushed out-of-range ordinals past the range check below\n          // instead of reaching it).\n          const m = d.match(/^([+-]?\\d{1,2})?([A-Z]{2})$/);\n          // Unknown tokens used to map to 0 silently — a typo'd BYDAY\n          // entry quietly matched nothing instead of failing loudly.\n          if (!m || WEEKDAY_MAP[m[2]!] === undefined) {\n            throw new RangeError(`temporal-fmt: RRULE BYDAY contains an invalid weekday \"${d}\".`);\n          }\n          const weekday = WEEKDAY_MAP[m[2]!]!;\n          if (m[1] !== undefined) {\n            const ordinal = Number(m[1]);\n            if (!Number.isSafeInteger(ordinal) || ordinal === 0 || ordinal < -53 || ordinal > 53) {\n              throw new RangeError(`temporal-fmt: RRULE BYDAY ordinal out of range in \"${d}\".`);\n            }\n            ordinals.push({ ordinal, weekday });\n          } else {\n            plain.push(weekday);\n          }\n        }\n        rule.byWeekday = plain;\n        if (ordinals.length > 0) rule.byWeekdayOrdinal = ordinals;\n        break;\n      }\n      case 'BYMONTHDAY': {\n        const values = value.split(',').map(Number);\n        if (values.some((day) => !Number.isInteger(day) || day === 0 || day < -31 || day > 31)) {\n          throw new RangeError(`temporal-fmt: RRULE BYMONTHDAY contains an out-of-range value.`);\n        }\n        rule.byMonthDay = values;\n        break;\n      }\n      case 'BYMONTH': {\n        const values = value.split(',').map(Number);\n        if (values.some((month) => !Number.isInteger(month) || month < 1 || month > 12)) {\n          throw new RangeError(`temporal-fmt: RRULE BYMONTH contains an out-of-range value.`);\n        }\n        rule.byMonth = values;\n        break;\n      }\n    }\n  }\n  return rule;\n}\n\nexport function formatRRule(rule: RecurrenceRule): string {\n  const parts: string[] = [`FREQ=${rule.frequency.toUpperCase()}`];\n  // Programmatic rules may omit interval (documented default: 1) — emitting\n  // \"INTERVAL=undefined\" for them produced output that parseRRule itself\n  // rejects, breaking the round-trip. Omit it unless it's an explicit != 1.\n  if (rule.interval !== undefined && rule.interval !== 1) parts.push(`INTERVAL=${rule.interval}`);\n  if (rule.count !== undefined) parts.push(`COUNT=${rule.count}`);\n  if (rule.until !== undefined) parts.push(`UNTIL=${String(rule.until)}`);\n  const WEEKDAY_NAMES: Record<number, string> = { 1: 'MO', 2: 'TU', 3: 'WE', 4: 'TH', 5: 'FR', 6: 'SA', 7: 'SU' };\n  if (rule.byWeekday && rule.byWeekday.length > 0) {\n    parts.push(`BYDAY=${rule.byWeekday.map((d) => WEEKDAY_NAMES[d] ?? String(d)).join(',')}`);\n  }\n  if (rule.byWeekdayOrdinal && rule.byWeekdayOrdinal.length > 0) {\n    const rendered = rule.byWeekdayOrdinal.map((o) => `${o.ordinal}${WEEKDAY_NAMES[o.weekday] ?? String(o.weekday)}`);\n    // Merge into the plain BYDAY part when both exist (RRULE carries\n    // one combined list).\n    if (rule.byWeekday && rule.byWeekday.length > 0) {\n      parts[parts.length - 1] = `BYDAY=${[...rule.byWeekday.map((d) => WEEKDAY_NAMES[d] ?? String(d)), ...rendered].join(',')}`;\n    } else {\n      parts.push(`BYDAY=${rendered.join(',')}`);\n    }\n  }\n  if (rule.byMonthDay && rule.byMonthDay.length > 0) parts.push(`BYMONTHDAY=${rule.byMonthDay.join(',')}`);\n  if (rule.byMonth && rule.byMonth.length > 0) parts.push(`BYMONTH=${rule.byMonth.join(',')}`);\n  return parts.join(';');\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');","/*\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// Comparison helpers. Pure functions over the field\n// shape, no Temporal namespace needed — same convention as\n// calendarUtils.ts. All comparisons are field-based, not identity-based,\n// so a polyfill PlainDate compares equal to a native PlainDate with the\n// same year/month/day.\n\nimport { asDateFieldView, type DateFieldView } from './calendarUtils.js';\nimport { dayOfWeekFromCivil, daysFromCivil } from './isoWeek.js';\n\ninterface DateTimeFieldView extends DateFieldView {\n  hour?: number;\n  minute?: number;\n  second?: number;\n  millisecond?: number;\n}\n\nfunction toComparableMs(view: DateTimeFieldView): number {\n  // Exact proleptic-Gregorian day count (Howard Hinnant's days_from_civil,\n  // same algorithm arithmetic.ts/interval.ts use) plus the time-of-day —\n  // NOT an approximation. The previous implementation multiplied the\n  // year offset by an average 365.2425 days/year, on the theory that the\n  // error \"is constant for any given year, so it cancels out in a diff\".\n  // That's only true when both dates fall in the same year: the year\n  // term's error differs by up to ~0.76 days between adjacent years\n  // (365.2425 vs 365/366 actual), which corrupts cross-year comparisons\n  // near the boundary — e.g. isAfter(2025-01-01T00:00, 2024-12-31T18:12)\n  // returned false (truth: ~5.8h after), and isEqual() returned true for\n  // instants ~18h apart (2025-01-01T00:00 vs 2024-12-31T05:49:12).\n  // Exact arithmetic has no such error term. The day count itself comes\n  // from isoWeek.ts's daysFromCivil (Howard Hinnant's days_from_civil:\n  // O(1), correct for negative years — the inlined era formula this\n  // replaced double-corrected pre-year-0 dates by a day via Math.floor\n  // of the -399-offset numerator).\n  const days = daysFromCivil(view.year!, view.month!, view.day!);\n\n  const MS_PER_HOUR = 3_600_000;\n  const MS_PER_MINUTE = 60_000;\n  const MS_PER_SECOND = 1_000;\n\n  return days * 86_400_000\n    + (view.hour ?? 0) * MS_PER_HOUR\n    + (view.minute ?? 0) * MS_PER_MINUTE\n    + (view.second ?? 0) * MS_PER_SECOND\n    + (view.millisecond ?? 0);\n}\n\nfunction asDateTimeFieldView(value: unknown): DateTimeFieldView {\n  const v = asDateFieldView(value);\n  return v as DateTimeFieldView;\n}\n\n// Returns < 0 if a < b, 0 if a === b, > 0 if a > b. Same convention as\n// Array.prototype.sort and Temporal.PlainDate.compare. Lets callers\n// pass this directly as a comparator.\nexport function compare(a: unknown, b: unknown): number {\n  const av = asDateTimeFieldView(a);\n  const bv = asDateTimeFieldView(b);\n  const am = toComparableMs(av);\n  const bm = toComparableMs(bv);\n  if (am < bm) return -1;\n  if (am > bm) return 1;\n  return 0;\n}\n\nexport function isEqual(a: unknown, b: unknown): boolean {\n  return compare(a, b) === 0;\n}\n\nexport function isBefore(a: unknown, b: unknown): boolean {\n  return compare(a, b) < 0;\n}\n\nexport function isAfter(a: unknown, b: unknown): boolean {\n  return compare(a, b) > 0;\n}\n\nexport function min(values: unknown[]): unknown {\n  if (!Array.isArray(values) || values.length === 0) {\n    throw new Error('temporal-fmt: min() requires a non-empty array of values.');\n  }\n  let best = values[0];\n  for (let i = 1; i < values.length; i++) {\n    if (compare(values[i], best) < 0) best = values[i];\n  }\n  return best;\n}\n\nexport function max(values: unknown[]): unknown {\n  if (!Array.isArray(values) || values.length === 0) {\n    throw new Error('temporal-fmt: max() requires a non-empty array of values.');\n  }\n  let best = values[0];\n  for (let i = 1; i < values.length; i++) {\n    if (compare(values[i], best) > 0) best = values[i];\n  }\n  return best;\n}\n\nexport function clamp(value: unknown, lo: unknown, hi: unknown): unknown {\n  if (compare(value, lo) < 0) return lo;\n  if (compare(value, hi) > 0) return hi;\n  return value;\n}\n\nexport function isBetween(value: unknown, lo: unknown, hi: unknown): boolean {\n  return compare(value, lo) >= 0 && compare(value, hi) <= 0;\n}\n\n// Semantic helpers — same-day/week/month/quarter/year tests. Useful for\n// UI (\"is this event today?\") and for grouping/aggregation. All take a\n// reference value to compare against; the \"isToday\" / \"isTomorrow\" /\n// \"isYesterday\" variants compute the reference from the current system\n// date themselves so callers don't have to.\nfunction readYearMonthDay(value: unknown): { year: number; month: number; day: number } {\n  const v = asDateFieldView(value);\n  return { year: v.year!, month: v.month!, day: v.day! };\n}\n\nfunction todayYearMonthDay(): { year: number; month: number; day: number } {\n  const now = new Date();\n  return { year: now.getFullYear(), month: now.getMonth() + 1, day: now.getDate() };\n}\n\nfunction dateEqualYearMonthDay(a: { year: number; month: number; day: number }, b: { year: number; month: number; day: number }): boolean {\n  return a.year === b.year && a.month === b.month && a.day === b.day;\n}\n\nexport function isSameDay(value: unknown, reference: unknown): boolean {\n  return dateEqualYearMonthDay(readYearMonthDay(value), readYearMonthDay(reference));\n}\n\nexport function isToday(value: unknown): boolean {\n  return dateEqualYearMonthDay(readYearMonthDay(value), todayYearMonthDay());\n}\n\nfunction tomorrowYearMonthDay(): { year: number; month: number; day: number } {\n  const d = new Date();\n  d.setDate(d.getDate() + 1);\n  return { year: d.getFullYear(), month: d.getMonth() + 1, day: d.getDate() };\n}\n\nfunction yesterdayYearMonthDay(): { year: number; month: number; day: number } {\n  const d = new Date();\n  d.setDate(d.getDate() - 1);\n  return { year: d.getFullYear(), month: d.getMonth() + 1, day: d.getDate() };\n}\n\nexport function isTomorrow(value: unknown): boolean {\n  return dateEqualYearMonthDay(readYearMonthDay(value), tomorrowYearMonthDay());\n}\n\nexport function isYesterday(value: unknown): boolean {\n  return dateEqualYearMonthDay(readYearMonthDay(value), yesterdayYearMonthDay());\n}\n\nfunction sameWeek(yearA: number, monthA: number, dayA: number, yearB: number, monthB: number, dayB: number): boolean {\n  // Same week iff the dates are within 7 days of each other AND the earlier\n  // one's weekday is ≤ the later one's weekday (so we don't say \"Sun and\n  // the following Mon are in the same week\" — ISO weeks run Mon-Sun).\n  // Easier: compute ISO week numbers via isoWeekYearAndWeek, compare both\n  // year and week. That handles the year-boundary case (Dec 31 vs Jan 1 of\n  // the next year, which can be in the same ISO week).\n  // Local import to avoid module-cycle: isoWeek.ts doesn't import from here.\n  // Lazy require-style dynamic via inline static import at top would be\n  // cleaner; this inline computation is fine for a pure helper.\n  // ...actually let's just compute weekday offsets directly. Same-ISO-week\n  // iff |d1 - d2| < 7 days AND the earlier date's ISO weekday ≤ the later\n  // date's ISO weekday so they fall in the same Mon-Sun span.\n  const daysSince = (y: number, m: number, d: number): number => {\n    // daysFromCivil: O(1), correct for negative years. (The inlined\n    // formula this replaced was the one remaining copy of the\n    // Math.floor-of-offset era bug — see daysFromCivil's comment.)\n    return daysFromCivil(y, m, d);\n  };\n  const a = daysSince(yearA, monthA, dayA);\n  const b = daysSince(yearB, monthB, dayB);\n  if (Math.abs(a - b) >= 7) return false;\n  // Same week iff both dates round to the same Monday. Compute the\n  // Monday-of-week for each: subtract (weekday - 1) days, where weekday\n  // is 1=Mon..7=Sun. Use the standard Zeller formula for weekday.\n  const weekdayOf = (y: number, m: number, d: number): number => {\n    // O(1) proleptic-Gregorian weekday from isoWeek.ts's dayOfWeekFromCivil.\n    // The old Date.UTC(y, m-1, d) form remapped years 0-99 to 1900-1999\n    // (ECMAScript spec), computing the weekday of the wrong century for\n    // first-century dates.\n    return dayOfWeekFromCivil(y, m, d);\n  };\n  const wa = a - (weekdayOf(yearA, monthA, dayA) - 1);\n  const wb = b - (weekdayOf(yearB, monthB, dayB) - 1);\n  return wa === wb;\n}\n\nexport function isSameWeek(value: unknown, reference: unknown): boolean {\n  const a = readYearMonthDay(value);\n  const b = readYearMonthDay(reference);\n  return sameWeek(a.year, a.month, a.day, b.year, b.month, b.day);\n}\n\nexport function isSameMonth(value: unknown, reference: unknown): boolean {\n  const a = readYearMonthDay(value);\n  const b = readYearMonthDay(reference);\n  return a.year === b.year && a.month === b.month;\n}\n\nexport function isSameQuarter(value: unknown, reference: unknown): boolean {\n  const a = readYearMonthDay(value);\n  const b = readYearMonthDay(reference);\n  return a.year === b.year && Math.ceil(a.month / 3) === Math.ceil(b.month / 3);\n}\n\nexport function isSameYear(value: unknown, reference: unknown): boolean {\n  return readYearMonthDay(value).year === readYearMonthDay(reference).year;\n}\n\n// isWeekend / isWeekday depend on dayOfWeek — present on PlainDate,\n// PlainDateTime, ZonedDateTime, but NOT on PlainTime. Callers passing\n// PlainTime get a descriptive throw. Doesn't call asDateFieldView\n// because that would reject PlainTime (no year/month/day) before\n// reaching the dayOfWeek check — and the error we want here is the\n// \"no dayOfWeek field\" one, not the \"no date fields\" one.\nexport function isWeekend(value: unknown): boolean {\n  if (typeof value !== 'object' || value === null) {\n    throw new Error(`temporal-fmt: isWeekend() expected a Temporal value, got ${String(value)}.`);\n  }\n  const v = value as { dayOfWeek?: unknown };\n  if (typeof v.dayOfWeek !== 'number') {\n    throw new Error(\n      `temporal-fmt: isWeekend() needs a value with a dayOfWeek field (PlainDate / PlainDateTime / ZonedDateTime).`\n    );\n  }\n  // 6=Sat, 7=Sun in Temporal's Mon=1..Sun=7 numbering.\n  return v.dayOfWeek === 6 || v.dayOfWeek === 7;\n}\n\nexport function isWeekday(value: unknown): boolean {\n  return !isWeekend(value);\n}\n"],"mappings":"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","names":["day","advanced"]}