update
This commit is contained in:
parent
d9becc67b6
commit
9308795b8b
964 changed files with 104265 additions and 16 deletions
157
node_modules/luxon/src/impl/conversions.js
generated
vendored
Normal file
157
node_modules/luxon/src/impl/conversions.js
generated
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
import {
|
||||
integerBetween,
|
||||
isLeapYear,
|
||||
timeObject,
|
||||
daysInYear,
|
||||
daysInMonth,
|
||||
weeksInWeekYear,
|
||||
isInteger
|
||||
} from "./util.js";
|
||||
import Invalid from "./invalid.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`
|
||||
);
|
||||
}
|
||||
|
||||
function dayOfWeek(year, month, day) {
|
||||
const js = new Date(Date.UTC(year, month - 1, day)).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 };
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
||||
export function gregorianToWeek(gregObj) {
|
||||
const { year, month, day } = gregObj,
|
||||
ordinal = computeOrdinal(year, month, day),
|
||||
weekday = dayOfWeek(year, month, day);
|
||||
|
||||
let weekNumber = Math.floor((ordinal - weekday + 10) / 7),
|
||||
weekYear;
|
||||
|
||||
if (weekNumber < 1) {
|
||||
weekYear = year - 1;
|
||||
weekNumber = weeksInWeekYear(weekYear);
|
||||
} else if (weekNumber > weeksInWeekYear(year)) {
|
||||
weekYear = year + 1;
|
||||
weekNumber = 1;
|
||||
} else {
|
||||
weekYear = year;
|
||||
}
|
||||
|
||||
return Object.assign({ weekYear, weekNumber, weekday }, timeObject(gregObj));
|
||||
}
|
||||
|
||||
export function weekToGregorian(weekData) {
|
||||
const { weekYear, weekNumber, weekday } = weekData,
|
||||
weekdayOfJan4 = dayOfWeek(weekYear, 1, 4),
|
||||
yearInDays = daysInYear(weekYear);
|
||||
|
||||
let ordinal = weekNumber * 7 + weekday - weekdayOfJan4 - 3,
|
||||
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 Object.assign({ 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));
|
||||
}
|
||||
|
||||
export function ordinalToGregorian(ordinalData) {
|
||||
const { year, ordinal } = ordinalData,
|
||||
{ month, day } = uncomputeOrdinal(year, ordinal);
|
||||
|
||||
return Object.assign({ year, month, day }, timeObject(ordinalData));
|
||||
}
|
||||
|
||||
export function hasInvalidWeekData(obj) {
|
||||
const validYear = isInteger(obj.weekYear),
|
||||
validWeek = integerBetween(obj.weekNumber, 1, weeksInWeekYear(obj.weekYear)),
|
||||
validWeekday = integerBetween(obj.weekday, 1, 7);
|
||||
|
||||
if (!validYear) {
|
||||
return unitOutOfRange("weekYear", obj.weekYear);
|
||||
} else if (!validWeek) {
|
||||
return unitOutOfRange("week", obj.week);
|
||||
} 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;
|
||||
}
|
79
node_modules/luxon/src/impl/diff.js
generated
vendored
Normal file
79
node_modules/luxon/src/impl/diff.js
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
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],
|
||||
["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 = {};
|
||||
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 });
|
||||
|
||||
if (highWater > later) {
|
||||
cursor = cursor.plus({ [unit]: delta - 1 });
|
||||
delta -= 1;
|
||||
} else {
|
||||
cursor = highWater;
|
||||
}
|
||||
|
||||
results[unit] = delta;
|
||||
}
|
||||
}
|
||||
|
||||
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(Object.assign(results, opts));
|
||||
|
||||
if (lowerOrderUnits.length > 0) {
|
||||
return Duration.fromMillis(remainingMillis, opts)
|
||||
.shiftTo(...lowerOrderUnits)
|
||||
.plus(duration);
|
||||
} else {
|
||||
return duration;
|
||||
}
|
||||
}
|
76
node_modules/luxon/src/impl/digits.js
generated
vendored
Normal file
76
node_modules/luxon/src/impl/digits.js
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
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]
|
||||
};
|
||||
|
||||
// eslint-disable-next-line
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
export function digitRegex({ numberingSystem }, append = "") {
|
||||
return new RegExp(`${numberingSystems[numberingSystem || "latn"]}${append}`);
|
||||
}
|
231
node_modules/luxon/src/impl/english.js
generated
vendored
Normal file
231
node_modules/luxon/src/impl/english.js
generated
vendored
Normal file
|
@ -0,0 +1,231 @@
|
|||
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",
|
||||
"hour12"
|
||||
]),
|
||||
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_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;
|
||||
}
|
||||
}
|
184
node_modules/luxon/src/impl/formats.js
generated
vendored
Normal file
184
node_modules/luxon/src/impl/formats.js
generated
vendored
Normal file
|
@ -0,0 +1,184 @@
|
|||
/**
|
||||
* @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_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,
|
||||
hour12: false
|
||||
};
|
||||
|
||||
/**
|
||||
* {@link toLocaleString}; format like '09:30:23', always 24-hour.
|
||||
*/
|
||||
export const TIME_24_WITH_SECONDS = {
|
||||
hour: n,
|
||||
minute: n,
|
||||
second: n,
|
||||
hour12: false
|
||||
};
|
||||
|
||||
/**
|
||||
* {@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
|
||||
};
|
||||
|
||||
/**
|
||||
* {@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
|
||||
};
|
||||
|
||||
/**
|
||||
* {@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
|
||||
};
|
||||
|
||||
/**
|
||||
* {@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
|
||||
};
|
||||
|
||||
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
|
||||
};
|
386
node_modules/luxon/src/impl/formatter.js
generated
vendored
Normal file
386
node_modules/luxon/src/impl/formatter.js
generated
vendored
Normal file
|
@ -0,0 +1,386 @@
|
|||
import * as English from "./english.js";
|
||||
import * as Formats from "./formats.js";
|
||||
import { hasFormatToParts, 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) {
|
||||
let current = null,
|
||||
currentFull = "",
|
||||
bracketed = false;
|
||||
const splits = [];
|
||||
for (let i = 0; i < fmt.length; i++) {
|
||||
const c = fmt.charAt(i);
|
||||
if (c === "'") {
|
||||
if (currentFull.length > 0) {
|
||||
splits.push({ literal: bracketed, val: 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: false, val: currentFull });
|
||||
}
|
||||
currentFull = c;
|
||||
current = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentFull.length > 0) {
|
||||
splits.push({ literal: bracketed, 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, Object.assign({}, this.opts, opts));
|
||||
return df.format();
|
||||
}
|
||||
|
||||
formatDateTime(dt, opts = {}) {
|
||||
const df = this.loc.dtFormatter(dt, Object.assign({}, this.opts, opts));
|
||||
return df.format();
|
||||
}
|
||||
|
||||
formatDateTimeParts(dt, opts = {}) {
|
||||
const df = this.loc.dtFormatter(dt, Object.assign({}, this.opts, opts));
|
||||
return df.formatToParts();
|
||||
}
|
||||
|
||||
resolvedOptions(dt, opts = {}) {
|
||||
const df = this.loc.dtFormatter(dt, Object.assign({}, this.opts, opts));
|
||||
return df.resolvedOptions();
|
||||
}
|
||||
|
||||
num(n, p = 0) {
|
||||
// we get some perf out of doing this here, annoyingly
|
||||
if (this.opts.forceSimple) {
|
||||
return padStart(n, p);
|
||||
}
|
||||
|
||||
const opts = Object.assign({}, this.opts);
|
||||
|
||||
if (p > 0) {
|
||||
opts.padTo = p;
|
||||
}
|
||||
|
||||
return this.loc.numberFormatter(opts).format(n);
|
||||
}
|
||||
|
||||
formatDateTimeFromString(dt, fmt) {
|
||||
const knownEnglish = this.loc.listingMode() === "en",
|
||||
useDateTimeFormatter =
|
||||
this.loc.outputCalendar && this.loc.outputCalendar !== "gregory" && hasFormatToParts(),
|
||||
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", hour12: true }, "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: http://cldr.unicode.org/translation/date-time#TOC-Stand-Alone-vs.-Format-Styles
|
||||
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);
|
||||
// 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 "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 tokenToField = token => {
|
||||
switch (token[0]) {
|
||||
case "S":
|
||||
return "millisecond";
|
||||
case "s":
|
||||
return "second";
|
||||
case "m":
|
||||
return "minute";
|
||||
case "h":
|
||||
return "hour";
|
||||
case "d":
|
||||
return "day";
|
||||
case "M":
|
||||
return "month";
|
||||
case "y":
|
||||
return "year";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
tokenToString = lildur => token => {
|
||||
const mapped = tokenToField(token);
|
||||
if (mapped) {
|
||||
return this.num(lildur.get(mapped), token.length);
|
||||
} 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));
|
||||
return stringifyTokens(tokens, tokenToString(collapsed));
|
||||
}
|
||||
}
|
14
node_modules/luxon/src/impl/invalid.js
generated
vendored
Normal file
14
node_modules/luxon/src/impl/invalid.js
generated
vendored
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
469
node_modules/luxon/src/impl/locale.js
generated
vendored
Normal file
469
node_modules/luxon/src/impl/locale.js
generated
vendored
Normal file
|
@ -0,0 +1,469 @@
|
|||
import { hasFormatToParts, hasIntl, padStart, roundTo, hasRelative } from "./util.js";
|
||||
import * as English from "./english.js";
|
||||
import Settings from "../settings.js";
|
||||
import DateTime from "../datetime.js";
|
||||
import Formatter from "./formatter.js";
|
||||
|
||||
let intlDTCache = {};
|
||||
function getCachedDTF(locString, opts = {}) {
|
||||
const key = JSON.stringify([locString, opts]);
|
||||
let dtf = intlDTCache[key];
|
||||
if (!dtf) {
|
||||
dtf = new Intl.DateTimeFormat(locString, opts);
|
||||
intlDTCache[key] = dtf;
|
||||
}
|
||||
return dtf;
|
||||
}
|
||||
|
||||
let intlNumCache = {};
|
||||
function getCachedINF(locString, opts = {}) {
|
||||
const key = JSON.stringify([locString, opts]);
|
||||
let inf = intlNumCache[key];
|
||||
if (!inf) {
|
||||
inf = new Intl.NumberFormat(locString, opts);
|
||||
intlNumCache[key] = inf;
|
||||
}
|
||||
return inf;
|
||||
}
|
||||
|
||||
let intlRelCache = {};
|
||||
function getCachedRTF(locString, opts = {}) {
|
||||
const { base, ...cacheKeyOpts } = opts; // exclude `base` from the options
|
||||
const key = JSON.stringify([locString, cacheKeyOpts]);
|
||||
let inf = intlRelCache[key];
|
||||
if (!inf) {
|
||||
inf = new Intl.RelativeTimeFormat(locString, opts);
|
||||
intlRelCache[key] = inf;
|
||||
}
|
||||
return inf;
|
||||
}
|
||||
|
||||
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";
|
||||
return sysLocaleCache;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
const uIndex = localeStr.indexOf("-u-");
|
||||
if (uIndex === -1) {
|
||||
return [localeStr];
|
||||
} else {
|
||||
let options;
|
||||
const smaller = localeStr.substring(0, uIndex);
|
||||
try {
|
||||
options = getCachedDTF(localeStr).resolvedOptions();
|
||||
} catch (e) {
|
||||
options = getCachedDTF(smaller).resolvedOptions();
|
||||
}
|
||||
|
||||
const { numberingSystem, calendar } = options;
|
||||
// return the smaller one so that we can append the calendar and numbering overrides to it
|
||||
return [smaller, numberingSystem, calendar];
|
||||
}
|
||||
}
|
||||
|
||||
function intlConfigString(localeStr, numberingSystem, outputCalendar) {
|
||||
if (hasIntl()) {
|
||||
if (outputCalendar || numberingSystem) {
|
||||
localeStr += "-u";
|
||||
|
||||
if (outputCalendar) {
|
||||
localeStr += `-ca-${outputCalendar}`;
|
||||
}
|
||||
|
||||
if (numberingSystem) {
|
||||
localeStr += `-nu-${numberingSystem}`;
|
||||
}
|
||||
return localeStr;
|
||||
} else {
|
||||
return localeStr;
|
||||
}
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function mapMonths(f) {
|
||||
const ms = [];
|
||||
for (let i = 1; i <= 12; i++) {
|
||||
const dt = DateTime.utc(2016, 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, defaultOK, englishFn, intlFn) {
|
||||
const mode = loc.listingMode(defaultOK);
|
||||
|
||||
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") ||
|
||||
(hasIntl() && new Intl.DateTimeFormat(loc.intl).resolvedOptions().numberingSystem === "latn")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
||||
class PolyNumberFormatter {
|
||||
constructor(intl, forceSimple, opts) {
|
||||
this.padTo = opts.padTo || 0;
|
||||
this.floor = opts.floor || false;
|
||||
|
||||
if (!forceSimple && hasIntl()) {
|
||||
const intlOpts = { useGrouping: false };
|
||||
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.hasIntl = hasIntl();
|
||||
|
||||
let z;
|
||||
if (dt.zone.universal && this.hasIntl) {
|
||||
// Chromium doesn't support fixed-offset zones like Etc/GMT+8 in its formatter,
|
||||
// See https://bugs.chromium.org/p/chromium/issues/detail?id=364374.
|
||||
// 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.
|
||||
// We can clean all this up when Chrome fixes this.
|
||||
z = "UTC";
|
||||
if (opts.timeZoneName) {
|
||||
this.dt = dt;
|
||||
} else {
|
||||
this.dt = dt.offset === 0 ? dt : DateTime.fromMillis(dt.ts + dt.offset * 60 * 1000);
|
||||
}
|
||||
} else if (dt.zone.type === "local") {
|
||||
this.dt = dt;
|
||||
} else {
|
||||
this.dt = dt;
|
||||
z = dt.zone.name;
|
||||
}
|
||||
|
||||
if (this.hasIntl) {
|
||||
const intlOpts = Object.assign({}, this.opts);
|
||||
if (z) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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 [];
|
||||
}
|
||||
}
|
||||
|
||||
resolvedOptions() {
|
||||
if (this.hasIntl) {
|
||||
return this.dtf.resolvedOptions();
|
||||
} else {
|
||||
return {
|
||||
locale: "en-US",
|
||||
numberingSystem: "latn",
|
||||
outputCalendar: "gregory"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class PolyRelFormatter {
|
||||
constructor(intl, isEnglish, opts) {
|
||||
this.opts = Object.assign({ 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 [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
||||
export default class Locale {
|
||||
static fromOpts(opts) {
|
||||
return Locale.create(opts.locale, opts.numberingSystem, opts.outputCalendar, opts.defaultToEN);
|
||||
}
|
||||
|
||||
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;
|
||||
return new Locale(localeR, numberingSystemR, outputCalendarR, specifiedLocale);
|
||||
}
|
||||
|
||||
static resetCache() {
|
||||
sysLocaleCache = null;
|
||||
intlDTCache = {};
|
||||
intlNumCache = {};
|
||||
intlRelCache = {};
|
||||
}
|
||||
|
||||
static fromObject({ locale, numberingSystem, outputCalendar } = {}) {
|
||||
return Locale.create(locale, numberingSystem, outputCalendar);
|
||||
}
|
||||
|
||||
constructor(locale, numbering, outputCalendar, specifiedLocale) {
|
||||
const [parsedLocale, parsedNumberingSystem, parsedOutputCalendar] = parseLocaleString(locale);
|
||||
|
||||
this.locale = parsedLocale;
|
||||
this.numberingSystem = numbering || parsedNumberingSystem || null;
|
||||
this.outputCalendar = outputCalendar || parsedOutputCalendar || null;
|
||||
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(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";
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
alts.defaultToEN || false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
redefaultToEN(alts = {}) {
|
||||
return this.clone(Object.assign({}, alts, { defaultToEN: true }));
|
||||
}
|
||||
|
||||
redefaultToSystem(alts = {}) {
|
||||
return this.clone(Object.assign({}, alts, { defaultToEN: false }));
|
||||
}
|
||||
|
||||
months(length, format = false, defaultOK = true) {
|
||||
return listStuff(this, length, defaultOK, English.months, () => {
|
||||
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"));
|
||||
}
|
||||
return this.monthsCache[formatStr][length];
|
||||
});
|
||||
}
|
||||
|
||||
weekdays(length, format = false, defaultOK = true) {
|
||||
return listStuff(this, length, defaultOK, 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(defaultOK = true) {
|
||||
return listStuff(
|
||||
this,
|
||||
undefined,
|
||||
defaultOK,
|
||||
() => 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", hour12: true };
|
||||
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, defaultOK = true) {
|
||||
return listStuff(this, length, defaultOK, English.eras, () => {
|
||||
const intl = { era: length };
|
||||
|
||||
// This is utter bullshit. 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);
|
||||
}
|
||||
|
||||
isEnglish() {
|
||||
return (
|
||||
this.locale === "en" ||
|
||||
this.locale.toLowerCase() === "en-us" ||
|
||||
(hasIntl() && new Intl.DateTimeFormat(this.intl).resolvedOptions().locale.startsWith("en-us"))
|
||||
);
|
||||
}
|
||||
|
||||
equals(other) {
|
||||
return (
|
||||
this.locale === other.locale &&
|
||||
this.numberingSystem === other.numberingSystem &&
|
||||
this.outputCalendar === other.outputCalendar
|
||||
);
|
||||
}
|
||||
}
|
315
node_modules/luxon/src/impl/regexParser.js
generated
vendored
Normal file
315
node_modules/luxon/src/impl/regexParser.js
generated
vendored
Normal file
|
@ -0,0 +1,315 @@
|
|||
import {
|
||||
untruncateYear,
|
||||
signedOffset,
|
||||
parseInteger,
|
||||
parseMillis,
|
||||
ianaRegex,
|
||||
isUndefined
|
||||
} 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.
|
||||
*/
|
||||
|
||||
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 [Object.assign(mergedVals, val), mergedZone || zone, 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 = /(?:(Z)|([+-]\d\d)(?::?(\d\d))?)/,
|
||||
isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,9}))?)?)?/,
|
||||
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})?`);
|
||||
|
||||
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 = {
|
||||
hour: int(match, cursor, 0),
|
||||
minute: int(match, cursor + 1, 0),
|
||||
second: int(match, cursor + 2, 0),
|
||||
millisecond: 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 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,9})(?:[.,](-?\d{1,9}))?S)?)?)$/;
|
||||
|
||||
function extractISODuration(match) {
|
||||
const [
|
||||
,
|
||||
yearStr,
|
||||
monthStr,
|
||||
weekStr,
|
||||
dayStr,
|
||||
hourStr,
|
||||
minuteStr,
|
||||
secondStr,
|
||||
millisecondsStr
|
||||
] = match;
|
||||
|
||||
return [
|
||||
{
|
||||
years: parseInteger(yearStr),
|
||||
months: parseInteger(monthStr),
|
||||
weeks: parseInteger(weekStr),
|
||||
days: parseInteger(dayStr),
|
||||
hours: parseInteger(hourStr),
|
||||
minutes: parseInteger(minuteStr),
|
||||
seconds: parseInteger(secondStr),
|
||||
milliseconds: parseMillis(millisecondsStr)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
// 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|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})$/;
|
||||
|
||||
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
|
||||
);
|
||||
const extractISOWeekTimeAndOffset = combineExtractors(
|
||||
extractISOWeekData,
|
||||
extractISOTime,
|
||||
extractISOOffset
|
||||
);
|
||||
const extractISOOrdinalDataAndTime = combineExtractors(extractISOOrdinalData, extractISOTime);
|
||||
const extractISOTimeAndOffset = combineExtractors(extractISOTime, extractISOOffset);
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
||||
export function parseISODate(s) {
|
||||
return parse(
|
||||
s,
|
||||
[isoYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset],
|
||||
[isoWeekWithTimeExtensionRegex, extractISOWeekTimeAndOffset],
|
||||
[isoOrdinalWithTimeExtensionRegex, extractISOOrdinalDataAndTime],
|
||||
[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 sqlYmdWithTimeExtensionRegex = combineRegexes(sqlYmdRegex, sqlTimeExtensionRegex);
|
||||
const sqlTimeCombinedRegex = combineRegexes(sqlTimeRegex);
|
||||
|
||||
const extractISOYmdTimeOffsetAndIANAZone = combineExtractors(
|
||||
extractISOYmd,
|
||||
extractISOTime,
|
||||
extractISOOffset,
|
||||
extractIANAZone
|
||||
);
|
||||
const extractISOTimeOffsetAndIANAZone = combineExtractors(
|
||||
extractISOTime,
|
||||
extractISOOffset,
|
||||
extractIANAZone
|
||||
);
|
||||
|
||||
export function parseSQL(s) {
|
||||
return parse(
|
||||
s,
|
||||
[sqlYmdWithTimeExtensionRegex, extractISOYmdTimeOffsetAndIANAZone],
|
||||
[sqlTimeCombinedRegex, extractISOTimeOffsetAndIANAZone]
|
||||
);
|
||||
}
|
416
node_modules/luxon/src/impl/tokenParser.js
generated
vendored
Normal file
416
node_modules/luxon/src/impl/tokenParser.js
generated
vendored
Normal file
|
@ -0,0 +1,416 @@
|
|||
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)) };
|
||||
}
|
||||
|
||||
function fixListRegex(s) {
|
||||
// make dots optional and also make them literal
|
||||
return s.replace(/\./, "\\.?");
|
||||
}
|
||||
|
||||
function stripInsensitivities(s) {
|
||||
return s.replace(/\./, "").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) {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
|
||||
}
|
||||
|
||||
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", false), 0);
|
||||
case "GG":
|
||||
return oneOf(loc.eras("long", false), 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, false), 1);
|
||||
case "MMMM":
|
||||
return oneOf(loc.months("long", true, false), 1);
|
||||
case "L":
|
||||
return intUnit(oneOrTwo);
|
||||
case "LL":
|
||||
return intUnit(two);
|
||||
case "LLL":
|
||||
return oneOf(loc.months("short", false, false), 1);
|
||||
case "LLLL":
|
||||
return oneOf(loc.months("long", false, 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);
|
||||
// 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, false), 1);
|
||||
case "EEEE":
|
||||
return oneOf(loc.weekdays("long", false, false), 1);
|
||||
case "ccc":
|
||||
return oneOf(loc.weekdays("short", true, false), 1);
|
||||
case "cccc":
|
||||
return oneOf(loc.weekdays("long", true, false), 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);
|
||||
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",
|
||||
hour: {
|
||||
numeric: "h",
|
||||
"2-digit": "hh"
|
||||
},
|
||||
minute: {
|
||||
numeric: "m",
|
||||
"2-digit": "mm"
|
||||
},
|
||||
second: {
|
||||
numeric: "s",
|
||||
"2-digit": "ss"
|
||||
}
|
||||
};
|
||||
|
||||
function tokenForPart(part, locale, formatOpts) {
|
||||
const { type, value } = part;
|
||||
|
||||
if (type === "literal") {
|
||||
return {
|
||||
literal: true,
|
||||
val: value
|
||||
};
|
||||
}
|
||||
|
||||
const style = formatOpts[type];
|
||||
|
||||
let val = partTypeStyleToTokenVal[type];
|
||||
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;
|
||||
if (!isUndefined(matches.Z)) {
|
||||
zone = new FixedOffsetZone(matches.Z);
|
||||
} else if (!isUndefined(matches.z)) {
|
||||
zone = IANAZone.create(matches.z);
|
||||
} else {
|
||||
zone = null;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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)) {
|
||||
return token;
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
function expandMacroTokens(tokens, locale) {
|
||||
return Array.prototype.concat(...tokens.map(t => maybeExpandMacroToken(t, locale)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
if (disqualifyingUnit) {
|
||||
return { input, tokens, invalidReason: disqualifyingUnit.invalidReason };
|
||||
} else {
|
||||
const [regexString, handlers] = buildRegex(units),
|
||||
regex = RegExp(regexString, "i"),
|
||||
[rawMatches, matches] = match(input, regex, handlers),
|
||||
[result, zone] = matches ? dateTimeFromMatches(matches) : [null, null];
|
||||
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 };
|
||||
}
|
||||
}
|
||||
|
||||
export function parseFromTokens(locale, input, format) {
|
||||
const { result, zone, invalidReason } = explainFromTokens(locale, input, format);
|
||||
return [result, zone, invalidReason];
|
||||
}
|
287
node_modules/luxon/src/impl/util.js
generated
vendored
Normal file
287
node_modules/luxon/src/impl/util.js
generated
vendored
Normal file
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
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";
|
||||
|
||||
/**
|
||||
* @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 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;
|
||||
} 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);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (input.toString().length < n) {
|
||||
return ("0".repeat(n) + input).slice(-n);
|
||||
} else {
|
||||
return input.toString();
|
||||
}
|
||||
}
|
||||
|
||||
export function parseInteger(string) {
|
||||
if (isUndefined(string) || string === null || string === "") {
|
||||
return undefined;
|
||||
} else {
|
||||
return parseInt(string, 10);
|
||||
}
|
||||
}
|
||||
|
||||
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, towardZero = false) {
|
||||
const factor = 10 ** digits,
|
||||
rounder = towardZero ? Math.trunc : Math.round;
|
||||
return rounder(number * factor) / factor;
|
||||
}
|
||||
|
||||
// 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];
|
||||
}
|
||||
}
|
||||
|
||||
// covert 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);
|
||||
d.setUTCFullYear(d.getUTCFullYear() - 1900);
|
||||
}
|
||||
return +d;
|
||||
}
|
||||
|
||||
export function weeksInWeekYear(weekYear) {
|
||||
const p1 =
|
||||
(weekYear +
|
||||
Math.floor(weekYear / 4) -
|
||||
Math.floor(weekYear / 100) +
|
||||
Math.floor(weekYear / 400)) %
|
||||
7,
|
||||
last = weekYear - 1,
|
||||
p2 = (last + Math.floor(last / 4) - Math.floor(last / 100) + Math.floor(last / 400)) % 7;
|
||||
return p1 === 4 || p2 === 3 ? 53 : 52;
|
||||
}
|
||||
|
||||
export function untruncateYear(year) {
|
||||
if (year > 99) {
|
||||
return year;
|
||||
} else return year > 60 ? 1900 + year : 2000 + year;
|
||||
}
|
||||
|
||||
// PARSING
|
||||
|
||||
export function parseZoneInfo(ts, offsetFormat, locale, timeZone = null) {
|
||||
const date = new Date(ts),
|
||||
intlOpts = {
|
||||
hour12: false,
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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.isNaN(numericValue))
|
||||
throw new InvalidArgumentError(`Invalid unit value ${value}`);
|
||||
return numericValue;
|
||||
}
|
||||
|
||||
export function normalizeObject(obj, normalizer, nonUnitKeys) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function formatOffset(offset, format) {
|
||||
const hours = Math.trunc(offset / 60),
|
||||
minutes = Math.abs(offset % 60),
|
||||
sign = hours >= 0 && !Object.is(hours, -0) ? "+" : "-",
|
||||
base = `${sign}${Math.abs(hours)}`;
|
||||
|
||||
switch (format) {
|
||||
case "short":
|
||||
return `${sign}${padStart(Math.abs(hours), 2)}:${padStart(minutes, 2)}`;
|
||||
case "narrow":
|
||||
return minutes > 0 ? `${base}:${minutes}` : base;
|
||||
case "techie":
|
||||
return `${sign}${padStart(Math.abs(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"]);
|
||||
}
|
||||
|
||||
export const ianaRegex = /[A-Za-z_+-]{1,256}(:?\/[A-Za-z_+-]{1,256}(\/[A-Za-z_+-]{1,256})?)?/;
|
36
node_modules/luxon/src/impl/zoneUtil.js
generated
vendored
Normal file
36
node_modules/luxon/src/impl/zoneUtil.js
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* @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";
|
||||
|
||||
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 === "local") return defaultZone;
|
||||
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 if (isNumber(input)) {
|
||||
return FixedOffsetZone.instance(input);
|
||||
} else if (typeof input === "object" && input.offset && typeof input.offset === "number") {
|
||||
// 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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue