diff options
| author | 2024-04-23 00:37:58 -0400 | |
|---|---|---|
| committer | 2024-04-23 00:37:58 -0400 | |
| commit | 9b0e86a8e74768c4fe848fb5ce8d754292db4e3e (patch) | |
| tree | cfd424be8ecb68357e6e572033f08bc534bf724f /npm_assets/node_modules/luxon/src/impl | |
| parent | 393aa58f2c5afd51f92fd9bd4b6dfd0dc90cea41 (diff) | |
New upstream version 8.3.0.upstream/8.3.0upstream
Diffstat (limited to 'npm_assets/node_modules/luxon/src/impl')
| -rw-r--r-- | npm_assets/node_modules/luxon/src/impl/conversions.js | 32 | ||||
| -rw-r--r-- | npm_assets/node_modules/luxon/src/impl/diff.js | 29 | ||||
| -rw-r--r-- | npm_assets/node_modules/luxon/src/impl/digits.js | 5 | ||||
| -rw-r--r-- | npm_assets/node_modules/luxon/src/impl/english.js | 14 | ||||
| -rw-r--r-- | npm_assets/node_modules/luxon/src/impl/formats.js | 63 | ||||
| -rw-r--r-- | npm_assets/node_modules/luxon/src/impl/formatter.js | 54 | ||||
| -rw-r--r-- | npm_assets/node_modules/luxon/src/impl/locale.js | 218 | ||||
| -rw-r--r-- | npm_assets/node_modules/luxon/src/impl/regexParser.js | 122 | ||||
| -rw-r--r-- | npm_assets/node_modules/luxon/src/impl/tokenParser.js | 112 | ||||
| -rw-r--r-- | npm_assets/node_modules/luxon/src/impl/util.js | 76 | ||||
| -rw-r--r-- | npm_assets/node_modules/luxon/src/impl/zoneUtil.js | 10 |
11 files changed, 372 insertions, 363 deletions
diff --git a/npm_assets/node_modules/luxon/src/impl/conversions.js b/npm_assets/node_modules/luxon/src/impl/conversions.js index cbe7172..bfb355f 100644 --- a/npm_assets/node_modules/luxon/src/impl/conversions.js +++ b/npm_assets/node_modules/luxon/src/impl/conversions.js @@ -5,7 +5,7 @@ import { daysInYear, daysInMonth, weeksInWeekYear, - isInteger + isInteger, } from "./util.js"; import Invalid from "./invalid.js"; @@ -20,7 +20,14 @@ function unitOutOfRange(unit, value) { } function dayOfWeek(year, month, day) { - const js = new Date(Date.UTC(year, month - 1, day)).getUTCDay(); + const d = new Date(Date.UTC(year, month - 1, day)); + + if (year < 100 && year >= 0) { + d.setUTCFullYear(d.getUTCFullYear() - 1900); + } + + const js = d.getUTCDay(); + return js === 0 ? 7 : js; } @@ -30,7 +37,7 @@ function computeOrdinal(year, month, day) { function uncomputeOrdinal(year, ordinal) { const table = isLeapYear(year) ? leapLadder : nonLeapLadder, - month0 = table.findIndex(i => i < ordinal), + month0 = table.findIndex((i) => i < ordinal), day = ordinal - table[month0]; return { month: month0 + 1, day }; } @@ -57,7 +64,7 @@ export function gregorianToWeek(gregObj) { weekYear = year; } - return Object.assign({ weekYear, weekNumber, weekday }, timeObject(gregObj)); + return { weekYear, weekNumber, weekday, ...timeObject(gregObj) }; } export function weekToGregorian(weekData) { @@ -79,22 +86,19 @@ export function weekToGregorian(weekData) { } const { month, day } = uncomputeOrdinal(year, ordinal); - - return Object.assign({ year, month, day }, timeObject(weekData)); + return { year, month, day, ...timeObject(weekData) }; } export function gregorianToOrdinal(gregData) { - const { year, month, day } = gregData, - ordinal = computeOrdinal(year, month, day); - - return Object.assign({ year, ordinal }, timeObject(gregData)); + const { year, month, day } = gregData; + const ordinal = computeOrdinal(year, month, day); + return { year, ordinal, ...timeObject(gregData) }; } export function ordinalToGregorian(ordinalData) { - const { year, ordinal } = ordinalData, - { month, day } = uncomputeOrdinal(year, ordinal); - - return Object.assign({ year, month, day }, timeObject(ordinalData)); + const { year, ordinal } = ordinalData; + const { month, day } = uncomputeOrdinal(year, ordinal); + return { year, month, day, ...timeObject(ordinalData) }; } export function hasInvalidWeekData(obj) { diff --git a/npm_assets/node_modules/luxon/src/impl/diff.js b/npm_assets/node_modules/luxon/src/impl/diff.js index 1b8afb3..7fe389b 100644 --- a/npm_assets/node_modules/luxon/src/impl/diff.js +++ b/npm_assets/node_modules/luxon/src/impl/diff.js @@ -1,11 +1,7 @@ import Duration from "../duration.js"; function dayDiff(earlier, later) { - const utcDayStart = dt => - dt - .toUTC(0, { keepLocalTime: true }) - .startOf("day") - .valueOf(), + const utcDayStart = (dt) => dt.toUTC(0, { keepLocalTime: true }).startOf("day").valueOf(), ms = utcDayStart(later) - utcDayStart(earlier); return Math.floor(Duration.fromMillis(ms).as("days")); } @@ -13,49 +9,48 @@ function dayDiff(earlier, later) { function highOrderDiffs(cursor, later, units) { const differs = [ ["years", (a, b) => b.year - a.year], - ["quarters", (a, b) => b.quarter - a.quarter], + ["quarters", (a, b) => b.quarter - a.quarter + (b.year - a.year) * 4], ["months", (a, b) => b.month - a.month + (b.year - a.year) * 12], [ "weeks", (a, b) => { const days = dayDiff(a, b); return (days - (days % 7)) / 7; - } + }, ], - ["days", dayDiff] + ["days", dayDiff], ]; const results = {}; + const earlier = cursor; let lowestOrder, highWater; for (const [unit, differ] of differs) { if (units.indexOf(unit) >= 0) { lowestOrder = unit; - let delta = differ(cursor, later); - highWater = cursor.plus({ [unit]: delta }); + results[unit] = differ(cursor, later); + highWater = earlier.plus(results); if (highWater > later) { - cursor = cursor.plus({ [unit]: delta - 1 }); - delta -= 1; + results[unit]--; + cursor = earlier.plus(results); } else { cursor = highWater; } - - results[unit] = delta; } } return [cursor, results, highWater, lowestOrder]; } -export default function(earlier, later, units, opts) { +export default function (earlier, later, units, opts) { let [cursor, results, highWater, lowestOrder] = highOrderDiffs(earlier, later, units); const remainingMillis = later - cursor; const lowerOrderUnits = units.filter( - u => ["hours", "minutes", "seconds", "milliseconds"].indexOf(u) >= 0 + (u) => ["hours", "minutes", "seconds", "milliseconds"].indexOf(u) >= 0 ); if (lowerOrderUnits.length === 0) { @@ -68,7 +63,7 @@ export default function(earlier, later, units, opts) { } } - const duration = Duration.fromObject(Object.assign(results, opts)); + const duration = Duration.fromObject(results, opts); if (lowerOrderUnits.length > 0) { return Duration.fromMillis(remainingMillis, opts) diff --git a/npm_assets/node_modules/luxon/src/impl/digits.js b/npm_assets/node_modules/luxon/src/impl/digits.js index 0d081c2..6ac1bae 100644 --- a/npm_assets/node_modules/luxon/src/impl/digits.js +++ b/npm_assets/node_modules/luxon/src/impl/digits.js @@ -19,7 +19,7 @@ const numberingSystems = { telu: "[\u0C66-\u0C6F]", thai: "[\u0E50-\u0E59]", tibt: "[\u0F20-\u0F29]", - latn: "\\d" + latn: "\\d", }; const numberingSystemsUTF16 = { @@ -41,10 +41,9 @@ const numberingSystemsUTF16 = { tamldec: [3046, 3055], telu: [3174, 3183], thai: [3664, 3673], - tibt: [3872, 3881] + tibt: [3872, 3881], }; -// eslint-disable-next-line const hanidecChars = numberingSystems.hanidec.replace(/[\[|\]]/g, "").split(""); export function parseDigits(str) { diff --git a/npm_assets/node_modules/luxon/src/impl/english.js b/npm_assets/node_modules/luxon/src/impl/english.js index 0ae2069..cf93798 100644 --- a/npm_assets/node_modules/luxon/src/impl/english.js +++ b/npm_assets/node_modules/luxon/src/impl/english.js @@ -21,7 +21,7 @@ export const monthsLong = [ "September", "October", "November", - "December" + "December", ]; export const monthsShort = [ @@ -36,7 +36,7 @@ export const monthsShort = [ "Sep", "Oct", "Nov", - "Dec" + "Dec", ]; export const monthsNarrow = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"]; @@ -65,7 +65,7 @@ export const weekdaysLong = [ "Thursday", "Friday", "Saturday", - "Sunday" + "Sunday", ]; export const weekdaysShort = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; @@ -133,7 +133,7 @@ export function formatRelativeTime(unit, count, numeric = "always", narrow = fal days: ["day", "day", "days"], hours: ["hour", "hr."], minutes: ["minute", "min."], - seconds: ["second", "sec."] + seconds: ["second", "sec."], }; const lastable = ["hours", "minutes", "seconds"].indexOf(unit) === -1; @@ -160,8 +160,8 @@ export function formatRelativeTime(unit, count, numeric = "always", narrow = fal ? lilUnits[1] : lilUnits[2] || lilUnits[1] : singular - ? units[unit][0] - : unit; + ? units[unit][0] + : unit; return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}`; } @@ -178,7 +178,7 @@ export function formatString(knownFormat) { "minute", "second", "timeZoneName", - "hour12" + "hourCycle", ]), key = stringify(filtered), dateTimeHuge = "EEEE, LLLL d, yyyy, h:mm a"; diff --git a/npm_assets/node_modules/luxon/src/impl/formats.js b/npm_assets/node_modules/luxon/src/impl/formats.js index 25210f6..f2efaad 100644 --- a/npm_assets/node_modules/luxon/src/impl/formats.js +++ b/npm_assets/node_modules/luxon/src/impl/formats.js @@ -9,119 +9,104 @@ const n = "numeric", export const DATE_SHORT = { year: n, month: n, - day: n + day: n, }; export const DATE_MED = { year: n, month: s, - day: n + day: n, }; export const DATE_MED_WITH_WEEKDAY = { year: n, month: s, day: n, - weekday: s + weekday: s, }; export const DATE_FULL = { year: n, month: l, - day: n + day: n, }; export const DATE_HUGE = { year: n, month: l, day: n, - weekday: l + weekday: l, }; export const TIME_SIMPLE = { hour: n, - minute: n + minute: n, }; export const TIME_WITH_SECONDS = { hour: n, minute: n, - second: n + second: n, }; export const TIME_WITH_SHORT_OFFSET = { hour: n, minute: n, second: n, - timeZoneName: s + timeZoneName: s, }; export const TIME_WITH_LONG_OFFSET = { hour: n, minute: n, second: n, - timeZoneName: l + timeZoneName: l, }; export const TIME_24_SIMPLE = { hour: n, minute: n, - hour12: false + hourCycle: "h23", }; -/** - * {@link toLocaleString}; format like '09:30:23', always 24-hour. - */ export const TIME_24_WITH_SECONDS = { hour: n, minute: n, second: n, - hour12: false + hourCycle: "h23", }; -/** - * {@link toLocaleString}; format like '09:30:23 EDT', always 24-hour. - */ export const TIME_24_WITH_SHORT_OFFSET = { hour: n, minute: n, second: n, - hour12: false, - timeZoneName: s + hourCycle: "h23", + timeZoneName: s, }; -/** - * {@link toLocaleString}; format like '09:30:23 Eastern Daylight Time', always 24-hour. - */ export const TIME_24_WITH_LONG_OFFSET = { hour: n, minute: n, second: n, - hour12: false, - timeZoneName: l + hourCycle: "h23", + timeZoneName: l, }; -/** - * {@link toLocaleString}; format like '10/14/1983, 9:30 AM'. Only 12-hour if the locale is. - */ export const DATETIME_SHORT = { year: n, month: n, day: n, hour: n, - minute: n + minute: n, }; -/** - * {@link toLocaleString}; format like '10/14/1983, 9:30:33 AM'. Only 12-hour if the locale is. - */ export const DATETIME_SHORT_WITH_SECONDS = { year: n, month: n, day: n, hour: n, minute: n, - second: n + second: n, }; export const DATETIME_MED = { @@ -129,7 +114,7 @@ export const DATETIME_MED = { month: s, day: n, hour: n, - minute: n + minute: n, }; export const DATETIME_MED_WITH_SECONDS = { @@ -138,7 +123,7 @@ export const DATETIME_MED_WITH_SECONDS = { day: n, hour: n, minute: n, - second: n + second: n, }; export const DATETIME_MED_WITH_WEEKDAY = { @@ -147,7 +132,7 @@ export const DATETIME_MED_WITH_WEEKDAY = { day: n, weekday: s, hour: n, - minute: n + minute: n, }; export const DATETIME_FULL = { @@ -156,7 +141,7 @@ export const DATETIME_FULL = { day: n, hour: n, minute: n, - timeZoneName: s + timeZoneName: s, }; export const DATETIME_FULL_WITH_SECONDS = { @@ -166,7 +151,7 @@ export const DATETIME_FULL_WITH_SECONDS = { hour: n, minute: n, second: n, - timeZoneName: s + timeZoneName: s, }; export const DATETIME_HUGE = { @@ -176,7 +161,7 @@ export const DATETIME_HUGE = { weekday: l, hour: n, minute: n, - timeZoneName: l + timeZoneName: l, }; export const DATETIME_HUGE_WITH_SECONDS = { @@ -187,5 +172,5 @@ export const DATETIME_HUGE_WITH_SECONDS = { hour: n, minute: n, second: n, - timeZoneName: l + timeZoneName: l, }; diff --git a/npm_assets/node_modules/luxon/src/impl/formatter.js b/npm_assets/node_modules/luxon/src/impl/formatter.js index 87b8a2f..7fe6891 100644 --- a/npm_assets/node_modules/luxon/src/impl/formatter.js +++ b/npm_assets/node_modules/luxon/src/impl/formatter.js @@ -1,6 +1,6 @@ import * as English from "./english.js"; import * as Formats from "./formats.js"; -import { hasFormatToParts, padStart } from "./util.js"; +import { padStart } from "./util.js"; function stringifyTokens(splits, tokenToString) { let s = ""; @@ -34,7 +34,7 @@ const macroTokenToFormatOpts = { F: Formats.DATETIME_SHORT_WITH_SECONDS, FF: Formats.DATETIME_MED_WITH_SECONDS, FFF: Formats.DATETIME_FULL_WITH_SECONDS, - FFFF: Formats.DATETIME_HUGE_WITH_SECONDS + FFFF: Formats.DATETIME_HUGE_WITH_SECONDS, }; /** @@ -47,6 +47,9 @@ export default class Formatter { } static parseFormat(fmt) { + // white-space is always considered a literal in user-provided formats + // the " " token has a special meaning (see unitForToken) + let current = null, currentFull = "", bracketed = false; @@ -55,7 +58,7 @@ export default class Formatter { const c = fmt.charAt(i); if (c === "'") { if (currentFull.length > 0) { - splits.push({ literal: bracketed, val: currentFull }); + splits.push({ literal: bracketed || /^\s+$/.test(currentFull), val: currentFull }); } current = null; currentFull = ""; @@ -66,7 +69,7 @@ export default class Formatter { currentFull += c; } else { if (currentFull.length > 0) { - splits.push({ literal: false, val: currentFull }); + splits.push({ literal: /^\s+$/.test(currentFull), val: currentFull }); } currentFull = c; current = c; @@ -74,7 +77,7 @@ export default class Formatter { } if (currentFull.length > 0) { - splits.push({ literal: bracketed, val: currentFull }); + splits.push({ literal: bracketed || /^\s+$/.test(currentFull), val: currentFull }); } return splits; @@ -94,22 +97,27 @@ export default class Formatter { if (this.systemLoc === null) { this.systemLoc = this.loc.redefaultToSystem(); } - const df = this.systemLoc.dtFormatter(dt, Object.assign({}, this.opts, opts)); + const df = this.systemLoc.dtFormatter(dt, { ...this.opts, ...opts }); return df.format(); } formatDateTime(dt, opts = {}) { - const df = this.loc.dtFormatter(dt, Object.assign({}, this.opts, opts)); + const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); return df.format(); } formatDateTimeParts(dt, opts = {}) { - const df = this.loc.dtFormatter(dt, Object.assign({}, this.opts, opts)); + const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); return df.formatToParts(); } + formatInterval(interval, opts = {}) { + const df = this.loc.dtFormatter(interval.start, { ...this.opts, ...opts }); + return df.dtf.formatRange(interval.start.toJSDate(), interval.end.toJSDate()); + } + resolvedOptions(dt, opts = {}) { - const df = this.loc.dtFormatter(dt, Object.assign({}, this.opts, opts)); + const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); return df.resolvedOptions(); } @@ -119,7 +127,7 @@ export default class Formatter { return padStart(n, p); } - const opts = Object.assign({}, this.opts); + const opts = { ...this.opts }; if (p > 0) { opts.padTo = p; @@ -130,10 +138,9 @@ export default class Formatter { formatDateTimeFromString(dt, fmt) { const knownEnglish = this.loc.listingMode() === "en", - useDateTimeFormatter = - this.loc.outputCalendar && this.loc.outputCalendar !== "gregory" && hasFormatToParts(), + useDateTimeFormatter = this.loc.outputCalendar && this.loc.outputCalendar !== "gregory", string = (opts, extract) => this.loc.extract(dt, opts, extract), - formatOffset = opts => { + formatOffset = (opts) => { if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) { return "Z"; } @@ -143,7 +150,7 @@ export default class Formatter { meridiem = () => knownEnglish ? English.meridiemForDateTime(dt) - : string({ hour: "numeric", hour12: true }, "dayperiod"), + : string({ hour: "numeric", hourCycle: "h12" }, "dayperiod"), month = (length, standalone) => knownEnglish ? English.monthForDateTime(dt, length) @@ -155,7 +162,7 @@ export default class Formatter { standalone ? { weekday: length } : { weekday: length, month: "long", day: "numeric" }, "weekday" ), - maybeMacro = token => { + maybeMacro = (token) => { const formatOpts = Formatter.macroTokenToFormatOpts(token); if (formatOpts) { return this.formatWithSystemDefault(dt, formatOpts); @@ -163,9 +170,9 @@ export default class Formatter { return token; } }, - era = length => + era = (length) => knownEnglish ? English.eraForDateTime(dt, length) : string({ era: length }, "era"), - tokenToString = token => { + tokenToString = (token) => { // Where possible: http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles switch (token) { // ms @@ -180,6 +187,11 @@ export default class Formatter { return this.num(dt.second); case "ss": return this.num(dt.second, 2); + // fractional seconds + case "uu": + return this.num(Math.floor(dt.millisecond / 10), 2); + case "uuu": + return this.num(Math.floor(dt.millisecond / 100)); // minutes case "m": return this.num(dt.minute); @@ -347,7 +359,7 @@ export default class Formatter { } formatDurationFromString(dur, fmt) { - const tokenToField = token => { + const tokenToField = (token) => { switch (token[0]) { case "S": return "millisecond"; @@ -359,6 +371,8 @@ export default class Formatter { return "hour"; case "d": return "day"; + case "w": + return "week"; case "M": return "month"; case "y": @@ -367,7 +381,7 @@ export default class Formatter { return null; } }, - tokenToString = lildur => token => { + tokenToString = (lildur) => (token) => { const mapped = tokenToField(token); if (mapped) { return this.num(lildur.get(mapped), token.length); @@ -380,7 +394,7 @@ export default class Formatter { (found, { literal, val }) => (literal ? found : found.concat(val)), [] ), - collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter(t => t)); + collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter((t) => t)); return stringifyTokens(tokens, tokenToString(collapsed)); } } diff --git a/npm_assets/node_modules/luxon/src/impl/locale.js b/npm_assets/node_modules/luxon/src/impl/locale.js index 44a9266..a1dcd33 100644 --- a/npm_assets/node_modules/luxon/src/impl/locale.js +++ b/npm_assets/node_modules/luxon/src/impl/locale.js @@ -1,10 +1,22 @@ -import { hasFormatToParts, hasIntl, padStart, roundTo, hasRelative } from "./util.js"; +import { padStart, roundTo, hasRelative, formatOffset } from "./util.js"; import * as English from "./english.js"; import Settings from "../settings.js"; import DateTime from "../datetime.js"; -import Formatter from "./formatter.js"; import IANAZone from "../zones/IANAZone.js"; +// todo - remap caching + +let intlLFCache = {}; +function getCachedLF(locString, opts = {}) { + const key = JSON.stringify([locString, opts]); + let dtf = intlLFCache[key]; + if (!dtf) { + dtf = new Intl.ListFormat(locString, opts); + intlLFCache[key] = dtf; + } + return dtf; +} + let intlDTCache = {}; function getCachedDTF(locString, opts = {}) { const key = JSON.stringify([locString, opts]); @@ -43,13 +55,8 @@ let sysLocaleCache = null; function systemLocale() { if (sysLocaleCache) { return sysLocaleCache; - } else if (hasIntl()) { - const computedSys = new Intl.DateTimeFormat().resolvedOptions().locale; - // node sometimes defaults to "und". Override that because that is dumb - sysLocaleCache = !computedSys || computedSys === "und" ? "en-US" : computedSys; - return sysLocaleCache; } else { - sysLocaleCache = "en-US"; + sysLocaleCache = new Intl.DateTimeFormat().resolvedOptions().locale; return sysLocaleCache; } } @@ -63,42 +70,50 @@ function parseLocaleString(localeStr) { // b) if it does, use Intl to resolve everything // c) if Intl fails, try again without the -u + // private subtags and unicode subtags have ordering requirements, + // and we're not properly parsing this, so just strip out the + // private ones if they exist. + const xIndex = localeStr.indexOf("-x-"); + if (xIndex !== -1) { + localeStr = localeStr.substring(0, xIndex); + } + const uIndex = localeStr.indexOf("-u-"); if (uIndex === -1) { return [localeStr]; } else { let options; - const smaller = localeStr.substring(0, uIndex); + let selectedStr; try { options = getCachedDTF(localeStr).resolvedOptions(); + selectedStr = localeStr; } catch (e) { + const smaller = localeStr.substring(0, uIndex); options = getCachedDTF(smaller).resolvedOptions(); + selectedStr = smaller; } const { numberingSystem, calendar } = options; - // return the smaller one so that we can append the calendar and numbering overrides to it - return [smaller, numberingSystem, calendar]; + return [selectedStr, numberingSystem, calendar]; } } function intlConfigString(localeStr, numberingSystem, outputCalendar) { - if (hasIntl()) { - if (outputCalendar || numberingSystem) { + if (outputCalendar || numberingSystem) { + if (!localeStr.includes("-u-")) { localeStr += "-u"; + } - if (outputCalendar) { - localeStr += `-ca-${outputCalendar}`; - } + if (outputCalendar) { + localeStr += `-ca-${outputCalendar}`; + } - if (numberingSystem) { - localeStr += `-nu-${numberingSystem}`; - } - return localeStr; - } else { - return localeStr; + if (numberingSystem) { + localeStr += `-nu-${numberingSystem}`; } + return localeStr; } else { - return []; + return localeStr; } } @@ -140,7 +155,7 @@ function supportsFastNumbers(loc) { loc.numberingSystem === "latn" || !loc.locale || loc.locale.startsWith("en") || - (hasIntl() && new Intl.DateTimeFormat(loc.intl).resolvedOptions().numberingSystem === "latn") + new Intl.DateTimeFormat(loc.intl).resolvedOptions().numberingSystem === "latn" ); } } @@ -154,8 +169,10 @@ class PolyNumberFormatter { this.padTo = opts.padTo || 0; this.floor = opts.floor || false; - if (!forceSimple && hasIntl()) { - const intlOpts = { useGrouping: false }; + const { padTo, floor, ...otherOpts } = opts; + + if (!forceSimple || Object.keys(otherOpts).length > 0) { + const intlOpts = { useGrouping: false, ...opts }; if (opts.padTo > 0) intlOpts.minimumIntegerDigits = opts.padTo; this.inf = getCachedINF(intl, intlOpts); } @@ -180,10 +197,13 @@ class PolyNumberFormatter { class PolyDateFormatter { constructor(dt, intl, opts) { this.opts = opts; - this.hasIntl = hasIntl(); + this.originalZone = undefined; - let z; - if (dt.zone.universal && this.hasIntl) { + let z = undefined; + if (this.opts.timeZone) { + // Don't apply any workarounds if a timeZone is explicitly provided in opts + this.dt = dt; + } else if (dt.zone.type === "fixed") { // UTC-8 or Etc/UTC-8 are not part of tzdata, only Etc/GMT+8 and the like. // That is why fixed-offset TZ is set to that unless it is: // 1. Representing offset 0 when UTC is used to maintain previous behavior and does not become GMT. @@ -192,71 +212,68 @@ class PolyDateFormatter { // - < Etc/GMT-14, > Etc/GMT+12, and 30-minute or 45-minute offsets are not part of tzdata const gmtOffset = -1 * (dt.offset / 60); const offsetZ = gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}`; - const isOffsetZoneSupported = IANAZone.isValidZone(offsetZ); - if (dt.offset !== 0 && isOffsetZoneSupported) { + if (dt.offset !== 0 && IANAZone.create(offsetZ).valid) { z = offsetZ; this.dt = dt; } else { - // Not all fixed-offset zones like Etc/+4:30 are present in tzdata. - // So we have to make do. Two cases: - // 1. The format options tell us to show the zone. We can't do that, so the best - // we can do is format the date in UTC. - // 2. The format options don't tell us to show the zone. Then we can adjust them - // the time and tell the formatter to show it to us in UTC, so that the time is right - // and the bad zone doesn't show up. + // Not all fixed-offset zones like Etc/+4:30 are present in tzdata so + // we manually apply the offset and substitute the zone as needed. z = "UTC"; - if (opts.timeZoneName) { - this.dt = dt; - } else { - this.dt = dt.offset === 0 ? dt : DateTime.fromMillis(dt.ts + dt.offset * 60 * 1000); - } + this.dt = dt.offset === 0 ? dt : dt.setZone("UTC").plus({ minutes: dt.offset }); + this.originalZone = dt.zone; } - } else if (dt.zone.type === "local") { + } else if (dt.zone.type === "system") { this.dt = dt; - } else { + } else if (dt.zone.type === "iana") { this.dt = dt; z = dt.zone.name; + } else { + // Custom zones can have any offset / offsetName so we just manually + // apply the offset and substitute the zone as needed. + z = "UTC"; + this.dt = dt.setZone("UTC").plus({ minutes: dt.offset }); + this.originalZone = dt.zone; } - if (this.hasIntl) { - const intlOpts = Object.assign({}, this.opts); - if (z) { - intlOpts.timeZone = z; - } - this.dtf = getCachedDTF(intl, intlOpts); - } + const intlOpts = { ...this.opts }; + intlOpts.timeZone = intlOpts.timeZone || z; + this.dtf = getCachedDTF(intl, intlOpts); } format() { - if (this.hasIntl) { - return this.dtf.format(this.dt.toJSDate()); - } else { - const tokenFormat = English.formatString(this.opts), - loc = Locale.create("en-US"); - return Formatter.create(loc).formatDateTimeFromString(this.dt, tokenFormat); + if (this.originalZone) { + // If we have to substitute in the actual zone name, we have to use + // formatToParts so that the timezone can be replaced. + return this.formatToParts() + .map(({ value }) => value) + .join(""); } + return this.dtf.format(this.dt.toJSDate()); } formatToParts() { - if (this.hasIntl && hasFormatToParts()) { - return this.dtf.formatToParts(this.dt.toJSDate()); - } else { - // This is kind of a cop out. We actually could do this for English. However, we couldn't do it for intl strings - // and IMO it's too weird to have an uncanny valley like that - return []; + const parts = this.dtf.formatToParts(this.dt.toJSDate()); + if (this.originalZone) { + return parts.map((part) => { + if (part.type === "timeZoneName") { + const offsetName = this.originalZone.offsetName(this.dt.ts, { + locale: this.dt.locale, + format: this.opts.timeZoneName, + }); + return { + ...part, + value: offsetName, + }; + } else { + return part; + } + }); } + return parts; } resolvedOptions() { - if (this.hasIntl) { - return this.dtf.resolvedOptions(); - } else { - return { - locale: "en-US", - numberingSystem: "latn", - outputCalendar: "gregory" - }; - } + return this.dtf.resolvedOptions(); } } @@ -265,7 +282,7 @@ class PolyDateFormatter { */ class PolyRelFormatter { constructor(intl, isEnglish, opts) { - this.opts = Object.assign({ style: "long" }, opts); + this.opts = { style: "long", ...opts }; if (!isEnglish && hasRelative()) { this.rtf = getCachedRTF(intl, opts); } @@ -298,11 +315,11 @@ export default class Locale { } static create(locale, numberingSystem, outputCalendar, defaultToEN = false) { - const specifiedLocale = locale || Settings.defaultLocale, - // the system locale is useful for human readable strings but annoying for parsing/formatting known formats - localeR = specifiedLocale || (defaultToEN ? "en-US" : systemLocale()), - numberingSystemR = numberingSystem || Settings.defaultNumberingSystem, - outputCalendarR = outputCalendar || Settings.defaultOutputCalendar; + const specifiedLocale = locale || Settings.defaultLocale; + // the system locale is useful for human readable strings but annoying for parsing/formatting known formats + const localeR = specifiedLocale || (defaultToEN ? "en-US" : systemLocale()); + const numberingSystemR = numberingSystem || Settings.defaultNumberingSystem; + const outputCalendarR = outputCalendar || Settings.defaultOutputCalendar; return new Locale(localeR, numberingSystemR, outputCalendarR, specifiedLocale); } @@ -342,21 +359,12 @@ export default class Locale { return this.fastNumbersCached; } - listingMode(defaultOK = true) { - const intl = hasIntl(), - hasFTP = intl && hasFormatToParts(), - isActuallyEn = this.isEnglish(), - hasNoWeirdness = - (this.numberingSystem === null || this.numberingSystem === "latn") && - (this.outputCalendar === null || this.outputCalendar === "gregory"); - - if (!hasFTP && !(isActuallyEn && hasNoWeirdness) && !defaultOK) { - return "error"; - } else if (!hasFTP || (isActuallyEn && hasNoWeirdness)) { - return "en"; - } else { - return "intl"; - } + listingMode() { + const isActuallyEn = this.isEnglish(); + const hasNoWeirdness = + (this.numberingSystem === null || this.numberingSystem === "latn") && + (this.outputCalendar === null || this.outputCalendar === "gregory"); + return isActuallyEn && hasNoWeirdness ? "en" : "intl"; } clone(alts) { @@ -373,11 +381,11 @@ export default class Locale { } redefaultToEN(alts = {}) { - return this.clone(Object.assign({}, alts, { defaultToEN: true })); + return this.clone({ ...alts, defaultToEN: true }); } redefaultToSystem(alts = {}) { - return this.clone(Object.assign({}, alts, { defaultToEN: false })); + return this.clone({ ...alts, defaultToEN: false }); } months(length, format = false, defaultOK = true) { @@ -385,7 +393,7 @@ export default class Locale { const intl = format ? { month: length, day: "numeric" } : { month: length }, formatStr = format ? "format" : "standalone"; if (!this.monthsCache[formatStr][length]) { - this.monthsCache[formatStr][length] = mapMonths(dt => this.extract(dt, intl, "month")); + this.monthsCache[formatStr][length] = mapMonths((dt) => this.extract(dt, intl, "month")); } return this.monthsCache[formatStr][length]; }); @@ -398,7 +406,7 @@ export default class Locale { : { weekday: length }, formatStr = format ? "format" : "standalone"; if (!this.weekdaysCache[formatStr][length]) { - this.weekdaysCache[formatStr][length] = mapWeekdays(dt => + this.weekdaysCache[formatStr][length] = mapWeekdays((dt) => this.extract(dt, intl, "weekday") ); } @@ -416,9 +424,9 @@ export default class Locale { // In theory there could be aribitrary day periods. We're gonna assume there are exactly two // for AM and PM. This is probably wrong, but it's makes parsing way easier. if (!this.meridiemCache) { - const intl = { hour: "numeric", hour12: true }; + const intl = { hour: "numeric", hourCycle: "h12" }; this.meridiemCache = [DateTime.utc(2016, 11, 13, 9), DateTime.utc(2016, 11, 13, 19)].map( - dt => this.extract(dt, intl, "dayperiod") + (dt) => this.extract(dt, intl, "dayperiod") ); } @@ -434,7 +442,7 @@ export default class Locale { // This is problematic. Different calendars are going to define eras totally differently. What I need is the minimum set of dates // to definitely enumerate them. if (!this.eraCache[length]) { - this.eraCache[length] = [DateTime.utc(-40, 1, 1), DateTime.utc(2017, 1, 1)].map(dt => + this.eraCache[length] = [DateTime.utc(-40, 1, 1), DateTime.utc(2017, 1, 1)].map((dt) => this.extract(dt, intl, "era") ); } @@ -446,7 +454,7 @@ export default class Locale { extract(dt, intlOpts, field) { const df = this.dtFormatter(dt, intlOpts), results = df.formatToParts(), - matching = results.find(m => m.type.toLowerCase() === field); + matching = results.find((m) => m.type.toLowerCase() === field); return matching ? matching.value : null; } @@ -464,11 +472,15 @@ export default class Locale { return new PolyRelFormatter(this.intl, this.isEnglish(), opts); } + listFormatter(opts = {}) { + return getCachedLF(this.intl, opts); + } + isEnglish() { return ( this.locale === "en" || this.locale.toLowerCase() === "en-us" || - (hasIntl() && new Intl.DateTimeFormat(this.intl).resolvedOptions().locale.startsWith("en-us")) + new Intl.DateTimeFormat(this.intl).resolvedOptions().locale.startsWith("en-us") ); } diff --git a/npm_assets/node_modules/luxon/src/impl/regexParser.js b/npm_assets/node_modules/luxon/src/impl/regexParser.js index 0b0297b..ab09586 100644 --- a/npm_assets/node_modules/luxon/src/impl/regexParser.js +++ b/npm_assets/node_modules/luxon/src/impl/regexParser.js @@ -3,8 +3,8 @@ import { signedOffset, parseInteger, parseMillis, - ianaRegex, - isUndefined + isUndefined, + parseFloating, } from "./util.js"; import * as English from "./english.js"; import FixedOffsetZone from "../zones/fixedOffsetZone.js"; @@ -20,18 +20,20 @@ import IANAZone from "../zones/IANAZone.js"; * Some extractions are super dumb and simpleParse and fromStrings help DRY them. */ +const ianaRegex = /[A-Za-z_+-]{1,256}(?::?\/[A-Za-z0-9_+-]{1,256}(?:\/[A-Za-z0-9_+-]{1,256})?)?/; + function combineRegexes(...regexes) { const full = regexes.reduce((f, r) => f + r.source, ""); return RegExp(`^${full}$`); } function combineExtractors(...extractors) { - return m => + return (m) => extractors .reduce( ([mergedVals, mergedZone, cursor], ex) => { const [val, zone, next] = ex(m, cursor); - return [Object.assign(mergedVals, val), mergedZone || zone, next]; + return [{ ...mergedVals, ...val }, zone || mergedZone, next]; }, [{}, null, 1] ) @@ -65,20 +67,21 @@ function simpleParse(...keys) { } // ISO and SQL parsing -const offsetRegex = /(?:(Z)|([+-]\d\d)(?::?(\d\d))?)/, - isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,30}))?)?)?/, - isoTimeRegex = RegExp(`${isoTimeBaseRegex.source}${offsetRegex.source}?`), - isoTimeExtensionRegex = RegExp(`(?:T${isoTimeRegex.source})?`), - isoYmdRegex = /([+-]\d{6}|\d{4})(?:-?(\d\d)(?:-?(\d\d))?)?/, - isoWeekRegex = /(\d{4})-?W(\d\d)(?:-?(\d))?/, - isoOrdinalRegex = /(\d{4})-?(\d{3})/, - extractISOWeekData = simpleParse("weekYear", "weekNumber", "weekDay"), - extractISOOrdinalData = simpleParse("year", "ordinal"), - sqlYmdRegex = /(\d{4})-(\d\d)-(\d\d)/, // dumbed-down version of the ISO one - sqlTimeRegex = RegExp( - `${isoTimeBaseRegex.source} ?(?:${offsetRegex.source}|(${ianaRegex.source}))?` - ), - sqlTimeExtensionRegex = RegExp(`(?: ${sqlTimeRegex.source})?`); +const offsetRegex = /(?:(Z)|([+-]\d\d)(?::?(\d\d))?)/; +const isoExtendedZone = `(?:${offsetRegex.source}?(?:\\[(${ianaRegex.source})\\])?)?`; +const isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,30}))?)?)?/; +const isoTimeRegex = RegExp(`${isoTimeBaseRegex.source}${isoExtendedZone}`); +const isoTimeExtensionRegex = RegExp(`(?:T${isoTimeRegex.source})?`); +const isoYmdRegex = /([+-]\d{6}|\d{4})(?:-?(\d\d)(?:-?(\d\d))?)?/; +const isoWeekRegex = /(\d{4})-?W(\d\d)(?:-?(\d))?/; +const isoOrdinalRegex = /(\d{4})-?(\d{3})/; +const extractISOWeekData = simpleParse("weekYear", "weekNumber", "weekDay"); +const extractISOOrdinalData = simpleParse("year", "ordinal"); +const sqlYmdRegex = /(\d{4})-(\d\d)-(\d\d)/; // dumbed-down version of the ISO one +const sqlTimeRegex = RegExp( + `${isoTimeBaseRegex.source} ?(?:${offsetRegex.source}|(${ianaRegex.source}))?` +); +const sqlTimeExtensionRegex = RegExp(`(?: ${sqlTimeRegex.source})?`); function int(match, pos, fallback) { const m = match[pos]; @@ -89,7 +92,7 @@ function extractISOYmd(match, cursor) { const item = { year: int(match, cursor), month: int(match, cursor + 1, 1), - day: int(match, cursor + 2, 1) + day: int(match, cursor + 2, 1), }; return [item, null, cursor + 3]; @@ -100,7 +103,7 @@ function extractISOTime(match, cursor) { hours: int(match, cursor, 0), minutes: int(match, cursor + 1, 0), seconds: int(match, cursor + 2, 0), - milliseconds: parseMillis(match[cursor + 3]) + milliseconds: parseMillis(match[cursor + 3]), }; return [item, null, cursor + 4]; @@ -124,20 +127,12 @@ const isoTimeOnly = RegExp(`^T?${isoTimeBaseRegex.source}$`); // ISO duration parsing -const isoDuration = /^-?P(?:(?:(-?\d{1,9})Y)?(?:(-?\d{1,9})M)?(?:(-?\d{1,9})W)?(?:(-?\d{1,9})D)?(?:T(?:(-?\d{1,9})H)?(?:(-?\d{1,9})M)?(?:(-?\d{1,20})(?:[.,](-?\d{1,9}))?S)?)?)$/; +const isoDuration = + /^-?P(?:(?:(-?\d{1,20}(?:\.\d{1,20})?)Y)?(?:(-?\d{1,20}(?:\.\d{1,20})?)M)?(?:(-?\d{1,20}(?:\.\d{1,20})?)W)?(?:(-?\d{1,20}(?:\.\d{1,20})?)D)?(?:T(?:(-?\d{1,20}(?:\.\d{1,20})?)H)?(?:(-?\d{1,20}(?:\.\d{1,20})?)M)?(?:(-?\d{1,20})(?:[.,](-?\d{1,20}))?S)?)?)$/; function extractISODuration(match) { - const [ - s, - yearStr, - monthStr, - weekStr, - dayStr, - hourStr, - minuteStr, - secondStr, - millisecondsStr - ] = match; + const [s, yearStr, monthStr, weekStr, dayStr, hourStr, minuteStr, secondStr, millisecondsStr] = + match; const hasNegativePrefix = s[0] === "-"; const negativeSeconds = secondStr && secondStr[0] === "-"; @@ -147,15 +142,15 @@ function extractISODuration(match) { return [ { - years: maybeNegate(parseInteger(yearStr)), - months: maybeNegate(parseInteger(monthStr)), - weeks: maybeNegate(parseInteger(weekStr)), - days: maybeNegate(parseInteger(dayStr)), - hours: maybeNegate(parseInteger(hourStr)), - minutes: maybeNegate(parseInteger(minuteStr)), - seconds: maybeNegate(parseInteger(secondStr), secondStr === "-0"), - milliseconds: maybeNegate(parseMillis(millisecondsStr), negativeSeconds) - } + years: maybeNegate(parseFloating(yearStr)), + months: maybeNegate(parseFloating(monthStr)), + weeks: maybeNegate(parseFloating(weekStr)), + days: maybeNegate(parseFloating(dayStr)), + hours: maybeNegate(parseFloating(hourStr)), + minutes: maybeNegate(parseFloating(minuteStr)), + seconds: maybeNegate(parseFloating(secondStr), secondStr === "-0"), + milliseconds: maybeNegate(parseMillis(millisecondsStr), negativeSeconds), + }, ]; } @@ -171,7 +166,7 @@ const obsOffsets = { MDT: -6 * 60, MST: -7 * 60, PDT: -7 * 60, - PST: -8 * 60 + PST: -8 * 60, }; function fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) { @@ -180,7 +175,7 @@ function fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, month: English.monthsShort.indexOf(monthStr) + 1, day: parseInteger(dayStr), hour: parseInteger(hourStr), - minute: parseInteger(minuteStr) + minute: parseInteger(minuteStr), }; if (secondStr) result.second = parseInteger(secondStr); @@ -195,7 +190,8 @@ function fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, } // RFC 2822/5322 -const rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|(?:([+-]\d\d)(\d\d)))$/; +const rfc2822 = + /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|(?:([+-]\d\d)(\d\d)))$/; function extractRFC2822(match) { const [ @@ -210,7 +206,7 @@ function extractRFC2822(match) { obsOffset, milOffset, offHourStr, - offMinuteStr + offMinuteStr, ] = match, result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr); @@ -229,16 +225,19 @@ function extractRFC2822(match) { function preprocessRFC2822(s) { // Remove comments and folding whitespace and replace multiple-spaces with a single space return s - .replace(/\([^)]*\)|[\n\t]/g, " ") + .replace(/\([^()]*\)|[\n\t]/g, " ") .replace(/(\s\s+)/g, " ") .trim(); } // http date -const rfc1123 = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d\d) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d\d):(\d\d):(\d\d) GMT$/, - rfc850 = /^(Monday|Tuesday|Wedsday|Thursday|Friday|Saturday|Sunday), (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d) (\d\d):(\d\d):(\d\d) GMT$/, - ascii = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ( \d|\d\d) (\d\d):(\d\d):(\d\d) (\d{4})$/; +const rfc1123 = + /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d\d) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d\d):(\d\d):(\d\d) GMT$/, + rfc850 = + /^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d) (\d\d):(\d\d):(\d\d) GMT$/, + ascii = + /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ( \d|\d\d) (\d\d):(\d\d):(\d\d) (\d{4})$/; function extractRFC1123Or850(match) { const [, weekdayStr, dayStr, monthStr, yearStr, hourStr, minuteStr, secondStr] = match, @@ -260,21 +259,28 @@ const isoTimeCombinedRegex = combineRegexes(isoTimeRegex); const extractISOYmdTimeAndOffset = combineExtractors( extractISOYmd, extractISOTime, - extractISOOffset + extractISOOffset, + extractIANAZone ); const extractISOWeekTimeAndOffset = combineExtractors( extractISOWeekData, extractISOTime, - extractISOOffset + extractISOOffset, + extractIANAZone ); const extractISOOrdinalDateAndTime = combineExtractors( extractISOOrdinalData, extractISOTime, - extractISOOffset + extractISOOffset, + extractIANAZone +); +const extractISOTimeAndOffset = combineExtractors( + extractISOTime, + extractISOOffset, + extractIANAZone ); -const extractISOTimeAndOffset = combineExtractors(extractISOTime, extractISOOffset); -/** +/* * @private */ @@ -314,12 +320,6 @@ export function parseISOTimeOnly(s) { const sqlYmdWithTimeExtensionRegex = combineRegexes(sqlYmdRegex, sqlTimeExtensionRegex); const sqlTimeCombinedRegex = combineRegexes(sqlTimeRegex); -const extractISOYmdTimeOffsetAndIANAZone = combineExtractors( - extractISOYmd, - extractISOTime, - extractISOOffset, - extractIANAZone -); const extractISOTimeOffsetAndIANAZone = combineExtractors( extractISOTime, extractISOOffset, @@ -329,7 +329,7 @@ const extractISOTimeOffsetAndIANAZone = combineExtractors( export function parseSQL(s) { return parse( s, - [sqlYmdWithTimeExtensionRegex, extractISOYmdTimeOffsetAndIANAZone], + [sqlYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], [sqlTimeCombinedRegex, extractISOTimeOffsetAndIANAZone] ); } diff --git a/npm_assets/node_modules/luxon/src/impl/tokenParser.js b/npm_assets/node_modules/luxon/src/impl/tokenParser.js index 4ca0401..5a913b0 100644 --- a/npm_assets/node_modules/luxon/src/impl/tokenParser.js +++ b/npm_assets/node_modules/luxon/src/impl/tokenParser.js @@ -8,12 +8,12 @@ import { ConflictingSpecificationError } from "../errors.js"; const MISSING_FTP = "missing Intl.DateTimeFormat.formatToParts support"; -function intUnit(regex, post = i => i) { +function intUnit(regex, post = (i) => i) { return { regex, deser: ([s]) => post(parseDigits(s)) }; } const NBSP = String.fromCharCode(160); -const spaceOrNBSP = `( |${NBSP})`; +const spaceOrNBSP = `[ ${NBSP}]`; const spaceOrNBSPRegExp = new RegExp(spaceOrNBSP, "g"); function fixListRegex(s) { @@ -36,7 +36,7 @@ function oneOf(strings, startIndex) { return { regex: RegExp(strings.map(fixListRegex).join("|")), deser: ([s]) => - strings.findIndex(i => stripInsensitivities(s) === stripInsensitivities(i)) + startIndex + strings.findIndex((i) => stripInsensitivities(s) === stripInsensitivities(i)) + startIndex, }; } } @@ -50,7 +50,6 @@ function simple(regex) { } function escapeToken(value) { - // eslint-disable-next-line no-useless-escape return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); } @@ -66,8 +65,8 @@ function unitForToken(token, loc) { oneToNine = digitRegex(loc, "{1,9}"), twoToFour = digitRegex(loc, "{2,4}"), fourToSix = digitRegex(loc, "{4,6}"), - literal = t => ({ regex: RegExp(escapeToken(t.val)), deser: ([s]) => s, literal: true }), - unitate = t => { + literal = (t) => ({ regex: RegExp(escapeToken(t.val)), deser: ([s]) => s, literal: true }), + unitate = (t) => { if (token.literal) { return literal(t); } @@ -142,6 +141,10 @@ function unitForToken(token, loc) { return intUnit(three); case "u": return simple(oneToNine); + case "uu": + return simple(oneOrTwo); + case "uuu": + return intUnit(one); // meridiem case "a": return oneOf(loc.meridiems(), 0); @@ -177,13 +180,17 @@ function unitForToken(token, loc) { // because we don't have any way to figure out what they are case "z": return simple(/[a-z_+-/]{1,256}?/i); + // this special-case "token" represents a place where a macro-token expanded into a white-space literal + // in this case we accept any non-newline white-space + case " ": + return simple(/[^\S\n\r]/); default: return literal(t); } }; const unit = unitate(token) || { - invalidReason: MISSING_FTP + invalidReason: MISSING_FTP, }; unit.token = token; @@ -194,45 +201,50 @@ function unitForToken(token, loc) { const partTypeStyleToTokenVal = { year: { "2-digit": "yy", - numeric: "yyyyy" + numeric: "yyyyy", }, month: { numeric: "M", "2-digit": "MM", short: "MMM", - long: "MMMM" + long: "MMMM", }, day: { numeric: "d", - "2-digit": "dd" + "2-digit": "dd", }, weekday: { short: "EEE", - long: "EEEE" + long: "EEEE", }, dayperiod: "a", dayPeriod: "a", hour: { numeric: "h", - "2-digit": "hh" + "2-digit": "hh", }, minute: { numeric: "m", - "2-digit": "mm" + "2-digit": "mm", }, second: { numeric: "s", - "2-digit": "ss" - } + "2-digit": "ss", + }, + timeZoneName: { + long: "ZZZZZ", + short: "ZZZ", + }, }; -function tokenForPart(part, locale, formatOpts) { +function tokenForPart(part, formatOpts) { const { type, value } = part; if (type === "literal") { + const isSpace = /^\s+$/.test(value); return { - literal: true, - val: value + literal: !isSpace, + val: isSpace ? " " : value, }; } @@ -246,7 +258,7 @@ function tokenForPart(part, locale, formatOpts) { if (val) { return { literal: false, - val + val, }; } @@ -254,7 +266,7 @@ function tokenForPart(part, locale, formatOpts) { } function buildRegex(units) { - const re = units.map(u => u.regex).reduce((f, r) => `${f}(${r.source})`, ""); + const re = units.map((u) => u.regex).reduce((f, r) => `${f}(${r.source})`, ""); return [`^${re}$`, units]; } @@ -281,7 +293,7 @@ function match(input, regex, handlers) { } function dateTimeFromMatches(matches) { - const toField = token => { + const toField = (token) => { switch (token) { case "S": return "millisecond"; @@ -315,13 +327,17 @@ function dateTimeFromMatches(matches) { } }; - let zone; - if (!isUndefined(matches.Z)) { - zone = new FixedOffsetZone(matches.Z); - } else if (!isUndefined(matches.z)) { + let zone = null; + let specificOffset; + if (!isUndefined(matches.z)) { zone = IANAZone.create(matches.z); - } else { - zone = null; + } + + if (!isUndefined(matches.Z)) { + if (!zone) { + zone = new FixedOffsetZone(matches.Z); + } + specificOffset = matches.Z; } if (!isUndefined(matches.q)) { @@ -353,7 +369,7 @@ function dateTimeFromMatches(matches) { return r; }, {}); - return [vals, zone]; + return [vals, zone, specificOffset]; } let dummyDateTimeCache = null; @@ -372,25 +388,17 @@ function maybeExpandMacroToken(token, locale) { } const formatOpts = Formatter.macroTokenToFormatOpts(token.val); + const tokens = formatOptsToTokens(formatOpts, locale); - if (!formatOpts) { - return token; - } - - const formatter = Formatter.create(locale, formatOpts); - const parts = formatter.formatDateTimeParts(getDummyDateTime()); - - const tokens = parts.map(p => tokenForPart(p, locale, formatOpts)); - - if (tokens.includes(undefined)) { + if (tokens == null || tokens.includes(undefined)) { return token; } return tokens; } -function expandMacroTokens(tokens, locale) { - return Array.prototype.concat(...tokens.map(t => maybeExpandMacroToken(t, locale))); +export function expandMacroTokens(tokens, locale) { + return Array.prototype.concat(...tokens.map((t) => maybeExpandMacroToken(t, locale))); } /** @@ -399,8 +407,8 @@ function expandMacroTokens(tokens, locale) { export function explainFromTokens(locale, input, format) { const tokens = expandMacroTokens(Formatter.parseFormat(format), locale), - units = tokens.map(t => unitForToken(t, locale)), - disqualifyingUnit = units.find(t => t.invalidReason); + units = tokens.map((t) => unitForToken(t, locale)), + disqualifyingUnit = units.find((t) => t.invalidReason); if (disqualifyingUnit) { return { input, tokens, invalidReason: disqualifyingUnit.invalidReason }; @@ -408,17 +416,29 @@ export function explainFromTokens(locale, input, format) { const [regexString, handlers] = buildRegex(units), regex = RegExp(regexString, "i"), [rawMatches, matches] = match(input, regex, handlers), - [result, zone] = matches ? dateTimeFromMatches(matches) : [null, null]; + [result, zone, specificOffset] = matches + ? dateTimeFromMatches(matches) + : [null, null, undefined]; if (hasOwnProperty(matches, "a") && hasOwnProperty(matches, "H")) { throw new ConflictingSpecificationError( "Can't include meridiem when specifying 24-hour format" ); } - return { input, tokens, regex, rawMatches, matches, result, zone }; + return { input, tokens, regex, rawMatches, matches, result, zone, specificOffset }; } } export function parseFromTokens(locale, input, format) { - const { result, zone, invalidReason } = explainFromTokens(locale, input, format); - return [result, zone, invalidReason]; + const { result, zone, specificOffset, invalidReason } = explainFromTokens(locale, input, format); + return [result, zone, specificOffset, invalidReason]; +} + +export function formatOptsToTokens(formatOpts, locale) { + if (!formatOpts) { + return null; + } + + const formatter = Formatter.create(locale, formatOpts); + const parts = formatter.formatDateTimeParts(getDummyDateTime()); + return parts.map((p) => tokenForPart(p, formatOpts)); } diff --git a/npm_assets/node_modules/luxon/src/impl/util.js b/npm_assets/node_modules/luxon/src/impl/util.js index 59f6f86..81bffc6 100644 --- a/npm_assets/node_modules/luxon/src/impl/util.js +++ b/npm_assets/node_modules/luxon/src/impl/util.js @@ -5,6 +5,7 @@ */ import { InvalidArgumentError } from "../errors.js"; +import Settings from "../settings.js"; /** * @private @@ -34,18 +35,6 @@ export function isDate(o) { // CAPABILITIES -export function hasIntl() { - try { - return typeof Intl !== "undefined" && Intl.DateTimeFormat; - } catch (e) { - return false; - } -} - -export function hasFormatToParts() { - return !isUndefined(Intl.DateTimeFormat.prototype.formatToParts); -} - export function hasRelative() { try { return typeof Intl !== "undefined" && !!Intl.RelativeTimeFormat; @@ -99,17 +88,14 @@ export function floorMod(x, n) { } export function padStart(input, n = 2) { - const minus = input < 0 ? "-" : ""; - const target = minus ? input * -1 : input; - let result; - - if (target.toString().length < n) { - result = ("0".repeat(n) + target).slice(-n); + const isNeg = input < 0; + let padded; + if (isNeg) { + padded = "-" + ("" + -input).padStart(n, "0"); } else { - result = target.toString(); + padded = ("" + input).padStart(n, "0"); } - - return `${minus}${result}`; + return padded; } export function parseInteger(string) { @@ -120,6 +106,14 @@ export function parseInteger(string) { } } +export function parseFloating(string) { + if (isUndefined(string) || string === null || string === "") { + return undefined; + } else { + return parseFloat(string); + } +} + export function parseMillis(fraction) { // Return undefined (instead of 0) in these cases, where fraction is not set if (isUndefined(fraction) || fraction === null || fraction === "") { @@ -172,7 +166,10 @@ export function objToLocalTS(obj) { // for legacy reasons, years between 0 and 99 are interpreted as 19XX; revert that if (obj.year < 100 && obj.year >= 0) { d = new Date(d); - d.setUTCFullYear(d.getUTCFullYear() - 1900); + // set the month and day again, this is necessary because year 2000 is a leap year, but year 100 is not + // so if obj.year is in 99, but obj.day makes it roll over into year 100, + // the calculations done by Date.UTC are using year 2000 - which is incorrect + d.setUTCFullYear(obj.year, obj.month - 1, obj.day); } return +d; } @@ -192,7 +189,7 @@ export function weeksInWeekYear(weekYear) { export function untruncateYear(year) { if (year > 99) { return year; - } else return year > 60 ? 1900 + year : 2000 + year; + } else return year > Settings.twoDigitCutoffYear ? 1900 + year : 2000 + year; } // PARSING @@ -200,36 +197,24 @@ export function untruncateYear(year) { export function parseZoneInfo(ts, offsetFormat, locale, timeZone = null) { const date = new Date(ts), intlOpts = { - hour12: false, + hourCycle: "h23", year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", - minute: "2-digit" + minute: "2-digit", }; if (timeZone) { intlOpts.timeZone = timeZone; } - const modified = Object.assign({ timeZoneName: offsetFormat }, intlOpts), - intl = hasIntl(); - - if (intl && hasFormatToParts()) { - const parsed = new Intl.DateTimeFormat(locale, modified) - .formatToParts(date) - .find(m => m.type.toLowerCase() === "timezonename"); - return parsed ? parsed.value : null; - } else if (intl) { - // this probably doesn't work for all locales - const without = new Intl.DateTimeFormat(locale, intlOpts).format(date), - included = new Intl.DateTimeFormat(locale, modified).format(date), - diffed = included.substring(without.length), - trimmed = diffed.replace(/^[, \u200e]+/, ""); - return trimmed; - } else { - return null; - } + const modified = { timeZoneName: offsetFormat, ...intlOpts }; + + const parsed = new Intl.DateTimeFormat(locale, modified) + .formatToParts(date) + .find((m) => m.type.toLowerCase() === "timezonename"); + return parsed ? parsed.value : null; } // signedOffset('-5', '30') -> -330 @@ -255,11 +240,10 @@ export function asNumber(value) { return numericValue; } -export function normalizeObject(obj, normalizer, nonUnitKeys) { +export function normalizeObject(obj, normalizer) { const normalized = {}; for (const u in obj) { if (hasOwnProperty(obj, u)) { - if (nonUnitKeys.indexOf(u) >= 0) continue; const v = obj[u]; if (v === undefined || v === null) continue; normalized[normalizer(u)] = asNumber(v); @@ -288,5 +272,3 @@ export function formatOffset(offset, format) { export function timeObject(obj) { return pick(obj, ["hour", "minute", "second", "millisecond"]); } - -export const ianaRegex = /[A-Za-z_+-]{1,256}(:?\/[A-Za-z_+-]{1,256}(\/[A-Za-z_+-]{1,256})?)?/; diff --git a/npm_assets/node_modules/luxon/src/impl/zoneUtil.js b/npm_assets/node_modules/luxon/src/impl/zoneUtil.js index c45e828..ad389db 100644 --- a/npm_assets/node_modules/luxon/src/impl/zoneUtil.js +++ b/npm_assets/node_modules/luxon/src/impl/zoneUtil.js @@ -8,6 +8,7 @@ import FixedOffsetZone from "../zones/fixedOffsetZone.js"; import InvalidZone from "../zones/invalidZone.js"; import { isUndefined, isString, isNumber } from "./util.js"; +import SystemZone from "../zones/systemZone.js"; export function normalizeZone(input, defaultZone) { let offset; @@ -17,13 +18,10 @@ export function normalizeZone(input, defaultZone) { return input; } else if (isString(input)) { const lowered = input.toLowerCase(); - if (lowered === "local") return defaultZone; + if (lowered === "default") return defaultZone; + else if (lowered === "local" || lowered === "system") return SystemZone.instance; else if (lowered === "utc" || lowered === "gmt") return FixedOffsetZone.utcInstance; - else if ((offset = IANAZone.parseGMTOffset(input)) != null) { - // handle Etc/GMT-4, which V8 chokes on - return FixedOffsetZone.instance(offset); - } else if (IANAZone.isValidSpecifier(lowered)) return IANAZone.create(input); - else return FixedOffsetZone.parseSpecifier(lowered) || new InvalidZone(input); + else return FixedOffsetZone.parseSpecifier(lowered) || IANAZone.create(input); } else if (isNumber(input)) { return FixedOffsetZone.instance(input); } else if (typeof input === "object" && input.offset && typeof input.offset === "number") { |
