UNPKG

@sanity/util

Version:

Utilities shared across projects of Sanity

1 lines • 24.5 kB
{"version":3,"file":"legacyDateFormat.mjs","sources":["../src/datetime-formatter/sanitizeLocale.ts","../src/datetime-formatter/formatter.ts","../src/datetime-formatter/momentToDateFnsFormat.ts","../src/legacyDateFormat.ts"],"sourcesContent":["// this is used to avoid issues with the Intl.DateTimeFormat constructor as part of the efps tests\nconst sanitizeLocale = (locale: string): string => locale.replace(/@posix$/, '')\n\nexport default sanitizeLocale\n","import {format} from 'date-fns'\n\nimport sanitizeLocale from './sanitizeLocale'\n\nfunction getMonthName(\n date: Date,\n style: 'long' | 'short' | 'narrow' | undefined = 'long',\n locale = 'en-US',\n): string {\n const validLocale = sanitizeLocale(locale)\n return new Intl.DateTimeFormat(validLocale, {month: style}).format(date)\n}\n\nfunction getDayName(\n date: Date,\n style: 'long' | 'short' | 'narrow' | undefined = 'long',\n locale = 'en-US',\n): string {\n const validLocale = sanitizeLocale(locale)\n return new Intl.DateTimeFormat(validLocale, {weekday: style}).format(date)\n}\n\nfunction getLocalizedDate(date: Date, options: Intl.DateTimeFormatOptions, locale = 'en-US') {\n const validLocale = sanitizeLocale(locale)\n return new Intl.DateTimeFormat(validLocale, options).format(date)\n}\n\n/**\n * Zero-pads a number to `length` digits (e.g. zeroPad(7, 2) = \"07\").\n */\nfunction zeroPad(num: number, length: number): string {\n return String(num).padStart(length, '0')\n}\n\n/**\n * Returns an English ordinal for a given day number\n */\nfunction getOrdinal(day: number): string {\n const j = day % 10\n const k = day % 100\n if (j === 1 && k !== 11) return `${day}st`\n if (j === 2 && k !== 12) return `${day}nd`\n if (j === 3 && k !== 13) return `${day}rd`\n return `${day}th`\n}\n\nfunction getISODayOfWeek(date: Date): number {\n // Sunday=0 in JS, but ISO calls Monday=1...Sunday=7\n const dow = date.getDay()\n return dow === 0 ? 7 : dow\n}\n\nfunction getISOWeekYear(date: Date): number {\n // Clone date, shift to the \"Thursday\" of this week\n const temp = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()))\n const dayOfWeek = getISODayOfWeek(temp)\n temp.setUTCDate(temp.getUTCDate() - dayOfWeek + 4)\n return temp.getUTCFullYear()\n}\n\nfunction getISOWeekNumber(date: Date): number {\n const temp = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()))\n const dayOfWeek = getISODayOfWeek(temp)\n temp.setUTCDate(temp.getUTCDate() - dayOfWeek + 4)\n const yearStart = new Date(Date.UTC(temp.getUTCFullYear(), 0, 1))\n return Math.ceil(((temp.valueOf() - yearStart.valueOf()) / 86400000 + 1) / 7)\n}\n\nfunction getDayOfYear(date: Date): number {\n const startOfYear = new Date(Date.UTC(date.getFullYear(), 0, 1))\n // fix for local-time differences\n const diff =\n date.valueOf() -\n startOfYear.valueOf() +\n (startOfYear.getTimezoneOffset() - date.getTimezoneOffset()) * 60_000\n return Math.floor(diff / (1000 * 60 * 60 * 24)) + 1\n}\n\n// \"Locale\" week-year => approximate with ISO logic here\nfunction getLocaleWeekYear(date: Date): number {\n return getISOWeekYear(date)\n}\n\n/**\n * Returns fractional seconds based on the count of 'S' in the token.\n */\nfunction getFractionalSeconds(date: Date, length: number): string {\n const ms = zeroPad(date.getMilliseconds(), 3) // \"123\"\n if (length === 1) {\n return ms.slice(0, 1) // \"1\"\n } else if (length === 2) {\n return ms.slice(0, 2) // \"12\"\n } else if (length === 3) {\n return ms // \"123\"\n }\n // length=4 => e.g. \"1230\"\n return `${ms}0`\n}\n\nfunction getTimeZoneAbbreviation(date: Date) {\n const parts = new Intl.DateTimeFormat(sanitizeLocale('en-US'), {\n timeZoneName: 'short',\n }).formatToParts(date)\n const tz = parts.find((part) => part.type === 'timeZoneName')\n return tz ? tz.value : ''\n}\n\n/**\n * Formats a Date object using many Moment-like tokens.\n */\nfunction formatMomentLike(date: Date, formatStr: string): string {\n // Store escaped sequences to restore later\n const escapeSequences: string[] = []\n const escapeToken = '\\uE000' // Use a Unicode private use character as placeholder\n\n // Replace bracketed content with placeholders\n const processedFormat = formatStr.replace(/\\[([^\\]]+)\\]/g, (_, contents) => {\n escapeSequences.push(contents)\n return escapeToken\n })\n\n // Basic fields\n const year = date.getFullYear()\n const monthIndex = date.getMonth() // 0..11\n const dayOfMonth = date.getDate() // 1..31\n const dayOfWeek = date.getDay() // 0..6 (Sun=0)\n const hours = date.getHours() // 0..23\n const minutes = date.getMinutes() // 0..59\n const seconds = date.getSeconds() // 0..59\n\n // Week-related\n const isoWeekNum = getISOWeekNumber(date)\n const isoWeekYear = getISOWeekYear(date)\n const localeWeekYear = getLocaleWeekYear(date)\n\n // Timestamps\n const unixMs = date.getTime() // milliseconds since epoch\n const unixSec = Math.floor(unixMs / 1000) // seconds since epoch\n\n // Build token -> value map\n const tokens = [\n // Year\n // 1970 1971 ... 2029 2030\n {key: 'YYYY', getValue: () => String(year)},\n // 70 71 ... 29 30\n {key: 'YY', getValue: () => String(year).slice(-2)},\n // 1970 1971 ... 9999 +10000 +10001\n {key: 'Y', getValue: () => String(year)},\n // Expanded years, -001970 -001971 ... +001907 +001971\n {key: 'YYYYY', getValue: () => zeroPad(year, 5)},\n\n // ISO week-year\n // 1970 1971 ... 2029 2030\n {key: 'GGGG', getValue: () => String(isoWeekYear)},\n // 70 71 ... 29 30\n {key: 'GG', getValue: () => String(isoWeekYear).slice(-2)},\n\n // \"locale\" week-year\n {key: 'gggg', getValue: () => String(localeWeekYear)},\n {key: 'gg', getValue: () => String(localeWeekYear).slice(-2)},\n\n // Quarter\n {key: 'Q', getValue: () => String(Math.floor(monthIndex / 3) + 1)},\n {key: 'Qo', getValue: () => getOrdinal(Math.floor(monthIndex / 3) + 1)},\n\n // --- Month (using Intl) ---\n {key: 'MMMM', getValue: () => getMonthName(date, 'long')}, // e.g. \"January\"\n {key: 'MMM', getValue: () => getMonthName(date, 'short')}, // e.g. \"Jan\"\n // For numeric months, we still do a manual approach:\n {key: 'MM', getValue: () => zeroPad(monthIndex + 1, 2)},\n {key: 'M', getValue: () => String(monthIndex + 1)},\n {key: 'Mo', getValue: () => getOrdinal(monthIndex + 1)},\n\n // Day of Month\n {key: 'DD', getValue: () => zeroPad(dayOfMonth, 2)},\n {key: 'D', getValue: () => String(dayOfMonth)},\n {key: 'Do', getValue: () => getOrdinal(dayOfMonth)},\n\n // --- Day of Week (using Intl) ---\n {key: 'dddd', getValue: () => getDayName(date, 'long')}, // e.g. \"Monday\"\n {key: 'ddd', getValue: () => getDayName(date, 'short')}, // e.g. \"Mon\"\n {\n key: 'dd',\n // e.g. \"Mo\" => first 2 chars of short day name\n getValue: () => getDayName(date, 'short').slice(0, 2),\n },\n {key: 'd', getValue: () => String(dayOfWeek)},\n {key: 'do', getValue: () => getOrdinal(dayOfWeek + 1)},\n\n // Day of the year\n {key: 'DDDD', getValue: () => zeroPad(getDayOfYear(date), 3)},\n {key: 'DDD', getValue: () => String(getDayOfYear(date))},\n {key: 'DDDo', getValue: () => getOrdinal(getDayOfYear(date))},\n\n // ISO day of week\n {key: 'E', getValue: () => String(getISODayOfWeek(date))},\n\n // Week of the year\n // w 1 2 ... 52 53\n {key: 'w', getValue: () => zeroPad(isoWeekNum, 2)},\n // week 1st 2nd ... 52nd 53rd\n {key: 'wo', getValue: () => getOrdinal(isoWeekNum)},\n // 01 02 ... 52 53\n {key: 'ww', getValue: () => zeroPad(isoWeekNum, 2)},\n\n // ISO Week\n {key: 'WW', getValue: () => zeroPad(isoWeekNum, 2)},\n {key: 'W', getValue: () => String(isoWeekNum)},\n {key: 'Wo', getValue: () => getOrdinal(isoWeekNum)},\n\n // or \"locale\" week => replace isoWeekNum\n\n // 24h hours\n {key: 'HH', getValue: () => zeroPad(hours, 2)},\n {key: 'H', getValue: () => String(hours)},\n\n // 12h hours\n {key: 'hh', getValue: () => zeroPad(((hours + 11) % 12) + 1, 2)},\n {key: 'h', getValue: () => String(((hours + 11) % 12) + 1)},\n\n // 1 2 ... 23 24\n {key: 'k', getValue: () => String(hours || 24)},\n // 01 02 ... 23 24\n {key: 'kk', getValue: () => zeroPad(hours || 24, 2)},\n\n // Minutes\n {key: 'mm', getValue: () => zeroPad(minutes, 2)},\n {key: 'm', getValue: () => String(minutes)},\n\n // Seconds\n {key: 'ss', getValue: () => zeroPad(seconds, 2)},\n {key: 's', getValue: () => String(seconds)},\n\n // Fractional seconds (S..SSSS) => handled separately\n // Timezone offset (Z, ZZ) => handled separately\n\n // AM/PM\n {key: 'A', getValue: () => (hours < 12 ? 'AM' : 'PM')},\n {key: 'a', getValue: () => (hours < 12 ? 'am' : 'pm')},\n\n // Unix timestamps\n {key: 'X', getValue: () => String(unixSec)},\n {key: 'x', getValue: () => String(unixMs)},\n\n // Eras BC AD\n {key: 'N', getValue: () => (year < 0 ? 'BC' : 'AD')},\n {key: 'NN', getValue: () => (year < 0 ? 'BC' : 'AD')},\n {key: 'NNN', getValue: () => (year < 0 ? 'BC' : 'AD')},\n\n // Before Christ, Anno Domini\n {key: 'NNNN', getValue: () => (year < 0 ? 'Before Christ' : 'Anno Domini')},\n {key: 'NNNNN', getValue: () => (year < 0 ? 'BC' : 'AD')},\n\n // Time zone offset\n {key: 'z', getValue: () => getTimeZoneAbbreviation(date)},\n {key: 'zz', getValue: () => getTimeZoneAbbreviation(date)},\n {key: 'Z', getValue: () => format(date, 'xxx')},\n {key: 'ZZ', getValue: () => format(date, 'xx')},\n\n // Time\n {key: 'LTS', getValue: () => getLocalizedDate(date, {timeStyle: 'medium'})},\n {key: 'LT', getValue: () => getLocalizedDate(date, {timeStyle: 'short'})},\n\n // Date (uppercase = longer names)\n {\n key: 'LLLL',\n getValue: () =>\n getLocalizedDate(date, {\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n }),\n },\n {\n key: 'LLL',\n getValue: () =>\n getLocalizedDate(date, {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n }),\n },\n {\n key: 'LL',\n getValue: () => getLocalizedDate(date, {year: 'numeric', month: 'long', day: 'numeric'}),\n },\n {\n key: 'L',\n getValue: () => getLocalizedDate(date, {year: 'numeric', month: '2-digit', day: '2-digit'}),\n },\n\n // Date (lowercase = shorter names)\n {\n key: 'llll',\n getValue: () =>\n getLocalizedDate(date, {\n weekday: 'short',\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n }),\n },\n {\n key: 'lll',\n getValue: () =>\n getLocalizedDate(date, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n }),\n },\n {\n key: 'll',\n getValue: () => getLocalizedDate(date, {year: 'numeric', month: 'short', day: 'numeric'}),\n },\n {\n key: 'l',\n getValue: () => getLocalizedDate(date, {year: 'numeric', month: 'numeric', day: 'numeric'}),\n },\n ]\n\n // Sort tokens by descending length to avoid partial collisions\n tokens.sort((a, b) => b.key.length - a.key.length)\n\n // 1) Fractional seconds (avoid colliding with LTS)\n const fracSecRegex = /(?<!LT)S{1,4}/g\n let output = processedFormat.replace(fracSecRegex, (match) => {\n return getFractionalSeconds(date, match.length)\n })\n\n // Find each token and replace it, make sure not to replace overlapping tokens\n for (const {key, getValue} of tokens) {\n // Escape special characters\n const escapedKey = key.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n // Match the token, but only if it's not part of a larger word\n const tokenRegex = new RegExp(`(^|[^A-Z0-9a-z])(${escapedKey})(?![A-Z0-9a-z])`, 'g')\n\n // Only compute the value if the token exists in the output\n if (output.match(tokenRegex)) {\n const value = getValue()\n output = output.replace(tokenRegex, `$1${value}`)\n }\n }\n\n // After all token replacements, restore escaped sequences\n output = output.replace(new RegExp(escapeToken, 'g'), () => escapeSequences.shift() || '')\n\n return output\n}\n\nexport default formatMomentLike\n","/**\n * Converts a Moment.js format string into a UTS 35 (Unicode Technical Standard #35)\n * format string\n *\n * This function doesn't take absolutely every token into account, but should cover\n * all common cases. If you find a missing token, feel free to add it.\n *\n */\nexport function momentToDateFnsFormat(momentFormat: string): string {\n // A list of replacements from Moment tokens to date-fns tokens\n // ordered from longest to shortest to prevent partial replacements\n const formatMap: Record<string, string> = {\n YYYY: 'yyyy',\n YY: 'yy',\n MMMM: 'MMMM',\n MMM: 'MMM',\n MM: 'MM',\n M: 'M',\n DD: 'dd',\n D: 'd',\n dddd: 'EEEE',\n ddd: 'EEE',\n HH: 'HH',\n H: 'H',\n hh: 'hh',\n h: 'h',\n mm: 'mm',\n m: 'm',\n ss: 'ss',\n s: 's',\n A: 'a',\n a: 'a',\n }\n\n // Replace each token in the format string\n return Object.keys(formatMap).reduce(\n (acc, key) => acc.replace(new RegExp(key, 'g'), formatMap[key]),\n momentFormat,\n )\n}\n","import {TZDateMini} from '@date-fns/tz'\nimport {UTCDateMini} from '@date-fns/utc'\nimport {parse as dateFnsParse, parseISO} from 'date-fns'\n\nimport formatMomentLike from './datetime-formatter/formatter'\nimport {momentToDateFnsFormat} from './datetime-formatter/momentToDateFnsFormat'\nimport sanitizeLocale from './datetime-formatter/sanitizeLocale'\n\nexport {sanitizeLocale}\n\nexport const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD'\nexport const DEFAULT_TIME_FORMAT = 'HH:mm'\n// take local as default time zone\nconst DEFAULT_TIMEZONE = Intl.DateTimeFormat().resolvedOptions().timeZone\n\nexport type ParseResult = {isValid: boolean; date?: Date; error?: string} & (\n | {isValid: true; date: Date}\n | {isValid: false; error?: string}\n)\n\nexport function format(\n input: Date,\n dateFormat: string,\n options: {useUTC?: boolean; timeZone?: string} = {useUTC: false, timeZone: undefined},\n): string {\n const {useUTC, timeZone} = options\n\n if (useUTC) return formatMomentLike(new UTCDateMini(input), dateFormat)\n return formatMomentLike(\n timeZone ? new TZDateMini(input, timeZone || DEFAULT_TIMEZONE) : new Date(input),\n dateFormat,\n )\n}\n\n/*\n It would be so good to remove date-fns from this file, but it's used in the parse function. We could write our own parser,\n but this is better than moment.\n */\nexport function parse(dateString: string, dateFormat?: string, timeZone?: string): ParseResult {\n const dnsFormat = dateFormat ? momentToDateFnsFormat(dateFormat) : undefined\n\n // parse string to date using the format string from date-fns\n const parsed = dnsFormat ? dateFnsParse(dateString, dnsFormat, new Date()) : parseISO(dateString)\n if (parsed && !isNaN(parsed.getTime())) {\n const parsedDate =\n timeZone && isValidTimeZoneString(timeZone) ? new TZDateMini(parsed, timeZone) : parsed\n return {isValid: true, date: parsedDate}\n }\n return {isValid: false, error: `Invalid date. Must be on the format \"${dateFormat}\"`}\n}\n\nexport function isValidTimeZoneString(timeZone: string): boolean {\n return Intl.supportedValuesOf('timeZone').includes(timeZone)\n}\n"],"names":["format","dateFnsParse"],"mappings":"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"}