{"version":3,"sources":["../src/parse.ts"],"sourcesContent":["import { date } from \"./date\"\nimport { validate, styles, fixedLength, four, two, validOffset, fixedLengthByOffset, offsetToSecs, TimezoneToken } from \"./common\"\nimport { formatStr } from \"./formatStr\"\nimport { fourDigitYear } from \"./fourDigitYear\"\nimport { ap } from \"./ap\"\nimport { range } from \"./range\"\nimport { monthDays } from \"./monthDays\"\nimport { parts } from \"./parts\"\nimport type {\n  ParseOptions,\n  Format,\n  Part,\n  FormatStyle,\n  FilledPart,\n  FormatToken,\n} from \"./types\"\n\nexport function parse(options: ParseOptions): Date | never\nexport function parse(\n  dateStr: string,\n  format?: Format,\n  locale?: string\n): Date | never\n/**\n * Parses a date string into a Date object using the given format.\n * @param dateStr - A string representing a date.\n * @param format - The format the given string is in.\n * @param locale - The locale to parse the string from.\n */\nexport function parse(\n  dateStrOrOptions: string | ParseOptions,\n  format: Format = \"ISO8601\",\n  locale = \"device\"\n): Date | never {\n  let partFilter: (part: Part) => boolean = () => true\n  let dateStr: string\n  let dateOverflow = \"backward\"\n  if (typeof dateStrOrOptions === \"object\") {\n    ;({\n      date: dateStr,\n      format = \"ISO8601\",\n      locale = \"device\",\n      dateOverflow = \"backward\",\n      partFilter = () => true,\n    } = dateStrOrOptions)\n  } else {\n    dateStr = dateStrOrOptions\n  }\n  if (!dateStr) throw new Error(\"parse() requires a date string.\")\n  const invalid = (): never => {\n    throw new Error(\n      `Date (${dateStr}) does not match format (${formatStr(format, locale)})`\n    )\n  }\n  if (format === \"ISO8601\") return date(dateStr)\n  const genitive =\n    styles.includes(format as FormatStyle) || typeof format === \"object\"\n  const formatParts = validate(parts(format, locale).filter(partFilter))\n  if (!formatParts.length) throw new Error(\"parse() requires a pattern.\")\n  let parsedParts\n  try {\n    parsedParts = parseParts(dateStr, formatParts)\n  } catch {\n    return invalid()\n  }\n  const now = new Date()\n  const parsed = new Map([\n    [\"YYYY\", now.getFullYear()],\n    [\"MM\", now.getMonth() + 1],\n    [\"DD\", now.getDate()],\n    [\"HH\", 0],\n    [\"mm\", 0],\n    [\"ss\", 0],\n    [\"SSS\", 0],\n  ])\n  let a: null | boolean = null\n  let offset = \"\"\n  parsedParts.forEach((part): void | never => {\n    if (part.partName === \"literal\") return\n    if (part.token === part.value) return invalid()\n    const v = Number(part.value)\n    // Handle SSS specially - convert variable-length fractional seconds to milliseconds\n    if (part.token === \"SSS\") {\n      // \"1\" -> 100, \"12\" -> 120, \"123\" -> 123, \"123456\" -> 123\n      const digits = part.value.padEnd(3, \"0\").slice(0, 3)\n      parsed.set(\"SSS\", Number(digits))\n    } else if (parsed.has(part.token)) {\n      // Parse for YYYY, MM, DD, HH, hh, mm, ss\n      parsed.set(part.token, v)\n    } else if (part.token === \"YY\") {\n      // Parse for YY\n      parsed.set(\"YYYY\", fourDigitYear(part.value))\n    } else {\n      /* MMM - Short name Jan-Dec\n       * MMMM - Full name January - December\n       * h - Minimum hour digits, 12 hour clock, 1-12\n       * hh - 2 hour digits, 12 hour clock, 01-12\n       * m - The minute 0-59\n       * mm - The minute 00-12\n       * s - The second 0-59\n       * a - am/pm\n       * A - AM/PM\n       */\n      const t = part.token\n      if (t.startsWith(\"d\")) {\n        // d, ddd, dddd — we just ignore these because they are non specific\n        return\n      } else if (t === \"D\") {\n        parsed.set(\"DD\", v)\n      } else if (t === \"H\" || t.startsWith(\"h\")) {\n        parsed.set(\"HH\", v)\n      } else if (t === \"M\") {\n        parsed.set(\"MM\", v)\n      } else if (t === \"a\" || t === \"A\") {\n        a = part.value.toLowerCase() === ap(\"am\", locale).toLowerCase()\n      } else if (t === \"Z\" || t === \"ZZ\") {\n        offset = validOffset(part.value, t)\n      } else {\n        const values = range(t as FormatToken, locale, genitive)\n        const index = values.indexOf(part.value)\n        if (index !== -1) {\n          switch (t) {\n            case \"MMM\":\n            case \"MMMM\":\n              parsed.set(\"MM\", index + 1)\n              break\n          }\n        }\n      }\n    }\n  })\n  let hours = parsed.get(\"HH\") || 0\n  if (a === false) {\n    hours += hours === 12 ? 0 : 12\n    parsed.set(\"HH\", hours === 24 ? 0 : hours)\n  } else if (a === true && hours === 12) {\n    // 12am === 00 in 24 hour clock.\n    parsed.set(\"HH\", 0)\n  }\n  parsed.set(\"MM\", (parsed.get(\"MM\") || 1) - 1)\n  // eslint-disable-next-line prefer-const\n  let [Y, M, D, h, m, s, ms] = Array.from(parsed.values())\n\n  // Determine if the date is valid for the month.\n  const maxDaysInMonth = monthDays(new Date(`${four(Y)}-${two(M + 1)}-10`))\n  if (maxDaysInMonth < D && dateOverflow === \"throw\")\n    throw new Error(`Invalid date ${four(Y)}-${two(M + 1)}-${two(D)}`)\n  D = dateOverflow === \"backward\" ? Math.min(D, maxDaysInMonth) : D\n\n  // Create the date.\n  // If there's an offset, we need to handle it manually because JavaScript's Date\n  // doesn't support seconds in timezone offsets (e.g., -05:32:11).\n  const msStr = String(ms).padStart(3, \"0\")\n  if (offset) {\n    // Create the date in UTC, then apply the offset manually\n    const isoStringUtc = `${four(Y)}-${two(M + 1)}-${two(D)}T${two(h)}:${two(m)}:${two(s)}.${msStr}Z`\n    const d = new Date(isoStringUtc)\n    if (!isFinite(+d)) return invalid()\n\n    const len = fixedLengthByOffset(offset)\n    const token: TimezoneToken = len === 5 || len === 8 ? \"ZZ\" : \"Z\"\n    const offsetSecs = offsetToSecs(offset, token)\n    return new Date(d.getTime() - offsetSecs * 1000)\n  }\n\n  // No offset - create date in local time (original behavior)\n  const isoString = `${four(Y)}-${two(M + 1)}-${two(D)}T${two(h)}:${two(m)}:${two(s)}.${msStr}`\n  const d = new Date(isoString)\n  if (isFinite(+d)) return d\n  return invalid()\n}\n\n/**\n * Given a string date and corresponding format parts, fill the parts with the\n * data from the string.\n * @param dateStr - A string to parse.\n * @param formatParts - The expected parts of the given string.\n */\nexport function parseParts(dateStr: string, formatParts: Part[]): FilledPart[] {\n  let i = 0\n  const advance = (parts: Part[]): [Part, Part | undefined] => [\n    parts[i++],\n    parts[i],\n  ]\n  let pos = 0\n  const parsed: FilledPart[] = []\n  let n: undefined | Part = undefined\n  do {\n    const [current, next] = advance(formatParts)\n    n = next\n    let len = 1\n    if (current.partName === \"literal\") {\n      // Literals can be discarded\n      len = current.partValue.length\n    } else if (current.partName === \"timeZoneName\") {\n      len = fixedLengthByOffset(dateStr.substring(pos))\n    } else if (current.token === \"SSS\") {\n      // Variable length: consume all consecutive digits (gracious parsing)\n      let end = pos\n      while (end < dateStr.length && /\\d/.test(dateStr.charAt(end))) {\n        end++\n      }\n      len = end - pos\n    } else if (current.token in fixedLength) {\n      // Fixed length parse\n      len = fixedLength[current.token as keyof typeof fixedLength]\n    } else if (next) {\n      // Variable length parse.\n      if (next.partName === \"literal\") {\n        len = dateStr.indexOf(next.partValue, pos) - pos\n        if (len < 0) throw new Error()\n      } else if (next.partName === \"dayPeriod\") {\n        // Our validator is ensuring that the current item must be a variable\n        // length number. We need to extract it.\n        for (let i = 1; i <= 4; i++) {\n          if (isNaN(Number(dateStr.charAt(pos + i)))) {\n            len = i\n            break\n          }\n        }\n      } else {\n        // Our validator guarantees the next is either not a number or it\n        // will be the end of the string\n        const nextChar = dateStr.substring(pos).search(/\\d/)\n        if (nextChar !== -1) len = pos + nextChar\n      }\n    } else {\n      len = dateStr.length\n    }\n\n    parsed.push({ ...current, value: dateStr.substring(pos, pos + len) })\n    pos += len\n  } while (n)\n  return parsed\n}\n"],"mappings":"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","names":["d","parts","i"]}