summaryrefslogtreecommitdiff
path: root/node_modules/luxon/src/impl
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/luxon/src/impl')
-rw-r--r--node_modules/luxon/src/impl/conversions.js206
-rw-r--r--node_modules/luxon/src/impl/diff.js95
-rw-r--r--node_modules/luxon/src/impl/digits.js94
-rw-r--r--node_modules/luxon/src/impl/english.js233
-rw-r--r--node_modules/luxon/src/impl/formats.js176
-rw-r--r--node_modules/luxon/src/impl/formatter.js434
-rw-r--r--node_modules/luxon/src/impl/invalid.js14
-rw-r--r--node_modules/luxon/src/impl/locale.js569
-rw-r--r--node_modules/luxon/src/impl/regexParser.js335
-rw-r--r--node_modules/luxon/src/impl/tokenParser.js505
-rw-r--r--node_modules/luxon/src/impl/util.js330
-rw-r--r--node_modules/luxon/src/impl/zoneUtil.js34
12 files changed, 3025 insertions, 0 deletions
diff --git a/node_modules/luxon/src/impl/conversions.js b/node_modules/luxon/src/impl/conversions.js
new file mode 100644
index 0000000..4c7d117
--- /dev/null
+++ b/node_modules/luxon/src/impl/conversions.js
@@ -0,0 +1,206 @@
+import {
+ integerBetween,
+ isLeapYear,
+ timeObject,
+ daysInYear,
+ daysInMonth,
+ weeksInWeekYear,
+ isInteger,
+ isUndefined,
+} from "./util.js";
+import Invalid from "./invalid.js";
+import { ConflictingSpecificationError } from "../errors.js";
+
+const nonLeapLadder = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
+ leapLadder = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335];
+
+function unitOutOfRange(unit, value) {
+ return new Invalid(
+ "unit out of range",
+ `you specified ${value} (of type ${typeof value}) as a ${unit}, which is invalid`
+ );
+}
+
+export function dayOfWeek(year, month, day) {
+ 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;
+}
+
+function computeOrdinal(year, month, day) {
+ return day + (isLeapYear(year) ? leapLadder : nonLeapLadder)[month - 1];
+}
+
+function uncomputeOrdinal(year, ordinal) {
+ const table = isLeapYear(year) ? leapLadder : nonLeapLadder,
+ month0 = table.findIndex((i) => i < ordinal),
+ day = ordinal - table[month0];
+ return { month: month0 + 1, day };
+}
+
+export function isoWeekdayToLocal(isoWeekday, startOfWeek) {
+ return ((isoWeekday - startOfWeek + 7) % 7) + 1;
+}
+
+/**
+ * @private
+ */
+
+export function gregorianToWeek(gregObj, minDaysInFirstWeek = 4, startOfWeek = 1) {
+ const { year, month, day } = gregObj,
+ ordinal = computeOrdinal(year, month, day),
+ weekday = isoWeekdayToLocal(dayOfWeek(year, month, day), startOfWeek);
+
+ let weekNumber = Math.floor((ordinal - weekday + 14 - minDaysInFirstWeek) / 7),
+ weekYear;
+
+ if (weekNumber < 1) {
+ weekYear = year - 1;
+ weekNumber = weeksInWeekYear(weekYear, minDaysInFirstWeek, startOfWeek);
+ } else if (weekNumber > weeksInWeekYear(year, minDaysInFirstWeek, startOfWeek)) {
+ weekYear = year + 1;
+ weekNumber = 1;
+ } else {
+ weekYear = year;
+ }
+
+ return { weekYear, weekNumber, weekday, ...timeObject(gregObj) };
+}
+
+export function weekToGregorian(weekData, minDaysInFirstWeek = 4, startOfWeek = 1) {
+ const { weekYear, weekNumber, weekday } = weekData,
+ weekdayOfJan4 = isoWeekdayToLocal(dayOfWeek(weekYear, 1, minDaysInFirstWeek), startOfWeek),
+ yearInDays = daysInYear(weekYear);
+
+ let ordinal = weekNumber * 7 + weekday - weekdayOfJan4 - 7 + minDaysInFirstWeek,
+ year;
+
+ if (ordinal < 1) {
+ year = weekYear - 1;
+ ordinal += daysInYear(year);
+ } else if (ordinal > yearInDays) {
+ year = weekYear + 1;
+ ordinal -= daysInYear(weekYear);
+ } else {
+ year = weekYear;
+ }
+
+ const { month, day } = uncomputeOrdinal(year, ordinal);
+ return { year, month, day, ...timeObject(weekData) };
+}
+
+export function gregorianToOrdinal(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;
+ const { month, day } = uncomputeOrdinal(year, ordinal);
+ return { year, month, day, ...timeObject(ordinalData) };
+}
+
+/**
+ * Check if local week units like localWeekday are used in obj.
+ * If so, validates that they are not mixed with ISO week units and then copies them to the normal week unit properties.
+ * Modifies obj in-place!
+ * @param obj the object values
+ */
+export function usesLocalWeekValues(obj, loc) {
+ const hasLocaleWeekData =
+ !isUndefined(obj.localWeekday) ||
+ !isUndefined(obj.localWeekNumber) ||
+ !isUndefined(obj.localWeekYear);
+ if (hasLocaleWeekData) {
+ const hasIsoWeekData =
+ !isUndefined(obj.weekday) || !isUndefined(obj.weekNumber) || !isUndefined(obj.weekYear);
+
+ if (hasIsoWeekData) {
+ throw new ConflictingSpecificationError(
+ "Cannot mix locale-based week fields with ISO-based week fields"
+ );
+ }
+ if (!isUndefined(obj.localWeekday)) obj.weekday = obj.localWeekday;
+ if (!isUndefined(obj.localWeekNumber)) obj.weekNumber = obj.localWeekNumber;
+ if (!isUndefined(obj.localWeekYear)) obj.weekYear = obj.localWeekYear;
+ delete obj.localWeekday;
+ delete obj.localWeekNumber;
+ delete obj.localWeekYear;
+ return {
+ minDaysInFirstWeek: loc.getMinDaysInFirstWeek(),
+ startOfWeek: loc.getStartOfWeek(),
+ };
+ } else {
+ return { minDaysInFirstWeek: 4, startOfWeek: 1 };
+ }
+}
+
+export function hasInvalidWeekData(obj, minDaysInFirstWeek = 4, startOfWeek = 1) {
+ const validYear = isInteger(obj.weekYear),
+ validWeek = integerBetween(
+ obj.weekNumber,
+ 1,
+ weeksInWeekYear(obj.weekYear, minDaysInFirstWeek, startOfWeek)
+ ),
+ validWeekday = integerBetween(obj.weekday, 1, 7);
+
+ if (!validYear) {
+ return unitOutOfRange("weekYear", obj.weekYear);
+ } else if (!validWeek) {
+ return unitOutOfRange("week", obj.weekNumber);
+ } else if (!validWeekday) {
+ return unitOutOfRange("weekday", obj.weekday);
+ } else return false;
+}
+
+export function hasInvalidOrdinalData(obj) {
+ const validYear = isInteger(obj.year),
+ validOrdinal = integerBetween(obj.ordinal, 1, daysInYear(obj.year));
+
+ if (!validYear) {
+ return unitOutOfRange("year", obj.year);
+ } else if (!validOrdinal) {
+ return unitOutOfRange("ordinal", obj.ordinal);
+ } else return false;
+}
+
+export function hasInvalidGregorianData(obj) {
+ const validYear = isInteger(obj.year),
+ validMonth = integerBetween(obj.month, 1, 12),
+ validDay = integerBetween(obj.day, 1, daysInMonth(obj.year, obj.month));
+
+ if (!validYear) {
+ return unitOutOfRange("year", obj.year);
+ } else if (!validMonth) {
+ return unitOutOfRange("month", obj.month);
+ } else if (!validDay) {
+ return unitOutOfRange("day", obj.day);
+ } else return false;
+}
+
+export function hasInvalidTimeData(obj) {
+ const { hour, minute, second, millisecond } = obj;
+ const validHour =
+ integerBetween(hour, 0, 23) ||
+ (hour === 24 && minute === 0 && second === 0 && millisecond === 0),
+ validMinute = integerBetween(minute, 0, 59),
+ validSecond = integerBetween(second, 0, 59),
+ validMillisecond = integerBetween(millisecond, 0, 999);
+
+ if (!validHour) {
+ return unitOutOfRange("hour", hour);
+ } else if (!validMinute) {
+ return unitOutOfRange("minute", minute);
+ } else if (!validSecond) {
+ return unitOutOfRange("second", second);
+ } else if (!validMillisecond) {
+ return unitOutOfRange("millisecond", millisecond);
+ } else return false;
+}
diff --git a/node_modules/luxon/src/impl/diff.js b/node_modules/luxon/src/impl/diff.js
new file mode 100644
index 0000000..ebd129e
--- /dev/null
+++ b/node_modules/luxon/src/impl/diff.js
@@ -0,0 +1,95 @@
+import Duration from "../duration.js";
+
+function dayDiff(earlier, later) {
+ const utcDayStart = (dt) => dt.toUTC(0, { keepLocalTime: true }).startOf("day").valueOf(),
+ ms = utcDayStart(later) - utcDayStart(earlier);
+ return Math.floor(Duration.fromMillis(ms).as("days"));
+}
+
+function highOrderDiffs(cursor, later, units) {
+ const differs = [
+ ["years", (a, b) => b.year - a.year],
+ ["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],
+ ];
+
+ const results = {};
+ const earlier = cursor;
+ let lowestOrder, highWater;
+
+ /* This loop tries to diff using larger units first.
+ If we overshoot, we backtrack and try the next smaller unit.
+ "cursor" starts out at the earlier timestamp and moves closer and closer to "later"
+ as we use smaller and smaller units.
+ highWater keeps track of where we would be if we added one more of the smallest unit,
+ this is used later to potentially convert any difference smaller than the smallest higher order unit
+ into a fraction of that smallest higher order unit
+ */
+ for (const [unit, differ] of differs) {
+ if (units.indexOf(unit) >= 0) {
+ lowestOrder = unit;
+
+ results[unit] = differ(cursor, later);
+ highWater = earlier.plus(results);
+
+ if (highWater > later) {
+ // we overshot the end point, backtrack cursor by 1
+ results[unit]--;
+ cursor = earlier.plus(results);
+
+ // if we are still overshooting now, we need to backtrack again
+ // this happens in certain situations when diffing times in different zones,
+ // because this calculation ignores time zones
+ if (cursor > later) {
+ // keep the "overshot by 1" around as highWater
+ highWater = cursor;
+ // backtrack cursor by 1
+ results[unit]--;
+ cursor = earlier.plus(results);
+ }
+ } else {
+ cursor = highWater;
+ }
+ }
+ }
+
+ return [cursor, results, highWater, lowestOrder];
+}
+
+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
+ );
+
+ if (lowerOrderUnits.length === 0) {
+ if (highWater < later) {
+ highWater = cursor.plus({ [lowestOrder]: 1 });
+ }
+
+ if (highWater !== cursor) {
+ results[lowestOrder] = (results[lowestOrder] || 0) + remainingMillis / (highWater - cursor);
+ }
+ }
+
+ const duration = Duration.fromObject(results, opts);
+
+ if (lowerOrderUnits.length > 0) {
+ return Duration.fromMillis(remainingMillis, opts)
+ .shiftTo(...lowerOrderUnits)
+ .plus(duration);
+ } else {
+ return duration;
+ }
+}
diff --git a/node_modules/luxon/src/impl/digits.js b/node_modules/luxon/src/impl/digits.js
new file mode 100644
index 0000000..db8dcca
--- /dev/null
+++ b/node_modules/luxon/src/impl/digits.js
@@ -0,0 +1,94 @@
+const numberingSystems = {
+ arab: "[\u0660-\u0669]",
+ arabext: "[\u06F0-\u06F9]",
+ bali: "[\u1B50-\u1B59]",
+ beng: "[\u09E6-\u09EF]",
+ deva: "[\u0966-\u096F]",
+ fullwide: "[\uFF10-\uFF19]",
+ gujr: "[\u0AE6-\u0AEF]",
+ hanidec: "[〇|一|二|三|四|五|六|七|八|九]",
+ khmr: "[\u17E0-\u17E9]",
+ knda: "[\u0CE6-\u0CEF]",
+ laoo: "[\u0ED0-\u0ED9]",
+ limb: "[\u1946-\u194F]",
+ mlym: "[\u0D66-\u0D6F]",
+ mong: "[\u1810-\u1819]",
+ mymr: "[\u1040-\u1049]",
+ orya: "[\u0B66-\u0B6F]",
+ tamldec: "[\u0BE6-\u0BEF]",
+ telu: "[\u0C66-\u0C6F]",
+ thai: "[\u0E50-\u0E59]",
+ tibt: "[\u0F20-\u0F29]",
+ latn: "\\d",
+};
+
+const numberingSystemsUTF16 = {
+ arab: [1632, 1641],
+ arabext: [1776, 1785],
+ bali: [6992, 7001],
+ beng: [2534, 2543],
+ deva: [2406, 2415],
+ fullwide: [65296, 65303],
+ gujr: [2790, 2799],
+ khmr: [6112, 6121],
+ knda: [3302, 3311],
+ laoo: [3792, 3801],
+ limb: [6470, 6479],
+ mlym: [3430, 3439],
+ mong: [6160, 6169],
+ mymr: [4160, 4169],
+ orya: [2918, 2927],
+ tamldec: [3046, 3055],
+ telu: [3174, 3183],
+ thai: [3664, 3673],
+ tibt: [3872, 3881],
+};
+
+const hanidecChars = numberingSystems.hanidec.replace(/[\[|\]]/g, "").split("");
+
+export function parseDigits(str) {
+ let value = parseInt(str, 10);
+ if (isNaN(value)) {
+ value = "";
+ for (let i = 0; i < str.length; i++) {
+ const code = str.charCodeAt(i);
+
+ if (str[i].search(numberingSystems.hanidec) !== -1) {
+ value += hanidecChars.indexOf(str[i]);
+ } else {
+ for (const key in numberingSystemsUTF16) {
+ const [min, max] = numberingSystemsUTF16[key];
+ if (code >= min && code <= max) {
+ value += code - min;
+ }
+ }
+ }
+ }
+ return parseInt(value, 10);
+ } else {
+ return value;
+ }
+}
+
+// cache of {numberingSystem: {append: regex}}
+const digitRegexCache = new Map();
+export function resetDigitRegexCache() {
+ digitRegexCache.clear();
+}
+
+export function digitRegex({ numberingSystem }, append = "") {
+ const ns = numberingSystem || "latn";
+
+ let appendCache = digitRegexCache.get(ns);
+ if (appendCache === undefined) {
+ appendCache = new Map();
+ digitRegexCache.set(ns, appendCache);
+ }
+ let regex = appendCache.get(append);
+ if (regex === undefined) {
+ regex = new RegExp(`${numberingSystems[ns]}${append}`);
+ appendCache.set(append, regex);
+ }
+
+ return regex;
+}
diff --git a/node_modules/luxon/src/impl/english.js b/node_modules/luxon/src/impl/english.js
new file mode 100644
index 0000000..cf93798
--- /dev/null
+++ b/node_modules/luxon/src/impl/english.js
@@ -0,0 +1,233 @@
+import * as Formats from "./formats.js";
+import { pick } from "./util.js";
+
+function stringify(obj) {
+ return JSON.stringify(obj, Object.keys(obj).sort());
+}
+
+/**
+ * @private
+ */
+
+export const monthsLong = [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December",
+];
+
+export const monthsShort = [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec",
+];
+
+export const monthsNarrow = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"];
+
+export function months(length) {
+ switch (length) {
+ case "narrow":
+ return [...monthsNarrow];
+ case "short":
+ return [...monthsShort];
+ case "long":
+ return [...monthsLong];
+ case "numeric":
+ return ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
+ case "2-digit":
+ return ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
+ default:
+ return null;
+ }
+}
+
+export const weekdaysLong = [
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+ "Sunday",
+];
+
+export const weekdaysShort = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
+
+export const weekdaysNarrow = ["M", "T", "W", "T", "F", "S", "S"];
+
+export function weekdays(length) {
+ switch (length) {
+ case "narrow":
+ return [...weekdaysNarrow];
+ case "short":
+ return [...weekdaysShort];
+ case "long":
+ return [...weekdaysLong];
+ case "numeric":
+ return ["1", "2", "3", "4", "5", "6", "7"];
+ default:
+ return null;
+ }
+}
+
+export const meridiems = ["AM", "PM"];
+
+export const erasLong = ["Before Christ", "Anno Domini"];
+
+export const erasShort = ["BC", "AD"];
+
+export const erasNarrow = ["B", "A"];
+
+export function eras(length) {
+ switch (length) {
+ case "narrow":
+ return [...erasNarrow];
+ case "short":
+ return [...erasShort];
+ case "long":
+ return [...erasLong];
+ default:
+ return null;
+ }
+}
+
+export function meridiemForDateTime(dt) {
+ return meridiems[dt.hour < 12 ? 0 : 1];
+}
+
+export function weekdayForDateTime(dt, length) {
+ return weekdays(length)[dt.weekday - 1];
+}
+
+export function monthForDateTime(dt, length) {
+ return months(length)[dt.month - 1];
+}
+
+export function eraForDateTime(dt, length) {
+ return eras(length)[dt.year < 0 ? 0 : 1];
+}
+
+export function formatRelativeTime(unit, count, numeric = "always", narrow = false) {
+ const units = {
+ years: ["year", "yr."],
+ quarters: ["quarter", "qtr."],
+ months: ["month", "mo."],
+ weeks: ["week", "wk."],
+ days: ["day", "day", "days"],
+ hours: ["hour", "hr."],
+ minutes: ["minute", "min."],
+ seconds: ["second", "sec."],
+ };
+
+ const lastable = ["hours", "minutes", "seconds"].indexOf(unit) === -1;
+
+ if (numeric === "auto" && lastable) {
+ const isDay = unit === "days";
+ switch (count) {
+ case 1:
+ return isDay ? "tomorrow" : `next ${units[unit][0]}`;
+ case -1:
+ return isDay ? "yesterday" : `last ${units[unit][0]}`;
+ case 0:
+ return isDay ? "today" : `this ${units[unit][0]}`;
+ default: // fall through
+ }
+ }
+
+ const isInPast = Object.is(count, -0) || count < 0,
+ fmtValue = Math.abs(count),
+ singular = fmtValue === 1,
+ lilUnits = units[unit],
+ fmtUnit = narrow
+ ? singular
+ ? lilUnits[1]
+ : lilUnits[2] || lilUnits[1]
+ : singular
+ ? units[unit][0]
+ : unit;
+ return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}`;
+}
+
+export function formatString(knownFormat) {
+ // these all have the offsets removed because we don't have access to them
+ // without all the intl stuff this is backfilling
+ const filtered = pick(knownFormat, [
+ "weekday",
+ "era",
+ "year",
+ "month",
+ "day",
+ "hour",
+ "minute",
+ "second",
+ "timeZoneName",
+ "hourCycle",
+ ]),
+ key = stringify(filtered),
+ dateTimeHuge = "EEEE, LLLL d, yyyy, h:mm a";
+ switch (key) {
+ case stringify(Formats.DATE_SHORT):
+ return "M/d/yyyy";
+ case stringify(Formats.DATE_MED):
+ return "LLL d, yyyy";
+ case stringify(Formats.DATE_MED_WITH_WEEKDAY):
+ return "EEE, LLL d, yyyy";
+ case stringify(Formats.DATE_FULL):
+ return "LLLL d, yyyy";
+ case stringify(Formats.DATE_HUGE):
+ return "EEEE, LLLL d, yyyy";
+ case stringify(Formats.TIME_SIMPLE):
+ return "h:mm a";
+ case stringify(Formats.TIME_WITH_SECONDS):
+ return "h:mm:ss a";
+ case stringify(Formats.TIME_WITH_SHORT_OFFSET):
+ return "h:mm a";
+ case stringify(Formats.TIME_WITH_LONG_OFFSET):
+ return "h:mm a";
+ case stringify(Formats.TIME_24_SIMPLE):
+ return "HH:mm";
+ case stringify(Formats.TIME_24_WITH_SECONDS):
+ return "HH:mm:ss";
+ case stringify(Formats.TIME_24_WITH_SHORT_OFFSET):
+ return "HH:mm";
+ case stringify(Formats.TIME_24_WITH_LONG_OFFSET):
+ return "HH:mm";
+ case stringify(Formats.DATETIME_SHORT):
+ return "M/d/yyyy, h:mm a";
+ case stringify(Formats.DATETIME_MED):
+ return "LLL d, yyyy, h:mm a";
+ case stringify(Formats.DATETIME_FULL):
+ return "LLLL d, yyyy, h:mm a";
+ case stringify(Formats.DATETIME_HUGE):
+ return dateTimeHuge;
+ case stringify(Formats.DATETIME_SHORT_WITH_SECONDS):
+ return "M/d/yyyy, h:mm:ss a";
+ case stringify(Formats.DATETIME_MED_WITH_SECONDS):
+ return "LLL d, yyyy, h:mm:ss a";
+ case stringify(Formats.DATETIME_MED_WITH_WEEKDAY):
+ return "EEE, d LLL yyyy, h:mm a";
+ case stringify(Formats.DATETIME_FULL_WITH_SECONDS):
+ return "LLLL d, yyyy, h:mm:ss a";
+ case stringify(Formats.DATETIME_HUGE_WITH_SECONDS):
+ return "EEEE, LLLL d, yyyy, h:mm:ss a";
+ default:
+ return dateTimeHuge;
+ }
+}
diff --git a/node_modules/luxon/src/impl/formats.js b/node_modules/luxon/src/impl/formats.js
new file mode 100644
index 0000000..f2efaad
--- /dev/null
+++ b/node_modules/luxon/src/impl/formats.js
@@ -0,0 +1,176 @@
+/**
+ * @private
+ */
+
+const n = "numeric",
+ s = "short",
+ l = "long";
+
+export const DATE_SHORT = {
+ year: n,
+ month: n,
+ day: n,
+};
+
+export const DATE_MED = {
+ year: n,
+ month: s,
+ day: n,
+};
+
+export const DATE_MED_WITH_WEEKDAY = {
+ year: n,
+ month: s,
+ day: n,
+ weekday: s,
+};
+
+export const DATE_FULL = {
+ year: n,
+ month: l,
+ day: n,
+};
+
+export const DATE_HUGE = {
+ year: n,
+ month: l,
+ day: n,
+ weekday: l,
+};
+
+export const TIME_SIMPLE = {
+ hour: n,
+ minute: n,
+};
+
+export const TIME_WITH_SECONDS = {
+ hour: n,
+ minute: n,
+ second: n,
+};
+
+export const TIME_WITH_SHORT_OFFSET = {
+ hour: n,
+ minute: n,
+ second: n,
+ timeZoneName: s,
+};
+
+export const TIME_WITH_LONG_OFFSET = {
+ hour: n,
+ minute: n,
+ second: n,
+ timeZoneName: l,
+};
+
+export const TIME_24_SIMPLE = {
+ hour: n,
+ minute: n,
+ hourCycle: "h23",
+};
+
+export const TIME_24_WITH_SECONDS = {
+ hour: n,
+ minute: n,
+ second: n,
+ hourCycle: "h23",
+};
+
+export const TIME_24_WITH_SHORT_OFFSET = {
+ hour: n,
+ minute: n,
+ second: n,
+ hourCycle: "h23",
+ timeZoneName: s,
+};
+
+export const TIME_24_WITH_LONG_OFFSET = {
+ hour: n,
+ minute: n,
+ second: n,
+ hourCycle: "h23",
+ timeZoneName: l,
+};
+
+export const DATETIME_SHORT = {
+ year: n,
+ month: n,
+ day: n,
+ hour: n,
+ minute: n,
+};
+
+export const DATETIME_SHORT_WITH_SECONDS = {
+ year: n,
+ month: n,
+ day: n,
+ hour: n,
+ minute: n,
+ second: n,
+};
+
+export const DATETIME_MED = {
+ year: n,
+ month: s,
+ day: n,
+ hour: n,
+ minute: n,
+};
+
+export const DATETIME_MED_WITH_SECONDS = {
+ year: n,
+ month: s,
+ day: n,
+ hour: n,
+ minute: n,
+ second: n,
+};
+
+export const DATETIME_MED_WITH_WEEKDAY = {
+ year: n,
+ month: s,
+ day: n,
+ weekday: s,
+ hour: n,
+ minute: n,
+};
+
+export const DATETIME_FULL = {
+ year: n,
+ month: l,
+ day: n,
+ hour: n,
+ minute: n,
+ timeZoneName: s,
+};
+
+export const DATETIME_FULL_WITH_SECONDS = {
+ year: n,
+ month: l,
+ day: n,
+ hour: n,
+ minute: n,
+ second: n,
+ timeZoneName: s,
+};
+
+export const DATETIME_HUGE = {
+ year: n,
+ month: l,
+ day: n,
+ weekday: l,
+ hour: n,
+ minute: n,
+ timeZoneName: l,
+};
+
+export const DATETIME_HUGE_WITH_SECONDS = {
+ year: n,
+ month: l,
+ day: n,
+ weekday: l,
+ hour: n,
+ minute: n,
+ second: n,
+ timeZoneName: l,
+};
diff --git a/node_modules/luxon/src/impl/formatter.js b/node_modules/luxon/src/impl/formatter.js
new file mode 100644
index 0000000..f7e2d04
--- /dev/null
+++ b/node_modules/luxon/src/impl/formatter.js
@@ -0,0 +1,434 @@
+import * as English from "./english.js";
+import * as Formats from "./formats.js";
+import { padStart } from "./util.js";
+
+function stringifyTokens(splits, tokenToString) {
+ let s = "";
+ for (const token of splits) {
+ if (token.literal) {
+ s += token.val;
+ } else {
+ s += tokenToString(token.val);
+ }
+ }
+ return s;
+}
+
+const macroTokenToFormatOpts = {
+ D: Formats.DATE_SHORT,
+ DD: Formats.DATE_MED,
+ DDD: Formats.DATE_FULL,
+ DDDD: Formats.DATE_HUGE,
+ t: Formats.TIME_SIMPLE,
+ tt: Formats.TIME_WITH_SECONDS,
+ ttt: Formats.TIME_WITH_SHORT_OFFSET,
+ tttt: Formats.TIME_WITH_LONG_OFFSET,
+ T: Formats.TIME_24_SIMPLE,
+ TT: Formats.TIME_24_WITH_SECONDS,
+ TTT: Formats.TIME_24_WITH_SHORT_OFFSET,
+ TTTT: Formats.TIME_24_WITH_LONG_OFFSET,
+ f: Formats.DATETIME_SHORT,
+ ff: Formats.DATETIME_MED,
+ fff: Formats.DATETIME_FULL,
+ ffff: Formats.DATETIME_HUGE,
+ F: Formats.DATETIME_SHORT_WITH_SECONDS,
+ FF: Formats.DATETIME_MED_WITH_SECONDS,
+ FFF: Formats.DATETIME_FULL_WITH_SECONDS,
+ FFFF: Formats.DATETIME_HUGE_WITH_SECONDS,
+};
+
+/**
+ * @private
+ */
+
+export default class Formatter {
+ static create(locale, opts = {}) {
+ return new Formatter(locale, opts);
+ }
+
+ 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;
+ const splits = [];
+ for (let i = 0; i < fmt.length; i++) {
+ const c = fmt.charAt(i);
+ if (c === "'") {
+ // turn '' into a literal signal quote instead of just skipping the empty literal
+ if (currentFull.length > 0 || bracketed) {
+ splits.push({
+ literal: bracketed || /^\s+$/.test(currentFull),
+ val: currentFull === "" ? "'" : currentFull,
+ });
+ }
+ current = null;
+ currentFull = "";
+ bracketed = !bracketed;
+ } else if (bracketed) {
+ currentFull += c;
+ } else if (c === current) {
+ currentFull += c;
+ } else {
+ if (currentFull.length > 0) {
+ splits.push({ literal: /^\s+$/.test(currentFull), val: currentFull });
+ }
+ currentFull = c;
+ current = c;
+ }
+ }
+
+ if (currentFull.length > 0) {
+ splits.push({ literal: bracketed || /^\s+$/.test(currentFull), val: currentFull });
+ }
+
+ return splits;
+ }
+
+ static macroTokenToFormatOpts(token) {
+ return macroTokenToFormatOpts[token];
+ }
+
+ constructor(locale, formatOpts) {
+ this.opts = formatOpts;
+ this.loc = locale;
+ this.systemLoc = null;
+ }
+
+ formatWithSystemDefault(dt, opts) {
+ if (this.systemLoc === null) {
+ this.systemLoc = this.loc.redefaultToSystem();
+ }
+ const df = this.systemLoc.dtFormatter(dt, { ...this.opts, ...opts });
+ return df.format();
+ }
+
+ dtFormatter(dt, opts = {}) {
+ return this.loc.dtFormatter(dt, { ...this.opts, ...opts });
+ }
+
+ formatDateTime(dt, opts) {
+ return this.dtFormatter(dt, opts).format();
+ }
+
+ formatDateTimeParts(dt, opts) {
+ return this.dtFormatter(dt, opts).formatToParts();
+ }
+
+ formatInterval(interval, opts) {
+ const df = this.dtFormatter(interval.start, opts);
+ return df.dtf.formatRange(interval.start.toJSDate(), interval.end.toJSDate());
+ }
+
+ resolvedOptions(dt, opts) {
+ return this.dtFormatter(dt, opts).resolvedOptions();
+ }
+
+ num(n, p = 0, signDisplay = undefined) {
+ // we get some perf out of doing this here, annoyingly
+ if (this.opts.forceSimple) {
+ return padStart(n, p);
+ }
+
+ const opts = { ...this.opts };
+
+ if (p > 0) {
+ opts.padTo = p;
+ }
+ if (signDisplay) {
+ opts.signDisplay = signDisplay;
+ }
+
+ return this.loc.numberFormatter(opts).format(n);
+ }
+
+ formatDateTimeFromString(dt, fmt) {
+ const knownEnglish = this.loc.listingMode() === "en",
+ useDateTimeFormatter = this.loc.outputCalendar && this.loc.outputCalendar !== "gregory",
+ string = (opts, extract) => this.loc.extract(dt, opts, extract),
+ formatOffset = (opts) => {
+ if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) {
+ return "Z";
+ }
+
+ return dt.isValid ? dt.zone.formatOffset(dt.ts, opts.format) : "";
+ },
+ meridiem = () =>
+ knownEnglish
+ ? English.meridiemForDateTime(dt)
+ : string({ hour: "numeric", hourCycle: "h12" }, "dayperiod"),
+ month = (length, standalone) =>
+ knownEnglish
+ ? English.monthForDateTime(dt, length)
+ : string(standalone ? { month: length } : { month: length, day: "numeric" }, "month"),
+ weekday = (length, standalone) =>
+ knownEnglish
+ ? English.weekdayForDateTime(dt, length)
+ : string(
+ standalone ? { weekday: length } : { weekday: length, month: "long", day: "numeric" },
+ "weekday"
+ ),
+ maybeMacro = (token) => {
+ const formatOpts = Formatter.macroTokenToFormatOpts(token);
+ if (formatOpts) {
+ return this.formatWithSystemDefault(dt, formatOpts);
+ } else {
+ return token;
+ }
+ },
+ era = (length) =>
+ knownEnglish ? English.eraForDateTime(dt, length) : string({ era: length }, "era"),
+ tokenToString = (token) => {
+ // Where possible: https://cldr.unicode.org/translation/date-time/date-time-symbols
+ switch (token) {
+ // ms
+ case "S":
+ return this.num(dt.millisecond);
+ case "u":
+ // falls through
+ case "SSS":
+ return this.num(dt.millisecond, 3);
+ // seconds
+ case "s":
+ 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);
+ case "mm":
+ return this.num(dt.minute, 2);
+ // hours
+ case "h":
+ return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12);
+ case "hh":
+ return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12, 2);
+ case "H":
+ return this.num(dt.hour);
+ case "HH":
+ return this.num(dt.hour, 2);
+ // offset
+ case "Z":
+ // like +6
+ return formatOffset({ format: "narrow", allowZ: this.opts.allowZ });
+ case "ZZ":
+ // like +06:00
+ return formatOffset({ format: "short", allowZ: this.opts.allowZ });
+ case "ZZZ":
+ // like +0600
+ return formatOffset({ format: "techie", allowZ: this.opts.allowZ });
+ case "ZZZZ":
+ // like EST
+ return dt.zone.offsetName(dt.ts, { format: "short", locale: this.loc.locale });
+ case "ZZZZZ":
+ // like Eastern Standard Time
+ return dt.zone.offsetName(dt.ts, { format: "long", locale: this.loc.locale });
+ // zone
+ case "z":
+ // like America/New_York
+ return dt.zoneName;
+ // meridiems
+ case "a":
+ return meridiem();
+ // dates
+ case "d":
+ return useDateTimeFormatter ? string({ day: "numeric" }, "day") : this.num(dt.day);
+ case "dd":
+ return useDateTimeFormatter ? string({ day: "2-digit" }, "day") : this.num(dt.day, 2);
+ // weekdays - standalone
+ case "c":
+ // like 1
+ return this.num(dt.weekday);
+ case "ccc":
+ // like 'Tues'
+ return weekday("short", true);
+ case "cccc":
+ // like 'Tuesday'
+ return weekday("long", true);
+ case "ccccc":
+ // like 'T'
+ return weekday("narrow", true);
+ // weekdays - format
+ case "E":
+ // like 1
+ return this.num(dt.weekday);
+ case "EEE":
+ // like 'Tues'
+ return weekday("short", false);
+ case "EEEE":
+ // like 'Tuesday'
+ return weekday("long", false);
+ case "EEEEE":
+ // like 'T'
+ return weekday("narrow", false);
+ // months - standalone
+ case "L":
+ // like 1
+ return useDateTimeFormatter
+ ? string({ month: "numeric", day: "numeric" }, "month")
+ : this.num(dt.month);
+ case "LL":
+ // like 01, doesn't seem to work
+ return useDateTimeFormatter
+ ? string({ month: "2-digit", day: "numeric" }, "month")
+ : this.num(dt.month, 2);
+ case "LLL":
+ // like Jan
+ return month("short", true);
+ case "LLLL":
+ // like January
+ return month("long", true);
+ case "LLLLL":
+ // like J
+ return month("narrow", true);
+ // months - format
+ case "M":
+ // like 1
+ return useDateTimeFormatter
+ ? string({ month: "numeric" }, "month")
+ : this.num(dt.month);
+ case "MM":
+ // like 01
+ return useDateTimeFormatter
+ ? string({ month: "2-digit" }, "month")
+ : this.num(dt.month, 2);
+ case "MMM":
+ // like Jan
+ return month("short", false);
+ case "MMMM":
+ // like January
+ return month("long", false);
+ case "MMMMM":
+ // like J
+ return month("narrow", false);
+ // years
+ case "y":
+ // like 2014
+ return useDateTimeFormatter ? string({ year: "numeric" }, "year") : this.num(dt.year);
+ case "yy":
+ // like 14
+ return useDateTimeFormatter
+ ? string({ year: "2-digit" }, "year")
+ : this.num(dt.year.toString().slice(-2), 2);
+ case "yyyy":
+ // like 0012
+ return useDateTimeFormatter
+ ? string({ year: "numeric" }, "year")
+ : this.num(dt.year, 4);
+ case "yyyyyy":
+ // like 000012
+ return useDateTimeFormatter
+ ? string({ year: "numeric" }, "year")
+ : this.num(dt.year, 6);
+ // eras
+ case "G":
+ // like AD
+ return era("short");
+ case "GG":
+ // like Anno Domini
+ return era("long");
+ case "GGGGG":
+ return era("narrow");
+ case "kk":
+ return this.num(dt.weekYear.toString().slice(-2), 2);
+ case "kkkk":
+ return this.num(dt.weekYear, 4);
+ case "W":
+ return this.num(dt.weekNumber);
+ case "WW":
+ return this.num(dt.weekNumber, 2);
+ case "n":
+ return this.num(dt.localWeekNumber);
+ case "nn":
+ return this.num(dt.localWeekNumber, 2);
+ case "ii":
+ return this.num(dt.localWeekYear.toString().slice(-2), 2);
+ case "iiii":
+ return this.num(dt.localWeekYear, 4);
+ case "o":
+ return this.num(dt.ordinal);
+ case "ooo":
+ return this.num(dt.ordinal, 3);
+ case "q":
+ // like 1
+ return this.num(dt.quarter);
+ case "qq":
+ // like 01
+ return this.num(dt.quarter, 2);
+ case "X":
+ return this.num(Math.floor(dt.ts / 1000));
+ case "x":
+ return this.num(dt.ts);
+ default:
+ return maybeMacro(token);
+ }
+ };
+
+ return stringifyTokens(Formatter.parseFormat(fmt), tokenToString);
+ }
+
+ formatDurationFromString(dur, fmt) {
+ const invertLargest = this.opts.signMode === "negativeLargestOnly" ? -1 : 1;
+ const tokenToField = (token) => {
+ switch (token[0]) {
+ case "S":
+ return "milliseconds";
+ case "s":
+ return "seconds";
+ case "m":
+ return "minutes";
+ case "h":
+ return "hours";
+ case "d":
+ return "days";
+ case "w":
+ return "weeks";
+ case "M":
+ return "months";
+ case "y":
+ return "years";
+ default:
+ return null;
+ }
+ },
+ tokenToString = (lildur, info) => (token) => {
+ const mapped = tokenToField(token);
+ if (mapped) {
+ const inversionFactor =
+ info.isNegativeDuration && mapped !== info.largestUnit ? invertLargest : 1;
+ let signDisplay;
+ if (this.opts.signMode === "negativeLargestOnly" && mapped !== info.largestUnit) {
+ signDisplay = "never";
+ } else if (this.opts.signMode === "all") {
+ signDisplay = "always";
+ } else {
+ // "auto" and "negative" are the same, but "auto" has better support
+ signDisplay = "auto";
+ }
+ return this.num(lildur.get(mapped) * inversionFactor, token.length, signDisplay);
+ } else {
+ return token;
+ }
+ },
+ tokens = Formatter.parseFormat(fmt),
+ realTokens = tokens.reduce(
+ (found, { literal, val }) => (literal ? found : found.concat(val)),
+ []
+ ),
+ collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter((t) => t)),
+ durationInfo = {
+ isNegativeDuration: collapsed < 0,
+ // this relies on "collapsed" being based on "shiftTo", which builds up the object
+ // in order
+ largestUnit: Object.keys(collapsed.values)[0],
+ };
+ return stringifyTokens(tokens, tokenToString(collapsed, durationInfo));
+ }
+}
diff --git a/node_modules/luxon/src/impl/invalid.js b/node_modules/luxon/src/impl/invalid.js
new file mode 100644
index 0000000..2a2c95b
--- /dev/null
+++ b/node_modules/luxon/src/impl/invalid.js
@@ -0,0 +1,14 @@
+export default class Invalid {
+ constructor(reason, explanation) {
+ this.reason = reason;
+ this.explanation = explanation;
+ }
+
+ toMessage() {
+ if (this.explanation) {
+ return `${this.reason}: ${this.explanation}`;
+ } else {
+ return this.reason;
+ }
+ }
+}
diff --git a/node_modules/luxon/src/impl/locale.js b/node_modules/luxon/src/impl/locale.js
new file mode 100644
index 0000000..76f08a7
--- /dev/null
+++ b/node_modules/luxon/src/impl/locale.js
@@ -0,0 +1,569 @@
+import { hasLocaleWeekInfo, hasRelative, padStart, roundTo, validateWeekSettings } from "./util.js";
+import * as English from "./english.js";
+import Settings from "../settings.js";
+import DateTime from "../datetime.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;
+}
+
+const intlDTCache = new Map();
+function getCachedDTF(locString, opts = {}) {
+ const key = JSON.stringify([locString, opts]);
+ let dtf = intlDTCache.get(key);
+ if (dtf === undefined) {
+ dtf = new Intl.DateTimeFormat(locString, opts);
+ intlDTCache.set(key, dtf);
+ }
+ return dtf;
+}
+
+const intlNumCache = new Map();
+function getCachedINF(locString, opts = {}) {
+ const key = JSON.stringify([locString, opts]);
+ let inf = intlNumCache.get(key);
+ if (inf === undefined) {
+ inf = new Intl.NumberFormat(locString, opts);
+ intlNumCache.set(key, inf);
+ }
+ return inf;
+}
+
+const intlRelCache = new Map();
+function getCachedRTF(locString, opts = {}) {
+ const { base, ...cacheKeyOpts } = opts; // exclude `base` from the options
+ const key = JSON.stringify([locString, cacheKeyOpts]);
+ let inf = intlRelCache.get(key);
+ if (inf === undefined) {
+ inf = new Intl.RelativeTimeFormat(locString, opts);
+ intlRelCache.set(key, inf);
+ }
+ return inf;
+}
+
+let sysLocaleCache = null;
+function systemLocale() {
+ if (sysLocaleCache) {
+ return sysLocaleCache;
+ } else {
+ sysLocaleCache = new Intl.DateTimeFormat().resolvedOptions().locale;
+ return sysLocaleCache;
+ }
+}
+
+const intlResolvedOptionsCache = new Map();
+function getCachedIntResolvedOptions(locString) {
+ let opts = intlResolvedOptionsCache.get(locString);
+ if (opts === undefined) {
+ opts = new Intl.DateTimeFormat(locString).resolvedOptions();
+ intlResolvedOptionsCache.set(locString, opts);
+ }
+ return opts;
+}
+
+const weekInfoCache = new Map();
+function getCachedWeekInfo(locString) {
+ let data = weekInfoCache.get(locString);
+ if (!data) {
+ const locale = new Intl.Locale(locString);
+ // browsers currently implement this as a property, but spec says it should be a getter function
+ data = "getWeekInfo" in locale ? locale.getWeekInfo() : locale.weekInfo;
+ // minimalDays was removed from WeekInfo: https://github.com/tc39/proposal-intl-locale-info/issues/86
+ if (!("minimalDays" in data)) {
+ data = { ...fallbackWeekSettings, ...data };
+ }
+ weekInfoCache.set(locString, data);
+ }
+ return data;
+}
+
+function parseLocaleString(localeStr) {
+ // I really want to avoid writing a BCP 47 parser
+ // see, e.g. https://github.com/wooorm/bcp-47
+ // Instead, we'll do this:
+
+ // a) if the string has no -u extensions, just leave it alone
+ // 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;
+ 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 [selectedStr, numberingSystem, calendar];
+ }
+}
+
+function intlConfigString(localeStr, numberingSystem, outputCalendar) {
+ if (outputCalendar || numberingSystem) {
+ if (!localeStr.includes("-u-")) {
+ localeStr += "-u";
+ }
+
+ if (outputCalendar) {
+ localeStr += `-ca-${outputCalendar}`;
+ }
+
+ if (numberingSystem) {
+ localeStr += `-nu-${numberingSystem}`;
+ }
+ return localeStr;
+ } else {
+ return localeStr;
+ }
+}
+
+function mapMonths(f) {
+ const ms = [];
+ for (let i = 1; i <= 12; i++) {
+ const dt = DateTime.utc(2009, i, 1);
+ ms.push(f(dt));
+ }
+ return ms;
+}
+
+function mapWeekdays(f) {
+ const ms = [];
+ for (let i = 1; i <= 7; i++) {
+ const dt = DateTime.utc(2016, 11, 13 + i);
+ ms.push(f(dt));
+ }
+ return ms;
+}
+
+function listStuff(loc, length, englishFn, intlFn) {
+ const mode = loc.listingMode();
+
+ if (mode === "error") {
+ return null;
+ } else if (mode === "en") {
+ return englishFn(length);
+ } else {
+ return intlFn(length);
+ }
+}
+
+function supportsFastNumbers(loc) {
+ if (loc.numberingSystem && loc.numberingSystem !== "latn") {
+ return false;
+ } else {
+ return (
+ loc.numberingSystem === "latn" ||
+ !loc.locale ||
+ loc.locale.startsWith("en") ||
+ getCachedIntResolvedOptions(loc.locale).numberingSystem === "latn"
+ );
+ }
+}
+
+/**
+ * @private
+ */
+
+class PolyNumberFormatter {
+ constructor(intl, forceSimple, opts) {
+ this.padTo = opts.padTo || 0;
+ this.floor = opts.floor || 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);
+ }
+ }
+
+ format(i) {
+ if (this.inf) {
+ const fixed = this.floor ? Math.floor(i) : i;
+ return this.inf.format(fixed);
+ } else {
+ // to match the browser's numberformatter defaults
+ const fixed = this.floor ? Math.floor(i) : roundTo(i, 3);
+ return padStart(fixed, this.padTo);
+ }
+ }
+}
+
+/**
+ * @private
+ */
+
+class PolyDateFormatter {
+ constructor(dt, intl, opts) {
+ this.opts = opts;
+ this.originalZone = undefined;
+
+ 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.
+ // 2. Unsupported by the browser:
+ // - some do not support Etc/
+ // - < 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}`;
+ 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 manually apply the offset and substitute the zone as needed.
+ z = "UTC";
+ this.dt = dt.offset === 0 ? dt : dt.setZone("UTC").plus({ minutes: dt.offset });
+ this.originalZone = dt.zone;
+ }
+ } else if (dt.zone.type === "system") {
+ this.dt = dt;
+ } 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;
+ }
+
+ const intlOpts = { ...this.opts };
+ intlOpts.timeZone = intlOpts.timeZone || z;
+ this.dtf = getCachedDTF(intl, intlOpts);
+ }
+
+ format() {
+ 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() {
+ 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() {
+ return this.dtf.resolvedOptions();
+ }
+}
+
+/**
+ * @private
+ */
+class PolyRelFormatter {
+ constructor(intl, isEnglish, opts) {
+ this.opts = { style: "long", ...opts };
+ if (!isEnglish && hasRelative()) {
+ this.rtf = getCachedRTF(intl, opts);
+ }
+ }
+
+ format(count, unit) {
+ if (this.rtf) {
+ return this.rtf.format(count, unit);
+ } else {
+ return English.formatRelativeTime(unit, count, this.opts.numeric, this.opts.style !== "long");
+ }
+ }
+
+ formatToParts(count, unit) {
+ if (this.rtf) {
+ return this.rtf.formatToParts(count, unit);
+ } else {
+ return [];
+ }
+ }
+}
+
+const fallbackWeekSettings = {
+ firstDay: 1,
+ minimalDays: 4,
+ weekend: [6, 7],
+};
+
+/**
+ * @private
+ */
+export default class Locale {
+ static fromOpts(opts) {
+ return Locale.create(
+ opts.locale,
+ opts.numberingSystem,
+ opts.outputCalendar,
+ opts.weekSettings,
+ opts.defaultToEN
+ );
+ }
+
+ static create(locale, numberingSystem, outputCalendar, weekSettings, defaultToEN = false) {
+ 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;
+ const weekSettingsR = validateWeekSettings(weekSettings) || Settings.defaultWeekSettings;
+ return new Locale(localeR, numberingSystemR, outputCalendarR, weekSettingsR, specifiedLocale);
+ }
+
+ static resetCache() {
+ sysLocaleCache = null;
+ intlDTCache.clear();
+ intlNumCache.clear();
+ intlRelCache.clear();
+ intlResolvedOptionsCache.clear();
+ weekInfoCache.clear();
+ }
+
+ static fromObject({ locale, numberingSystem, outputCalendar, weekSettings } = {}) {
+ return Locale.create(locale, numberingSystem, outputCalendar, weekSettings);
+ }
+
+ constructor(locale, numbering, outputCalendar, weekSettings, specifiedLocale) {
+ const [parsedLocale, parsedNumberingSystem, parsedOutputCalendar] = parseLocaleString(locale);
+
+ this.locale = parsedLocale;
+ this.numberingSystem = numbering || parsedNumberingSystem || null;
+ this.outputCalendar = outputCalendar || parsedOutputCalendar || null;
+ this.weekSettings = weekSettings;
+ this.intl = intlConfigString(this.locale, this.numberingSystem, this.outputCalendar);
+
+ this.weekdaysCache = { format: {}, standalone: {} };
+ this.monthsCache = { format: {}, standalone: {} };
+ this.meridiemCache = null;
+ this.eraCache = {};
+
+ this.specifiedLocale = specifiedLocale;
+ this.fastNumbersCached = null;
+ }
+
+ get fastNumbers() {
+ if (this.fastNumbersCached == null) {
+ this.fastNumbersCached = supportsFastNumbers(this);
+ }
+
+ return this.fastNumbersCached;
+ }
+
+ 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) {
+ if (!alts || Object.getOwnPropertyNames(alts).length === 0) {
+ return this;
+ } else {
+ return Locale.create(
+ alts.locale || this.specifiedLocale,
+ alts.numberingSystem || this.numberingSystem,
+ alts.outputCalendar || this.outputCalendar,
+ validateWeekSettings(alts.weekSettings) || this.weekSettings,
+ alts.defaultToEN || false
+ );
+ }
+ }
+
+ redefaultToEN(alts = {}) {
+ return this.clone({ ...alts, defaultToEN: true });
+ }
+
+ redefaultToSystem(alts = {}) {
+ return this.clone({ ...alts, defaultToEN: false });
+ }
+
+ months(length, format = false) {
+ return listStuff(this, length, English.months, () => {
+ // Workaround for "ja" locale: formatToParts does not label all parts of the month
+ // as "month" and for this locale there is no difference between "format" and "non-format".
+ // As such, just use format() instead of formatToParts() and take the whole string
+ const monthSpecialCase = this.intl === "ja" || this.intl.startsWith("ja-");
+ format &= !monthSpecialCase;
+ const intl = format ? { month: length, day: "numeric" } : { month: length },
+ formatStr = format ? "format" : "standalone";
+ if (!this.monthsCache[formatStr][length]) {
+ const mapper = !monthSpecialCase
+ ? (dt) => this.extract(dt, intl, "month")
+ : (dt) => this.dtFormatter(dt, intl).format();
+ this.monthsCache[formatStr][length] = mapMonths(mapper);
+ }
+ return this.monthsCache[formatStr][length];
+ });
+ }
+
+ weekdays(length, format = false) {
+ return listStuff(this, length, English.weekdays, () => {
+ const intl = format
+ ? { weekday: length, year: "numeric", month: "long", day: "numeric" }
+ : { weekday: length },
+ formatStr = format ? "format" : "standalone";
+ if (!this.weekdaysCache[formatStr][length]) {
+ this.weekdaysCache[formatStr][length] = mapWeekdays((dt) =>
+ this.extract(dt, intl, "weekday")
+ );
+ }
+ return this.weekdaysCache[formatStr][length];
+ });
+ }
+
+ meridiems() {
+ return listStuff(
+ this,
+ undefined,
+ () => English.meridiems,
+ () => {
+ // 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", hourCycle: "h12" };
+ this.meridiemCache = [DateTime.utc(2016, 11, 13, 9), DateTime.utc(2016, 11, 13, 19)].map(
+ (dt) => this.extract(dt, intl, "dayperiod")
+ );
+ }
+
+ return this.meridiemCache;
+ }
+ );
+ }
+
+ eras(length) {
+ return listStuff(this, length, English.eras, () => {
+ const intl = { era: length };
+
+ // 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.extract(dt, intl, "era")
+ );
+ }
+
+ return this.eraCache[length];
+ });
+ }
+
+ extract(dt, intlOpts, field) {
+ const df = this.dtFormatter(dt, intlOpts),
+ results = df.formatToParts(),
+ matching = results.find((m) => m.type.toLowerCase() === field);
+ return matching ? matching.value : null;
+ }
+
+ numberFormatter(opts = {}) {
+ // this forcesimple option is never used (the only caller short-circuits on it, but it seems safer to leave)
+ // (in contrast, the rest of the condition is used heavily)
+ return new PolyNumberFormatter(this.intl, opts.forceSimple || this.fastNumbers, opts);
+ }
+
+ dtFormatter(dt, intlOpts = {}) {
+ return new PolyDateFormatter(dt, this.intl, intlOpts);
+ }
+
+ relFormatter(opts = {}) {
+ 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" ||
+ getCachedIntResolvedOptions(this.intl).locale.startsWith("en-us")
+ );
+ }
+
+ getWeekSettings() {
+ if (this.weekSettings) {
+ return this.weekSettings;
+ } else if (!hasLocaleWeekInfo()) {
+ return fallbackWeekSettings;
+ } else {
+ return getCachedWeekInfo(this.locale);
+ }
+ }
+
+ getStartOfWeek() {
+ return this.getWeekSettings().firstDay;
+ }
+
+ getMinDaysInFirstWeek() {
+ return this.getWeekSettings().minimalDays;
+ }
+
+ getWeekendDays() {
+ return this.getWeekSettings().weekend;
+ }
+
+ equals(other) {
+ return (
+ this.locale === other.locale &&
+ this.numberingSystem === other.numberingSystem &&
+ this.outputCalendar === other.outputCalendar
+ );
+ }
+
+ toString() {
+ return `Locale(${this.locale}, ${this.numberingSystem}, ${this.outputCalendar})`;
+ }
+}
diff --git a/node_modules/luxon/src/impl/regexParser.js b/node_modules/luxon/src/impl/regexParser.js
new file mode 100644
index 0000000..6710d64
--- /dev/null
+++ b/node_modules/luxon/src/impl/regexParser.js
@@ -0,0 +1,335 @@
+import {
+ untruncateYear,
+ signedOffset,
+ parseInteger,
+ parseMillis,
+ isUndefined,
+ parseFloating,
+} from "./util.js";
+import * as English from "./english.js";
+import FixedOffsetZone from "../zones/fixedOffsetZone.js";
+import IANAZone from "../zones/IANAZone.js";
+
+/*
+ * This file handles parsing for well-specified formats. Here's how it works:
+ * Two things go into parsing: a regex to match with and an extractor to take apart the groups in the match.
+ * An extractor is just a function that takes a regex match array and returns a { year: ..., month: ... } object
+ * parse() does the work of executing the regex and applying the extractor. It takes multiple regex/extractor pairs to try in sequence.
+ * Extractors can take a "cursor" representing the offset in the match to look at. This makes it easy to combine extractors.
+ * combineExtractors() does the work of combining them, keeping track of the cursor through multiple extractions.
+ * 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) =>
+ extractors
+ .reduce(
+ ([mergedVals, mergedZone, cursor], ex) => {
+ const [val, zone, next] = ex(m, cursor);
+ return [{ ...mergedVals, ...val }, zone || mergedZone, next];
+ },
+ [{}, null, 1]
+ )
+ .slice(0, 2);
+}
+
+function parse(s, ...patterns) {
+ if (s == null) {
+ return [null, null];
+ }
+
+ for (const [regex, extractor] of patterns) {
+ const m = regex.exec(s);
+ if (m) {
+ return extractor(m);
+ }
+ }
+ return [null, null];
+}
+
+function simpleParse(...keys) {
+ return (match, cursor) => {
+ const ret = {};
+ let i;
+
+ for (i = 0; i < keys.length; i++) {
+ ret[keys[i]] = parseInteger(match[cursor + i]);
+ }
+ return [ret, null, cursor + i];
+ };
+}
+
+// ISO and SQL parsing
+const offsetRegex = /(?:([Zz])|([+-]\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(`(?:[Tt]${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];
+ return isUndefined(m) ? fallback : parseInteger(m);
+}
+
+function extractISOYmd(match, cursor) {
+ const item = {
+ year: int(match, cursor),
+ month: int(match, cursor + 1, 1),
+ day: int(match, cursor + 2, 1),
+ };
+
+ return [item, null, cursor + 3];
+}
+
+function extractISOTime(match, cursor) {
+ const item = {
+ hours: int(match, cursor, 0),
+ minutes: int(match, cursor + 1, 0),
+ seconds: int(match, cursor + 2, 0),
+ milliseconds: parseMillis(match[cursor + 3]),
+ };
+
+ return [item, null, cursor + 4];
+}
+
+function extractISOOffset(match, cursor) {
+ const local = !match[cursor] && !match[cursor + 1],
+ fullOffset = signedOffset(match[cursor + 1], match[cursor + 2]),
+ zone = local ? null : FixedOffsetZone.instance(fullOffset);
+ return [{}, zone, cursor + 3];
+}
+
+function extractIANAZone(match, cursor) {
+ const zone = match[cursor] ? IANAZone.create(match[cursor]) : null;
+ return [{}, zone, cursor + 1];
+}
+
+// ISO time parsing
+
+const isoTimeOnly = RegExp(`^T?${isoTimeBaseRegex.source}$`);
+
+// ISO duration parsing
+
+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 hasNegativePrefix = s[0] === "-";
+ const negativeSeconds = secondStr && secondStr[0] === "-";
+
+ const maybeNegate = (num, force = false) =>
+ num !== undefined && (force || (num && hasNegativePrefix)) ? -num : num;
+
+ return [
+ {
+ 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),
+ },
+ ];
+}
+
+// These are a little braindead. EDT *should* tell us that we're in, say, America/New_York
+// and not just that we're in -240 *right now*. But since I don't think these are used that often
+// I'm just going to ignore that
+const obsOffsets = {
+ GMT: 0,
+ EDT: -4 * 60,
+ EST: -5 * 60,
+ CDT: -5 * 60,
+ CST: -6 * 60,
+ MDT: -6 * 60,
+ MST: -7 * 60,
+ PDT: -7 * 60,
+ PST: -8 * 60,
+};
+
+function fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
+ const result = {
+ year: yearStr.length === 2 ? untruncateYear(parseInteger(yearStr)) : parseInteger(yearStr),
+ month: English.monthsShort.indexOf(monthStr) + 1,
+ day: parseInteger(dayStr),
+ hour: parseInteger(hourStr),
+ minute: parseInteger(minuteStr),
+ };
+
+ if (secondStr) result.second = parseInteger(secondStr);
+ if (weekdayStr) {
+ result.weekday =
+ weekdayStr.length > 3
+ ? English.weekdaysLong.indexOf(weekdayStr) + 1
+ : English.weekdaysShort.indexOf(weekdayStr) + 1;
+ }
+
+ return result;
+}
+
+// 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)))$/;
+
+function extractRFC2822(match) {
+ const [
+ ,
+ weekdayStr,
+ dayStr,
+ monthStr,
+ yearStr,
+ hourStr,
+ minuteStr,
+ secondStr,
+ obsOffset,
+ milOffset,
+ offHourStr,
+ offMinuteStr,
+ ] = match,
+ result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);
+
+ let offset;
+ if (obsOffset) {
+ offset = obsOffsets[obsOffset];
+ } else if (milOffset) {
+ offset = 0;
+ } else {
+ offset = signedOffset(offHourStr, offMinuteStr);
+ }
+
+ return [result, new FixedOffsetZone(offset)];
+}
+
+function preprocessRFC2822(s) {
+ // Remove comments and folding whitespace and replace multiple-spaces with a single space
+ return s
+ .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|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,
+ result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);
+ return [result, FixedOffsetZone.utcInstance];
+}
+
+function extractASCII(match) {
+ const [, weekdayStr, monthStr, dayStr, hourStr, minuteStr, secondStr, yearStr] = match,
+ result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);
+ return [result, FixedOffsetZone.utcInstance];
+}
+
+const isoYmdWithTimeExtensionRegex = combineRegexes(isoYmdRegex, isoTimeExtensionRegex);
+const isoWeekWithTimeExtensionRegex = combineRegexes(isoWeekRegex, isoTimeExtensionRegex);
+const isoOrdinalWithTimeExtensionRegex = combineRegexes(isoOrdinalRegex, isoTimeExtensionRegex);
+const isoTimeCombinedRegex = combineRegexes(isoTimeRegex);
+
+const extractISOYmdTimeAndOffset = combineExtractors(
+ extractISOYmd,
+ extractISOTime,
+ extractISOOffset,
+ extractIANAZone
+);
+const extractISOWeekTimeAndOffset = combineExtractors(
+ extractISOWeekData,
+ extractISOTime,
+ extractISOOffset,
+ extractIANAZone
+);
+const extractISOOrdinalDateAndTime = combineExtractors(
+ extractISOOrdinalData,
+ extractISOTime,
+ extractISOOffset,
+ extractIANAZone
+);
+const extractISOTimeAndOffset = combineExtractors(
+ extractISOTime,
+ extractISOOffset,
+ extractIANAZone
+);
+
+/*
+ * @private
+ */
+
+export function parseISODate(s) {
+ return parse(
+ s,
+ [isoYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset],
+ [isoWeekWithTimeExtensionRegex, extractISOWeekTimeAndOffset],
+ [isoOrdinalWithTimeExtensionRegex, extractISOOrdinalDateAndTime],
+ [isoTimeCombinedRegex, extractISOTimeAndOffset]
+ );
+}
+
+export function parseRFC2822Date(s) {
+ return parse(preprocessRFC2822(s), [rfc2822, extractRFC2822]);
+}
+
+export function parseHTTPDate(s) {
+ return parse(
+ s,
+ [rfc1123, extractRFC1123Or850],
+ [rfc850, extractRFC1123Or850],
+ [ascii, extractASCII]
+ );
+}
+
+export function parseISODuration(s) {
+ return parse(s, [isoDuration, extractISODuration]);
+}
+
+const extractISOTimeOnly = combineExtractors(extractISOTime);
+
+export function parseISOTimeOnly(s) {
+ return parse(s, [isoTimeOnly, extractISOTimeOnly]);
+}
+
+const sqlYmdWithTimeExtensionRegex = combineRegexes(sqlYmdRegex, sqlTimeExtensionRegex);
+const sqlTimeCombinedRegex = combineRegexes(sqlTimeRegex);
+
+const extractISOTimeOffsetAndIANAZone = combineExtractors(
+ extractISOTime,
+ extractISOOffset,
+ extractIANAZone
+);
+
+export function parseSQL(s) {
+ return parse(
+ s,
+ [sqlYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset],
+ [sqlTimeCombinedRegex, extractISOTimeOffsetAndIANAZone]
+ );
+}
diff --git a/node_modules/luxon/src/impl/tokenParser.js b/node_modules/luxon/src/impl/tokenParser.js
new file mode 100644
index 0000000..48a7595
--- /dev/null
+++ b/node_modules/luxon/src/impl/tokenParser.js
@@ -0,0 +1,505 @@
+import { parseMillis, isUndefined, untruncateYear, signedOffset, hasOwnProperty } from "./util.js";
+import Formatter from "./formatter.js";
+import FixedOffsetZone from "../zones/fixedOffsetZone.js";
+import IANAZone from "../zones/IANAZone.js";
+import DateTime from "../datetime.js";
+import { digitRegex, parseDigits } from "./digits.js";
+import { ConflictingSpecificationError } from "../errors.js";
+
+const MISSING_FTP = "missing Intl.DateTimeFormat.formatToParts support";
+
+function intUnit(regex, post = (i) => i) {
+ return { regex, deser: ([s]) => post(parseDigits(s)) };
+}
+
+const NBSP = String.fromCharCode(160);
+const spaceOrNBSP = `[ ${NBSP}]`;
+const spaceOrNBSPRegExp = new RegExp(spaceOrNBSP, "g");
+
+function fixListRegex(s) {
+ // make dots optional and also make them literal
+ // make space and non breakable space characters interchangeable
+ return s.replace(/\./g, "\\.?").replace(spaceOrNBSPRegExp, spaceOrNBSP);
+}
+
+function stripInsensitivities(s) {
+ return s
+ .replace(/\./g, "") // ignore dots that were made optional
+ .replace(spaceOrNBSPRegExp, " ") // interchange space and nbsp
+ .toLowerCase();
+}
+
+function oneOf(strings, startIndex) {
+ if (strings === null) {
+ return null;
+ } else {
+ return {
+ regex: RegExp(strings.map(fixListRegex).join("|")),
+ deser: ([s]) =>
+ strings.findIndex((i) => stripInsensitivities(s) === stripInsensitivities(i)) + startIndex,
+ };
+ }
+}
+
+function offset(regex, groups) {
+ return { regex, deser: ([, h, m]) => signedOffset(h, m), groups };
+}
+
+function simple(regex) {
+ return { regex, deser: ([s]) => s };
+}
+
+function escapeToken(value) {
+ return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
+}
+
+/**
+ * @param token
+ * @param {Locale} loc
+ */
+function unitForToken(token, loc) {
+ const one = digitRegex(loc),
+ two = digitRegex(loc, "{2}"),
+ three = digitRegex(loc, "{3}"),
+ four = digitRegex(loc, "{4}"),
+ six = digitRegex(loc, "{6}"),
+ oneOrTwo = digitRegex(loc, "{1,2}"),
+ oneToThree = digitRegex(loc, "{1,3}"),
+ oneToSix = digitRegex(loc, "{1,6}"),
+ 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) => {
+ if (token.literal) {
+ return literal(t);
+ }
+ switch (t.val) {
+ // era
+ case "G":
+ return oneOf(loc.eras("short"), 0);
+ case "GG":
+ return oneOf(loc.eras("long"), 0);
+ // years
+ case "y":
+ return intUnit(oneToSix);
+ case "yy":
+ return intUnit(twoToFour, untruncateYear);
+ case "yyyy":
+ return intUnit(four);
+ case "yyyyy":
+ return intUnit(fourToSix);
+ case "yyyyyy":
+ return intUnit(six);
+ // months
+ case "M":
+ return intUnit(oneOrTwo);
+ case "MM":
+ return intUnit(two);
+ case "MMM":
+ return oneOf(loc.months("short", true), 1);
+ case "MMMM":
+ return oneOf(loc.months("long", true), 1);
+ case "L":
+ return intUnit(oneOrTwo);
+ case "LL":
+ return intUnit(two);
+ case "LLL":
+ return oneOf(loc.months("short", false), 1);
+ case "LLLL":
+ return oneOf(loc.months("long", false), 1);
+ // dates
+ case "d":
+ return intUnit(oneOrTwo);
+ case "dd":
+ return intUnit(two);
+ // ordinals
+ case "o":
+ return intUnit(oneToThree);
+ case "ooo":
+ return intUnit(three);
+ // time
+ case "HH":
+ return intUnit(two);
+ case "H":
+ return intUnit(oneOrTwo);
+ case "hh":
+ return intUnit(two);
+ case "h":
+ return intUnit(oneOrTwo);
+ case "mm":
+ return intUnit(two);
+ case "m":
+ return intUnit(oneOrTwo);
+ case "q":
+ return intUnit(oneOrTwo);
+ case "qq":
+ return intUnit(two);
+ case "s":
+ return intUnit(oneOrTwo);
+ case "ss":
+ return intUnit(two);
+ case "S":
+ return intUnit(oneToThree);
+ case "SSS":
+ 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);
+ // weekYear (k)
+ case "kkkk":
+ return intUnit(four);
+ case "kk":
+ return intUnit(twoToFour, untruncateYear);
+ // weekNumber (W)
+ case "W":
+ return intUnit(oneOrTwo);
+ case "WW":
+ return intUnit(two);
+ // weekdays
+ case "E":
+ case "c":
+ return intUnit(one);
+ case "EEE":
+ return oneOf(loc.weekdays("short", false), 1);
+ case "EEEE":
+ return oneOf(loc.weekdays("long", false), 1);
+ case "ccc":
+ return oneOf(loc.weekdays("short", true), 1);
+ case "cccc":
+ return oneOf(loc.weekdays("long", true), 1);
+ // offset/zone
+ case "Z":
+ case "ZZ":
+ return offset(new RegExp(`([+-]${oneOrTwo.source})(?::(${two.source}))?`), 2);
+ case "ZZZ":
+ return offset(new RegExp(`([+-]${oneOrTwo.source})(${two.source})?`), 2);
+ // we don't support ZZZZ (PST) or ZZZZZ (Pacific Standard Time) in parsing
+ // 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,
+ };
+
+ unit.token = token;
+
+ return unit;
+}
+
+const partTypeStyleToTokenVal = {
+ year: {
+ "2-digit": "yy",
+ numeric: "yyyyy",
+ },
+ month: {
+ numeric: "M",
+ "2-digit": "MM",
+ short: "MMM",
+ long: "MMMM",
+ },
+ day: {
+ numeric: "d",
+ "2-digit": "dd",
+ },
+ weekday: {
+ short: "EEE",
+ long: "EEEE",
+ },
+ dayperiod: "a",
+ dayPeriod: "a",
+ hour12: {
+ numeric: "h",
+ "2-digit": "hh",
+ },
+ hour24: {
+ numeric: "H",
+ "2-digit": "HH",
+ },
+ minute: {
+ numeric: "m",
+ "2-digit": "mm",
+ },
+ second: {
+ numeric: "s",
+ "2-digit": "ss",
+ },
+ timeZoneName: {
+ long: "ZZZZZ",
+ short: "ZZZ",
+ },
+};
+
+function tokenForPart(part, formatOpts, resolvedOpts) {
+ const { type, value } = part;
+
+ if (type === "literal") {
+ const isSpace = /^\s+$/.test(value);
+ return {
+ literal: !isSpace,
+ val: isSpace ? " " : value,
+ };
+ }
+
+ const style = formatOpts[type];
+
+ // The user might have explicitly specified hour12 or hourCycle
+ // if so, respect their decision
+ // if not, refer back to the resolvedOpts, which are based on the locale
+ let actualType = type;
+ if (type === "hour") {
+ if (formatOpts.hour12 != null) {
+ actualType = formatOpts.hour12 ? "hour12" : "hour24";
+ } else if (formatOpts.hourCycle != null) {
+ if (formatOpts.hourCycle === "h11" || formatOpts.hourCycle === "h12") {
+ actualType = "hour12";
+ } else {
+ actualType = "hour24";
+ }
+ } else {
+ // tokens only differentiate between 24 hours or not,
+ // so we do not need to check hourCycle here, which is less supported anyways
+ actualType = resolvedOpts.hour12 ? "hour12" : "hour24";
+ }
+ }
+ let val = partTypeStyleToTokenVal[actualType];
+ if (typeof val === "object") {
+ val = val[style];
+ }
+
+ if (val) {
+ return {
+ literal: false,
+ val,
+ };
+ }
+
+ return undefined;
+}
+
+function buildRegex(units) {
+ const re = units.map((u) => u.regex).reduce((f, r) => `${f}(${r.source})`, "");
+ return [`^${re}$`, units];
+}
+
+function match(input, regex, handlers) {
+ const matches = input.match(regex);
+
+ if (matches) {
+ const all = {};
+ let matchIndex = 1;
+ for (const i in handlers) {
+ if (hasOwnProperty(handlers, i)) {
+ const h = handlers[i],
+ groups = h.groups ? h.groups + 1 : 1;
+ if (!h.literal && h.token) {
+ all[h.token.val[0]] = h.deser(matches.slice(matchIndex, matchIndex + groups));
+ }
+ matchIndex += groups;
+ }
+ }
+ return [matches, all];
+ } else {
+ return [matches, {}];
+ }
+}
+
+function dateTimeFromMatches(matches) {
+ const toField = (token) => {
+ switch (token) {
+ case "S":
+ return "millisecond";
+ case "s":
+ return "second";
+ case "m":
+ return "minute";
+ case "h":
+ case "H":
+ return "hour";
+ case "d":
+ return "day";
+ case "o":
+ return "ordinal";
+ case "L":
+ case "M":
+ return "month";
+ case "y":
+ return "year";
+ case "E":
+ case "c":
+ return "weekday";
+ case "W":
+ return "weekNumber";
+ case "k":
+ return "weekYear";
+ case "q":
+ return "quarter";
+ default:
+ return null;
+ }
+ };
+
+ let zone = null;
+ let specificOffset;
+ if (!isUndefined(matches.z)) {
+ zone = IANAZone.create(matches.z);
+ }
+
+ if (!isUndefined(matches.Z)) {
+ if (!zone) {
+ zone = new FixedOffsetZone(matches.Z);
+ }
+ specificOffset = matches.Z;
+ }
+
+ if (!isUndefined(matches.q)) {
+ matches.M = (matches.q - 1) * 3 + 1;
+ }
+
+ if (!isUndefined(matches.h)) {
+ if (matches.h < 12 && matches.a === 1) {
+ matches.h += 12;
+ } else if (matches.h === 12 && matches.a === 0) {
+ matches.h = 0;
+ }
+ }
+
+ if (matches.G === 0 && matches.y) {
+ matches.y = -matches.y;
+ }
+
+ if (!isUndefined(matches.u)) {
+ matches.S = parseMillis(matches.u);
+ }
+
+ const vals = Object.keys(matches).reduce((r, k) => {
+ const f = toField(k);
+ if (f) {
+ r[f] = matches[k];
+ }
+
+ return r;
+ }, {});
+
+ return [vals, zone, specificOffset];
+}
+
+let dummyDateTimeCache = null;
+
+function getDummyDateTime() {
+ if (!dummyDateTimeCache) {
+ dummyDateTimeCache = DateTime.fromMillis(1555555555555);
+ }
+
+ return dummyDateTimeCache;
+}
+
+function maybeExpandMacroToken(token, locale) {
+ if (token.literal) {
+ return token;
+ }
+
+ const formatOpts = Formatter.macroTokenToFormatOpts(token.val);
+ const tokens = formatOptsToTokens(formatOpts, locale);
+
+ if (tokens == null || tokens.includes(undefined)) {
+ return token;
+ }
+
+ return tokens;
+}
+
+export function expandMacroTokens(tokens, locale) {
+ return Array.prototype.concat(...tokens.map((t) => maybeExpandMacroToken(t, locale)));
+}
+
+/**
+ * @private
+ */
+
+export class TokenParser {
+ constructor(locale, format) {
+ this.locale = locale;
+ this.format = format;
+ this.tokens = expandMacroTokens(Formatter.parseFormat(format), locale);
+ this.units = this.tokens.map((t) => unitForToken(t, locale));
+ this.disqualifyingUnit = this.units.find((t) => t.invalidReason);
+
+ if (!this.disqualifyingUnit) {
+ const [regexString, handlers] = buildRegex(this.units);
+ this.regex = RegExp(regexString, "i");
+ this.handlers = handlers;
+ }
+ }
+
+ explainFromTokens(input) {
+ if (!this.isValid) {
+ return { input, tokens: this.tokens, invalidReason: this.invalidReason };
+ } else {
+ const [rawMatches, matches] = match(input, this.regex, this.handlers),
+ [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: this.tokens,
+ regex: this.regex,
+ rawMatches,
+ matches,
+ result,
+ zone,
+ specificOffset,
+ };
+ }
+ }
+
+ get isValid() {
+ return !this.disqualifyingUnit;
+ }
+
+ get invalidReason() {
+ return this.disqualifyingUnit ? this.disqualifyingUnit.invalidReason : null;
+ }
+}
+
+export function explainFromTokens(locale, input, format) {
+ const parser = new TokenParser(locale, format);
+ return parser.explainFromTokens(input);
+}
+
+export function parseFromTokens(locale, input, format) {
+ 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 df = formatter.dtFormatter(getDummyDateTime());
+ const parts = df.formatToParts();
+ const resolvedOpts = df.resolvedOptions();
+ return parts.map((p) => tokenForPart(p, formatOpts, resolvedOpts));
+}
diff --git a/node_modules/luxon/src/impl/util.js b/node_modules/luxon/src/impl/util.js
new file mode 100644
index 0000000..9164250
--- /dev/null
+++ b/node_modules/luxon/src/impl/util.js
@@ -0,0 +1,330 @@
+/*
+ This is just a junk drawer, containing anything used across multiple classes.
+ Because Luxon is small(ish), this should stay small and we won't worry about splitting
+ it up into, say, parsingUtil.js and basicUtil.js and so on. But they are divided up by feature area.
+*/
+
+import { InvalidArgumentError } from "../errors.js";
+import Settings from "../settings.js";
+import { dayOfWeek, isoWeekdayToLocal } from "./conversions.js";
+
+/**
+ * @private
+ */
+
+// TYPES
+
+export function isUndefined(o) {
+ return typeof o === "undefined";
+}
+
+export function isNumber(o) {
+ return typeof o === "number";
+}
+
+export function isInteger(o) {
+ return typeof o === "number" && o % 1 === 0;
+}
+
+export function isString(o) {
+ return typeof o === "string";
+}
+
+export function isDate(o) {
+ return Object.prototype.toString.call(o) === "[object Date]";
+}
+
+// CAPABILITIES
+
+export function hasRelative() {
+ try {
+ return typeof Intl !== "undefined" && !!Intl.RelativeTimeFormat;
+ } catch (e) {
+ return false;
+ }
+}
+
+export function hasLocaleWeekInfo() {
+ try {
+ return (
+ typeof Intl !== "undefined" &&
+ !!Intl.Locale &&
+ ("weekInfo" in Intl.Locale.prototype || "getWeekInfo" in Intl.Locale.prototype)
+ );
+ } catch (e) {
+ return false;
+ }
+}
+
+// OBJECTS AND ARRAYS
+
+export function maybeArray(thing) {
+ return Array.isArray(thing) ? thing : [thing];
+}
+
+export function bestBy(arr, by, compare) {
+ if (arr.length === 0) {
+ return undefined;
+ }
+ return arr.reduce((best, next) => {
+ const pair = [by(next), next];
+ if (!best) {
+ return pair;
+ } else if (compare(best[0], pair[0]) === best[0]) {
+ return best;
+ } else {
+ return pair;
+ }
+ }, null)[1];
+}
+
+export function pick(obj, keys) {
+ return keys.reduce((a, k) => {
+ a[k] = obj[k];
+ return a;
+ }, {});
+}
+
+export function hasOwnProperty(obj, prop) {
+ return Object.prototype.hasOwnProperty.call(obj, prop);
+}
+
+export function validateWeekSettings(settings) {
+ if (settings == null) {
+ return null;
+ } else if (typeof settings !== "object") {
+ throw new InvalidArgumentError("Week settings must be an object");
+ } else {
+ if (
+ !integerBetween(settings.firstDay, 1, 7) ||
+ !integerBetween(settings.minimalDays, 1, 7) ||
+ !Array.isArray(settings.weekend) ||
+ settings.weekend.some((v) => !integerBetween(v, 1, 7))
+ ) {
+ throw new InvalidArgumentError("Invalid week settings");
+ }
+ return {
+ firstDay: settings.firstDay,
+ minimalDays: settings.minimalDays,
+ weekend: Array.from(settings.weekend),
+ };
+ }
+}
+
+// NUMBERS AND STRINGS
+
+export function integerBetween(thing, bottom, top) {
+ return isInteger(thing) && thing >= bottom && thing <= top;
+}
+
+// x % n but takes the sign of n instead of x
+export function floorMod(x, n) {
+ return x - n * Math.floor(x / n);
+}
+
+export function padStart(input, n = 2) {
+ const isNeg = input < 0;
+ let padded;
+ if (isNeg) {
+ padded = "-" + ("" + -input).padStart(n, "0");
+ } else {
+ padded = ("" + input).padStart(n, "0");
+ }
+ return padded;
+}
+
+export function parseInteger(string) {
+ if (isUndefined(string) || string === null || string === "") {
+ return undefined;
+ } else {
+ return parseInt(string, 10);
+ }
+}
+
+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 === "") {
+ return undefined;
+ } else {
+ const f = parseFloat("0." + fraction) * 1000;
+ return Math.floor(f);
+ }
+}
+
+export function roundTo(number, digits, rounding = "round") {
+ const factor = 10 ** digits;
+ switch (rounding) {
+ case "expand":
+ return number > 0
+ ? Math.ceil(number * factor) / factor
+ : Math.floor(number * factor) / factor;
+ case "trunc":
+ return Math.trunc(number * factor) / factor;
+ case "round":
+ return Math.round(number * factor) / factor;
+ case "floor":
+ return Math.floor(number * factor) / factor;
+ case "ceil":
+ return Math.ceil(number * factor) / factor;
+ default:
+ throw new RangeError(`Value rounding ${rounding} is out of range`);
+ }
+}
+
+// DATE BASICS
+
+export function isLeapYear(year) {
+ return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
+}
+
+export function daysInYear(year) {
+ return isLeapYear(year) ? 366 : 365;
+}
+
+export function daysInMonth(year, month) {
+ const modMonth = floorMod(month - 1, 12) + 1,
+ modYear = year + (month - modMonth) / 12;
+
+ if (modMonth === 2) {
+ return isLeapYear(modYear) ? 29 : 28;
+ } else {
+ return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][modMonth - 1];
+ }
+}
+
+// convert a calendar object to a local timestamp (epoch, but with the offset baked in)
+export function objToLocalTS(obj) {
+ let d = Date.UTC(
+ obj.year,
+ obj.month - 1,
+ obj.day,
+ obj.hour,
+ obj.minute,
+ obj.second,
+ obj.millisecond
+ );
+
+ // 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);
+ // 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;
+}
+
+// adapted from moment.js: https://github.com/moment/moment/blob/000ac1800e620f770f4eb31b5ae908f6167b0ab2/src/lib/units/week-calendar-utils.js
+function firstWeekOffset(year, minDaysInFirstWeek, startOfWeek) {
+ const fwdlw = isoWeekdayToLocal(dayOfWeek(year, 1, minDaysInFirstWeek), startOfWeek);
+ return -fwdlw + minDaysInFirstWeek - 1;
+}
+
+export function weeksInWeekYear(weekYear, minDaysInFirstWeek = 4, startOfWeek = 1) {
+ const weekOffset = firstWeekOffset(weekYear, minDaysInFirstWeek, startOfWeek);
+ const weekOffsetNext = firstWeekOffset(weekYear + 1, minDaysInFirstWeek, startOfWeek);
+ return (daysInYear(weekYear) - weekOffset + weekOffsetNext) / 7;
+}
+
+export function untruncateYear(year) {
+ if (year > 99) {
+ return year;
+ } else return year > Settings.twoDigitCutoffYear ? 1900 + year : 2000 + year;
+}
+
+// PARSING
+
+export function parseZoneInfo(ts, offsetFormat, locale, timeZone = null) {
+ const date = new Date(ts),
+ intlOpts = {
+ hourCycle: "h23",
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit",
+ hour: "2-digit",
+ minute: "2-digit",
+ };
+
+ if (timeZone) {
+ intlOpts.timeZone = timeZone;
+ }
+
+ 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
+export function signedOffset(offHourStr, offMinuteStr) {
+ let offHour = parseInt(offHourStr, 10);
+
+ // don't || this because we want to preserve -0
+ if (Number.isNaN(offHour)) {
+ offHour = 0;
+ }
+
+ const offMin = parseInt(offMinuteStr, 10) || 0,
+ offMinSigned = offHour < 0 || Object.is(offHour, -0) ? -offMin : offMin;
+ return offHour * 60 + offMinSigned;
+}
+
+// COERCION
+
+export function asNumber(value) {
+ const numericValue = Number(value);
+ if (typeof value === "boolean" || value === "" || !Number.isFinite(numericValue))
+ throw new InvalidArgumentError(`Invalid unit value ${value}`);
+ return numericValue;
+}
+
+export function normalizeObject(obj, normalizer) {
+ const normalized = {};
+ for (const u in obj) {
+ if (hasOwnProperty(obj, u)) {
+ const v = obj[u];
+ if (v === undefined || v === null) continue;
+ normalized[normalizer(u)] = asNumber(v);
+ }
+ }
+ return normalized;
+}
+
+/**
+ * Returns the offset's value as a string
+ * @param {number} ts - Epoch milliseconds for which to get the offset
+ * @param {string} format - What style of offset to return.
+ * Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively
+ * @return {string}
+ */
+export function formatOffset(offset, format) {
+ const hours = Math.trunc(Math.abs(offset / 60)),
+ minutes = Math.trunc(Math.abs(offset % 60)),
+ sign = offset >= 0 ? "+" : "-";
+
+ switch (format) {
+ case "short":
+ return `${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}`;
+ case "narrow":
+ return `${sign}${hours}${minutes > 0 ? `:${minutes}` : ""}`;
+ case "techie":
+ return `${sign}${padStart(hours, 2)}${padStart(minutes, 2)}`;
+ default:
+ throw new RangeError(`Value format ${format} is out of range for property format`);
+ }
+}
+
+export function timeObject(obj) {
+ return pick(obj, ["hour", "minute", "second", "millisecond"]);
+}
diff --git a/node_modules/luxon/src/impl/zoneUtil.js b/node_modules/luxon/src/impl/zoneUtil.js
new file mode 100644
index 0000000..c3151a7
--- /dev/null
+++ b/node_modules/luxon/src/impl/zoneUtil.js
@@ -0,0 +1,34 @@
+/**
+ * @private
+ */
+
+import Zone from "../zone.js";
+import IANAZone from "../zones/IANAZone.js";
+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;
+ if (isUndefined(input) || input === null) {
+ return defaultZone;
+ } else if (input instanceof Zone) {
+ return input;
+ } else if (isString(input)) {
+ const lowered = input.toLowerCase();
+ if (lowered === "default") return defaultZone;
+ else if (lowered === "local" || lowered === "system") return SystemZone.instance;
+ else if (lowered === "utc" || lowered === "gmt") return FixedOffsetZone.utcInstance;
+ else return FixedOffsetZone.parseSpecifier(lowered) || IANAZone.create(input);
+ } else if (isNumber(input)) {
+ return FixedOffsetZone.instance(input);
+ } else if (typeof input === "object" && "offset" in input && typeof input.offset === "function") {
+ // This is dumb, but the instanceof check above doesn't seem to really work
+ // so we're duck checking it
+ return input;
+ } else {
+ return new InvalidZone(input);
+ }
+}