{"version":3,"file":"day.mjs","names":[],"sources":["../../../../package/common/utils/day.ts"],"sourcesContent":["// A day is a `'YYYY-MM-DD'` string, the value of `<input type=\"date\">`: no time and no time zone,\n// so it is the same day for everyone. A `Date` is a moment and cannot be one.\n//\n// Dates are built with `setFullYear` rather than the `Date` constructor or `Date.UTC`, which read\n// the years 0 to 99 as 1900 to 1999.\n\nexport interface DayParts {\n  year: number;\n  /** 1 to 12. */\n  month: number;\n  day: number;\n}\n\nconst DAY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nexport function daysInMonth({ year, month }: Pick<DayParts, 'year' | 'month'>): number {\n  const date = new Date(0);\n  date.setUTCFullYear(year, month, 0);\n  return date.getUTCDate();\n}\n\n/** The parts of a `'YYYY-MM-DD'` string, or `null` for anything else, 31 February included. */\nexport function parseDay(value: unknown): DayParts | null {\n  if (typeof value !== 'string') return null;\n  const match = DAY.exec(value);\n  if (!match) return null;\n  const year = Number(match[1]);\n  const month = Number(match[2]);\n  const day = Number(match[3]);\n  if (month < 1 || month > 12 || day < 1 || day > daysInMonth({ year, month })) return null;\n  return { year, month, day };\n}\n\n/** `value` itself when it is a `'YYYY-MM-DD'` day that exists, otherwise `null`. */\nexport function asDay(value: unknown): string | null {\n  return parseDay(value) ? (value as string) : null;\n}\n\nexport function formatDay({ year, month, day }: DayParts): string {\n  return `${String(year).padStart(4, '0')}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;\n}\n\n/** The day `date` falls on in the browser's time zone, as `'YYYY-MM-DD'`; `''` for an Invalid Date. */\nexport function dateToDay(date: Date): string {\n  if (Number.isNaN(date.getTime())) return '';\n  return formatDay({ year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate() });\n}\n\n/** The first moment of a `'YYYY-MM-DD'` day in the browser's time zone. An Invalid Date for anything else. */\nexport function dayToDate(day: string): Date {\n  const parts = parseDay(day);\n  if (!parts) return new Date(NaN);\n  const date = new Date(2000, 0, 1);\n  date.setFullYear(parts.year, parts.month - 1, parts.day);\n  return date;\n}\n\nconst TIME = /^(\\d{2}):(\\d{2})$/;\n\n/** The `'HH:MM'` of `date` in the browser's time zone, the value a TimeInput holds; `''` for an Invalid Date. */\nexport function dateToTime(date: Date): string {\n  if (Number.isNaN(date.getTime())) return '';\n  return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;\n}\n\n/**\n * The moment a `'YYYY-MM-DD'` day and an `'HH:MM'` time stand for in the browser's time zone,\n * DatePicker's and TimeInput's values together. A time the clock skips that day resolves forwards\n * (02:30 becomes 03:30), a repeated one to its first occurrence. An Invalid Date for anything else.\n */\nexport function dayTimeToDate(day: string, time: string): Date {\n  const date = dayToDate(day);\n  const match = TIME.exec(time);\n  const hours = match ? Number(match[1]) : NaN;\n  const minutes = match ? Number(match[2]) : NaN;\n  if (Number.isNaN(date.getTime()) || !(hours <= 23 && minutes <= 59)) return new Date(NaN);\n  date.setHours(hours, minutes, 0, 0);\n  return date;\n}\n"],"mappings":"aAaA,IAAM,EAAM,4BAEZ,SAAgB,EAAY,CAAE,OAAM,SAAmD,CACrF,IAAM,EAAO,IAAI,KAAK,CAAC,EAEvB,OADA,EAAK,eAAe,EAAM,EAAO,CAAC,EAC3B,EAAK,WAAW,CACzB,CAGA,SAAgB,EAAS,EAAiC,CACxD,GAAI,OAAO,GAAU,SAAU,OAAO,KACtC,IAAM,EAAQ,EAAI,KAAK,CAAK,EAC5B,GAAI,CAAC,EAAO,OAAO,KACnB,IAAM,EAAO,OAAO,EAAM,EAAE,EACtB,EAAQ,OAAO,EAAM,EAAE,EACvB,EAAM,OAAO,EAAM,EAAE,EAE3B,OADI,EAAQ,GAAK,EAAQ,IAAM,EAAM,GAAK,EAAM,EAAY,CAAE,OAAM,OAAM,CAAC,EAAU,KAC9E,CAAE,OAAM,QAAO,KAAI,CAC5B,CAGA,SAAgB,EAAM,EAA+B,CACnD,OAAO,EAAS,CAAK,EAAK,EAAmB,IAC/C,CAEA,SAAgB,EAAU,CAAE,OAAM,QAAO,OAAyB,CAChE,MAAO,GAAG,OAAO,CAAI,CAAC,CAAC,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,CAAK,CAAC,CAAC,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,CAAG,CAAC,CAAC,SAAS,EAAG,GAAG,GAC1G,CAGA,SAAgB,EAAU,EAAoB,CAE5C,OADI,OAAO,MAAM,EAAK,QAAQ,CAAC,EAAU,GAClC,EAAU,CAAE,KAAM,EAAK,YAAY,EAAG,MAAO,EAAK,SAAS,EAAI,EAAG,IAAK,EAAK,QAAQ,CAAE,CAAC,CAChG,CAGA,SAAgB,EAAU,EAAmB,CAC3C,IAAM,EAAQ,EAAS,CAAG,EAC1B,GAAI,CAAC,EAAO,OAAO,IAAI,KAAK,GAAG,EAC/B,IAAM,EAAO,IAAI,KAAK,IAAM,EAAG,CAAC,EAEhC,OADA,EAAK,YAAY,EAAM,KAAM,EAAM,MAAQ,EAAG,EAAM,GAAG,EAChD,CACT,CAEA,IAAM,EAAO,oBAGb,SAAgB,EAAW,EAAoB,CAE7C,OADI,OAAO,MAAM,EAAK,QAAQ,CAAC,EAAU,GAClC,GAAG,OAAO,EAAK,SAAS,CAAC,CAAC,CAAC,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,EAAK,WAAW,CAAC,CAAC,CAAC,SAAS,EAAG,GAAG,GACjG,CAOA,SAAgB,EAAc,EAAa,EAAoB,CAC7D,IAAM,EAAO,EAAU,CAAG,EACpB,EAAQ,EAAK,KAAK,CAAI,EACtB,EAAQ,EAAQ,OAAO,EAAM,EAAE,EAAI,IACnC,EAAU,EAAQ,OAAO,EAAM,EAAE,EAAI,IAG3C,OAFI,OAAO,MAAM,EAAK,QAAQ,CAAC,GAAK,EAAE,GAAS,IAAM,GAAW,IAAY,IAAI,KAAK,GAAG,GACxF,EAAK,SAAS,EAAO,EAAS,EAAG,CAAC,EAC3B,EACT"}