@bpmn-io/form-js-playground 0.12.1 → 0.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/form-playground.umd.js +1256 -1155
- package/package.json +4 -4
|
@@ -1521,772 +1521,6 @@
|
|
|
1521
1521
|
timeZoneName: l$1
|
|
1522
1522
|
};
|
|
1523
1523
|
|
|
1524
|
-
/*
|
|
1525
|
-
This is just a junk drawer, containing anything used across multiple classes.
|
|
1526
|
-
Because Luxon is small(ish), this should stay small and we won't worry about splitting
|
|
1527
|
-
it up into, say, parsingUtil.js and basicUtil.js and so on. But they are divided up by feature area.
|
|
1528
|
-
*/
|
|
1529
|
-
|
|
1530
|
-
/**
|
|
1531
|
-
* @private
|
|
1532
|
-
*/
|
|
1533
|
-
|
|
1534
|
-
// TYPES
|
|
1535
|
-
|
|
1536
|
-
function isUndefined$1(o) {
|
|
1537
|
-
return typeof o === "undefined";
|
|
1538
|
-
}
|
|
1539
|
-
function isNumber$2(o) {
|
|
1540
|
-
return typeof o === "number";
|
|
1541
|
-
}
|
|
1542
|
-
function isInteger(o) {
|
|
1543
|
-
return typeof o === "number" && o % 1 === 0;
|
|
1544
|
-
}
|
|
1545
|
-
function isString$2(o) {
|
|
1546
|
-
return typeof o === "string";
|
|
1547
|
-
}
|
|
1548
|
-
function isDate(o) {
|
|
1549
|
-
return Object.prototype.toString.call(o) === "[object Date]";
|
|
1550
|
-
}
|
|
1551
|
-
|
|
1552
|
-
// CAPABILITIES
|
|
1553
|
-
|
|
1554
|
-
function hasRelative() {
|
|
1555
|
-
try {
|
|
1556
|
-
return typeof Intl !== "undefined" && !!Intl.RelativeTimeFormat;
|
|
1557
|
-
} catch (e) {
|
|
1558
|
-
return false;
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
// OBJECTS AND ARRAYS
|
|
1563
|
-
|
|
1564
|
-
function maybeArray(thing) {
|
|
1565
|
-
return Array.isArray(thing) ? thing : [thing];
|
|
1566
|
-
}
|
|
1567
|
-
function bestBy(arr, by, compare) {
|
|
1568
|
-
if (arr.length === 0) {
|
|
1569
|
-
return undefined;
|
|
1570
|
-
}
|
|
1571
|
-
return arr.reduce((best, next) => {
|
|
1572
|
-
const pair = [by(next), next];
|
|
1573
|
-
if (!best) {
|
|
1574
|
-
return pair;
|
|
1575
|
-
} else if (compare(best[0], pair[0]) === best[0]) {
|
|
1576
|
-
return best;
|
|
1577
|
-
} else {
|
|
1578
|
-
return pair;
|
|
1579
|
-
}
|
|
1580
|
-
}, null)[1];
|
|
1581
|
-
}
|
|
1582
|
-
function pick(obj, keys) {
|
|
1583
|
-
return keys.reduce((a, k) => {
|
|
1584
|
-
a[k] = obj[k];
|
|
1585
|
-
return a;
|
|
1586
|
-
}, {});
|
|
1587
|
-
}
|
|
1588
|
-
function hasOwnProperty(obj, prop) {
|
|
1589
|
-
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
1590
|
-
}
|
|
1591
|
-
|
|
1592
|
-
// NUMBERS AND STRINGS
|
|
1593
|
-
|
|
1594
|
-
function integerBetween(thing, bottom, top) {
|
|
1595
|
-
return isInteger(thing) && thing >= bottom && thing <= top;
|
|
1596
|
-
}
|
|
1597
|
-
|
|
1598
|
-
// x % n but takes the sign of n instead of x
|
|
1599
|
-
function floorMod(x, n) {
|
|
1600
|
-
return x - n * Math.floor(x / n);
|
|
1601
|
-
}
|
|
1602
|
-
function padStart(input, n = 2) {
|
|
1603
|
-
const isNeg = input < 0;
|
|
1604
|
-
let padded;
|
|
1605
|
-
if (isNeg) {
|
|
1606
|
-
padded = "-" + ("" + -input).padStart(n, "0");
|
|
1607
|
-
} else {
|
|
1608
|
-
padded = ("" + input).padStart(n, "0");
|
|
1609
|
-
}
|
|
1610
|
-
return padded;
|
|
1611
|
-
}
|
|
1612
|
-
function parseInteger(string) {
|
|
1613
|
-
if (isUndefined$1(string) || string === null || string === "") {
|
|
1614
|
-
return undefined;
|
|
1615
|
-
} else {
|
|
1616
|
-
return parseInt(string, 10);
|
|
1617
|
-
}
|
|
1618
|
-
}
|
|
1619
|
-
function parseFloating(string) {
|
|
1620
|
-
if (isUndefined$1(string) || string === null || string === "") {
|
|
1621
|
-
return undefined;
|
|
1622
|
-
} else {
|
|
1623
|
-
return parseFloat(string);
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1626
|
-
function parseMillis(fraction) {
|
|
1627
|
-
// Return undefined (instead of 0) in these cases, where fraction is not set
|
|
1628
|
-
if (isUndefined$1(fraction) || fraction === null || fraction === "") {
|
|
1629
|
-
return undefined;
|
|
1630
|
-
} else {
|
|
1631
|
-
const f = parseFloat("0." + fraction) * 1000;
|
|
1632
|
-
return Math.floor(f);
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
function roundTo(number, digits, towardZero = false) {
|
|
1636
|
-
const factor = 10 ** digits,
|
|
1637
|
-
rounder = towardZero ? Math.trunc : Math.round;
|
|
1638
|
-
return rounder(number * factor) / factor;
|
|
1639
|
-
}
|
|
1640
|
-
|
|
1641
|
-
// DATE BASICS
|
|
1642
|
-
|
|
1643
|
-
function isLeapYear(year) {
|
|
1644
|
-
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
1645
|
-
}
|
|
1646
|
-
function daysInYear(year) {
|
|
1647
|
-
return isLeapYear(year) ? 366 : 365;
|
|
1648
|
-
}
|
|
1649
|
-
function daysInMonth(year, month) {
|
|
1650
|
-
const modMonth = floorMod(month - 1, 12) + 1,
|
|
1651
|
-
modYear = year + (month - modMonth) / 12;
|
|
1652
|
-
if (modMonth === 2) {
|
|
1653
|
-
return isLeapYear(modYear) ? 29 : 28;
|
|
1654
|
-
} else {
|
|
1655
|
-
return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][modMonth - 1];
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
// covert a calendar object to a local timestamp (epoch, but with the offset baked in)
|
|
1660
|
-
function objToLocalTS(obj) {
|
|
1661
|
-
let d = Date.UTC(obj.year, obj.month - 1, obj.day, obj.hour, obj.minute, obj.second, obj.millisecond);
|
|
1662
|
-
|
|
1663
|
-
// for legacy reasons, years between 0 and 99 are interpreted as 19XX; revert that
|
|
1664
|
-
if (obj.year < 100 && obj.year >= 0) {
|
|
1665
|
-
d = new Date(d);
|
|
1666
|
-
d.setUTCFullYear(d.getUTCFullYear() - 1900);
|
|
1667
|
-
}
|
|
1668
|
-
return +d;
|
|
1669
|
-
}
|
|
1670
|
-
function weeksInWeekYear(weekYear) {
|
|
1671
|
-
const p1 = (weekYear + Math.floor(weekYear / 4) - Math.floor(weekYear / 100) + Math.floor(weekYear / 400)) % 7,
|
|
1672
|
-
last = weekYear - 1,
|
|
1673
|
-
p2 = (last + Math.floor(last / 4) - Math.floor(last / 100) + Math.floor(last / 400)) % 7;
|
|
1674
|
-
return p1 === 4 || p2 === 3 ? 53 : 52;
|
|
1675
|
-
}
|
|
1676
|
-
function untruncateYear(year) {
|
|
1677
|
-
if (year > 99) {
|
|
1678
|
-
return year;
|
|
1679
|
-
} else return year > 60 ? 1900 + year : 2000 + year;
|
|
1680
|
-
}
|
|
1681
|
-
|
|
1682
|
-
// PARSING
|
|
1683
|
-
|
|
1684
|
-
function parseZoneInfo(ts, offsetFormat, locale, timeZone = null) {
|
|
1685
|
-
const date = new Date(ts),
|
|
1686
|
-
intlOpts = {
|
|
1687
|
-
hourCycle: "h23",
|
|
1688
|
-
year: "numeric",
|
|
1689
|
-
month: "2-digit",
|
|
1690
|
-
day: "2-digit",
|
|
1691
|
-
hour: "2-digit",
|
|
1692
|
-
minute: "2-digit"
|
|
1693
|
-
};
|
|
1694
|
-
if (timeZone) {
|
|
1695
|
-
intlOpts.timeZone = timeZone;
|
|
1696
|
-
}
|
|
1697
|
-
const modified = {
|
|
1698
|
-
timeZoneName: offsetFormat,
|
|
1699
|
-
...intlOpts
|
|
1700
|
-
};
|
|
1701
|
-
const parsed = new Intl.DateTimeFormat(locale, modified).formatToParts(date).find(m => m.type.toLowerCase() === "timezonename");
|
|
1702
|
-
return parsed ? parsed.value : null;
|
|
1703
|
-
}
|
|
1704
|
-
|
|
1705
|
-
// signedOffset('-5', '30') -> -330
|
|
1706
|
-
function signedOffset(offHourStr, offMinuteStr) {
|
|
1707
|
-
let offHour = parseInt(offHourStr, 10);
|
|
1708
|
-
|
|
1709
|
-
// don't || this because we want to preserve -0
|
|
1710
|
-
if (Number.isNaN(offHour)) {
|
|
1711
|
-
offHour = 0;
|
|
1712
|
-
}
|
|
1713
|
-
const offMin = parseInt(offMinuteStr, 10) || 0,
|
|
1714
|
-
offMinSigned = offHour < 0 || Object.is(offHour, -0) ? -offMin : offMin;
|
|
1715
|
-
return offHour * 60 + offMinSigned;
|
|
1716
|
-
}
|
|
1717
|
-
|
|
1718
|
-
// COERCION
|
|
1719
|
-
|
|
1720
|
-
function asNumber(value) {
|
|
1721
|
-
const numericValue = Number(value);
|
|
1722
|
-
if (typeof value === "boolean" || value === "" || Number.isNaN(numericValue)) throw new InvalidArgumentError(`Invalid unit value ${value}`);
|
|
1723
|
-
return numericValue;
|
|
1724
|
-
}
|
|
1725
|
-
function normalizeObject(obj, normalizer) {
|
|
1726
|
-
const normalized = {};
|
|
1727
|
-
for (const u in obj) {
|
|
1728
|
-
if (hasOwnProperty(obj, u)) {
|
|
1729
|
-
const v = obj[u];
|
|
1730
|
-
if (v === undefined || v === null) continue;
|
|
1731
|
-
normalized[normalizer(u)] = asNumber(v);
|
|
1732
|
-
}
|
|
1733
|
-
}
|
|
1734
|
-
return normalized;
|
|
1735
|
-
}
|
|
1736
|
-
function formatOffset(offset, format) {
|
|
1737
|
-
const hours = Math.trunc(Math.abs(offset / 60)),
|
|
1738
|
-
minutes = Math.trunc(Math.abs(offset % 60)),
|
|
1739
|
-
sign = offset >= 0 ? "+" : "-";
|
|
1740
|
-
switch (format) {
|
|
1741
|
-
case "short":
|
|
1742
|
-
return `${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}`;
|
|
1743
|
-
case "narrow":
|
|
1744
|
-
return `${sign}${hours}${minutes > 0 ? `:${minutes}` : ""}`;
|
|
1745
|
-
case "techie":
|
|
1746
|
-
return `${sign}${padStart(hours, 2)}${padStart(minutes, 2)}`;
|
|
1747
|
-
default:
|
|
1748
|
-
throw new RangeError(`Value format ${format} is out of range for property format`);
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
function timeObject(obj) {
|
|
1752
|
-
return pick(obj, ["hour", "minute", "second", "millisecond"]);
|
|
1753
|
-
}
|
|
1754
|
-
const ianaRegex = /[A-Za-z_+-]{1,256}(?::?\/[A-Za-z0-9_+-]{1,256}(?:\/[A-Za-z0-9_+-]{1,256})?)?/;
|
|
1755
|
-
|
|
1756
|
-
/**
|
|
1757
|
-
* @private
|
|
1758
|
-
*/
|
|
1759
|
-
|
|
1760
|
-
const monthsLong = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
1761
|
-
const monthsShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
1762
|
-
const monthsNarrow = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"];
|
|
1763
|
-
function months(length) {
|
|
1764
|
-
switch (length) {
|
|
1765
|
-
case "narrow":
|
|
1766
|
-
return [...monthsNarrow];
|
|
1767
|
-
case "short":
|
|
1768
|
-
return [...monthsShort];
|
|
1769
|
-
case "long":
|
|
1770
|
-
return [...monthsLong];
|
|
1771
|
-
case "numeric":
|
|
1772
|
-
return ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
|
|
1773
|
-
case "2-digit":
|
|
1774
|
-
return ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
|
|
1775
|
-
default:
|
|
1776
|
-
return null;
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
const weekdaysLong = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
|
1780
|
-
const weekdaysShort = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
1781
|
-
const weekdaysNarrow = ["M", "T", "W", "T", "F", "S", "S"];
|
|
1782
|
-
function weekdays(length) {
|
|
1783
|
-
switch (length) {
|
|
1784
|
-
case "narrow":
|
|
1785
|
-
return [...weekdaysNarrow];
|
|
1786
|
-
case "short":
|
|
1787
|
-
return [...weekdaysShort];
|
|
1788
|
-
case "long":
|
|
1789
|
-
return [...weekdaysLong];
|
|
1790
|
-
case "numeric":
|
|
1791
|
-
return ["1", "2", "3", "4", "5", "6", "7"];
|
|
1792
|
-
default:
|
|
1793
|
-
return null;
|
|
1794
|
-
}
|
|
1795
|
-
}
|
|
1796
|
-
const meridiems = ["AM", "PM"];
|
|
1797
|
-
const erasLong = ["Before Christ", "Anno Domini"];
|
|
1798
|
-
const erasShort = ["BC", "AD"];
|
|
1799
|
-
const erasNarrow = ["B", "A"];
|
|
1800
|
-
function eras(length) {
|
|
1801
|
-
switch (length) {
|
|
1802
|
-
case "narrow":
|
|
1803
|
-
return [...erasNarrow];
|
|
1804
|
-
case "short":
|
|
1805
|
-
return [...erasShort];
|
|
1806
|
-
case "long":
|
|
1807
|
-
return [...erasLong];
|
|
1808
|
-
default:
|
|
1809
|
-
return null;
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
function meridiemForDateTime(dt) {
|
|
1813
|
-
return meridiems[dt.hour < 12 ? 0 : 1];
|
|
1814
|
-
}
|
|
1815
|
-
function weekdayForDateTime(dt, length) {
|
|
1816
|
-
return weekdays(length)[dt.weekday - 1];
|
|
1817
|
-
}
|
|
1818
|
-
function monthForDateTime(dt, length) {
|
|
1819
|
-
return months(length)[dt.month - 1];
|
|
1820
|
-
}
|
|
1821
|
-
function eraForDateTime(dt, length) {
|
|
1822
|
-
return eras(length)[dt.year < 0 ? 0 : 1];
|
|
1823
|
-
}
|
|
1824
|
-
function formatRelativeTime(unit, count, numeric = "always", narrow = false) {
|
|
1825
|
-
const units = {
|
|
1826
|
-
years: ["year", "yr."],
|
|
1827
|
-
quarters: ["quarter", "qtr."],
|
|
1828
|
-
months: ["month", "mo."],
|
|
1829
|
-
weeks: ["week", "wk."],
|
|
1830
|
-
days: ["day", "day", "days"],
|
|
1831
|
-
hours: ["hour", "hr."],
|
|
1832
|
-
minutes: ["minute", "min."],
|
|
1833
|
-
seconds: ["second", "sec."]
|
|
1834
|
-
};
|
|
1835
|
-
const lastable = ["hours", "minutes", "seconds"].indexOf(unit) === -1;
|
|
1836
|
-
if (numeric === "auto" && lastable) {
|
|
1837
|
-
const isDay = unit === "days";
|
|
1838
|
-
switch (count) {
|
|
1839
|
-
case 1:
|
|
1840
|
-
return isDay ? "tomorrow" : `next ${units[unit][0]}`;
|
|
1841
|
-
case -1:
|
|
1842
|
-
return isDay ? "yesterday" : `last ${units[unit][0]}`;
|
|
1843
|
-
case 0:
|
|
1844
|
-
return isDay ? "today" : `this ${units[unit][0]}`;
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
|
-
const isInPast = Object.is(count, -0) || count < 0,
|
|
1849
|
-
fmtValue = Math.abs(count),
|
|
1850
|
-
singular = fmtValue === 1,
|
|
1851
|
-
lilUnits = units[unit],
|
|
1852
|
-
fmtUnit = narrow ? singular ? lilUnits[1] : lilUnits[2] || lilUnits[1] : singular ? units[unit][0] : unit;
|
|
1853
|
-
return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}`;
|
|
1854
|
-
}
|
|
1855
|
-
|
|
1856
|
-
function stringifyTokens(splits, tokenToString) {
|
|
1857
|
-
let s = "";
|
|
1858
|
-
for (const token of splits) {
|
|
1859
|
-
if (token.literal) {
|
|
1860
|
-
s += token.val;
|
|
1861
|
-
} else {
|
|
1862
|
-
s += tokenToString(token.val);
|
|
1863
|
-
}
|
|
1864
|
-
}
|
|
1865
|
-
return s;
|
|
1866
|
-
}
|
|
1867
|
-
const macroTokenToFormatOpts = {
|
|
1868
|
-
D: DATE_SHORT,
|
|
1869
|
-
DD: DATE_MED,
|
|
1870
|
-
DDD: DATE_FULL,
|
|
1871
|
-
DDDD: DATE_HUGE,
|
|
1872
|
-
t: TIME_SIMPLE,
|
|
1873
|
-
tt: TIME_WITH_SECONDS,
|
|
1874
|
-
ttt: TIME_WITH_SHORT_OFFSET,
|
|
1875
|
-
tttt: TIME_WITH_LONG_OFFSET,
|
|
1876
|
-
T: TIME_24_SIMPLE,
|
|
1877
|
-
TT: TIME_24_WITH_SECONDS,
|
|
1878
|
-
TTT: TIME_24_WITH_SHORT_OFFSET,
|
|
1879
|
-
TTTT: TIME_24_WITH_LONG_OFFSET,
|
|
1880
|
-
f: DATETIME_SHORT,
|
|
1881
|
-
ff: DATETIME_MED,
|
|
1882
|
-
fff: DATETIME_FULL,
|
|
1883
|
-
ffff: DATETIME_HUGE,
|
|
1884
|
-
F: DATETIME_SHORT_WITH_SECONDS,
|
|
1885
|
-
FF: DATETIME_MED_WITH_SECONDS,
|
|
1886
|
-
FFF: DATETIME_FULL_WITH_SECONDS,
|
|
1887
|
-
FFFF: DATETIME_HUGE_WITH_SECONDS
|
|
1888
|
-
};
|
|
1889
|
-
|
|
1890
|
-
/**
|
|
1891
|
-
* @private
|
|
1892
|
-
*/
|
|
1893
|
-
|
|
1894
|
-
class Formatter {
|
|
1895
|
-
static create(locale, opts = {}) {
|
|
1896
|
-
return new Formatter(locale, opts);
|
|
1897
|
-
}
|
|
1898
|
-
static parseFormat(fmt) {
|
|
1899
|
-
let current = null,
|
|
1900
|
-
currentFull = "",
|
|
1901
|
-
bracketed = false;
|
|
1902
|
-
const splits = [];
|
|
1903
|
-
for (let i = 0; i < fmt.length; i++) {
|
|
1904
|
-
const c = fmt.charAt(i);
|
|
1905
|
-
if (c === "'") {
|
|
1906
|
-
if (currentFull.length > 0) {
|
|
1907
|
-
splits.push({
|
|
1908
|
-
literal: bracketed,
|
|
1909
|
-
val: currentFull
|
|
1910
|
-
});
|
|
1911
|
-
}
|
|
1912
|
-
current = null;
|
|
1913
|
-
currentFull = "";
|
|
1914
|
-
bracketed = !bracketed;
|
|
1915
|
-
} else if (bracketed) {
|
|
1916
|
-
currentFull += c;
|
|
1917
|
-
} else if (c === current) {
|
|
1918
|
-
currentFull += c;
|
|
1919
|
-
} else {
|
|
1920
|
-
if (currentFull.length > 0) {
|
|
1921
|
-
splits.push({
|
|
1922
|
-
literal: false,
|
|
1923
|
-
val: currentFull
|
|
1924
|
-
});
|
|
1925
|
-
}
|
|
1926
|
-
currentFull = c;
|
|
1927
|
-
current = c;
|
|
1928
|
-
}
|
|
1929
|
-
}
|
|
1930
|
-
if (currentFull.length > 0) {
|
|
1931
|
-
splits.push({
|
|
1932
|
-
literal: bracketed,
|
|
1933
|
-
val: currentFull
|
|
1934
|
-
});
|
|
1935
|
-
}
|
|
1936
|
-
return splits;
|
|
1937
|
-
}
|
|
1938
|
-
static macroTokenToFormatOpts(token) {
|
|
1939
|
-
return macroTokenToFormatOpts[token];
|
|
1940
|
-
}
|
|
1941
|
-
constructor(locale, formatOpts) {
|
|
1942
|
-
this.opts = formatOpts;
|
|
1943
|
-
this.loc = locale;
|
|
1944
|
-
this.systemLoc = null;
|
|
1945
|
-
}
|
|
1946
|
-
formatWithSystemDefault(dt, opts) {
|
|
1947
|
-
if (this.systemLoc === null) {
|
|
1948
|
-
this.systemLoc = this.loc.redefaultToSystem();
|
|
1949
|
-
}
|
|
1950
|
-
const df = this.systemLoc.dtFormatter(dt, {
|
|
1951
|
-
...this.opts,
|
|
1952
|
-
...opts
|
|
1953
|
-
});
|
|
1954
|
-
return df.format();
|
|
1955
|
-
}
|
|
1956
|
-
formatDateTime(dt, opts = {}) {
|
|
1957
|
-
const df = this.loc.dtFormatter(dt, {
|
|
1958
|
-
...this.opts,
|
|
1959
|
-
...opts
|
|
1960
|
-
});
|
|
1961
|
-
return df.format();
|
|
1962
|
-
}
|
|
1963
|
-
formatDateTimeParts(dt, opts = {}) {
|
|
1964
|
-
const df = this.loc.dtFormatter(dt, {
|
|
1965
|
-
...this.opts,
|
|
1966
|
-
...opts
|
|
1967
|
-
});
|
|
1968
|
-
return df.formatToParts();
|
|
1969
|
-
}
|
|
1970
|
-
resolvedOptions(dt, opts = {}) {
|
|
1971
|
-
const df = this.loc.dtFormatter(dt, {
|
|
1972
|
-
...this.opts,
|
|
1973
|
-
...opts
|
|
1974
|
-
});
|
|
1975
|
-
return df.resolvedOptions();
|
|
1976
|
-
}
|
|
1977
|
-
num(n, p = 0) {
|
|
1978
|
-
// we get some perf out of doing this here, annoyingly
|
|
1979
|
-
if (this.opts.forceSimple) {
|
|
1980
|
-
return padStart(n, p);
|
|
1981
|
-
}
|
|
1982
|
-
const opts = {
|
|
1983
|
-
...this.opts
|
|
1984
|
-
};
|
|
1985
|
-
if (p > 0) {
|
|
1986
|
-
opts.padTo = p;
|
|
1987
|
-
}
|
|
1988
|
-
return this.loc.numberFormatter(opts).format(n);
|
|
1989
|
-
}
|
|
1990
|
-
formatDateTimeFromString(dt, fmt) {
|
|
1991
|
-
const knownEnglish = this.loc.listingMode() === "en",
|
|
1992
|
-
useDateTimeFormatter = this.loc.outputCalendar && this.loc.outputCalendar !== "gregory",
|
|
1993
|
-
string = (opts, extract) => this.loc.extract(dt, opts, extract),
|
|
1994
|
-
formatOffset = opts => {
|
|
1995
|
-
if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) {
|
|
1996
|
-
return "Z";
|
|
1997
|
-
}
|
|
1998
|
-
return dt.isValid ? dt.zone.formatOffset(dt.ts, opts.format) : "";
|
|
1999
|
-
},
|
|
2000
|
-
meridiem = () => knownEnglish ? meridiemForDateTime(dt) : string({
|
|
2001
|
-
hour: "numeric",
|
|
2002
|
-
hourCycle: "h12"
|
|
2003
|
-
}, "dayperiod"),
|
|
2004
|
-
month = (length, standalone) => knownEnglish ? monthForDateTime(dt, length) : string(standalone ? {
|
|
2005
|
-
month: length
|
|
2006
|
-
} : {
|
|
2007
|
-
month: length,
|
|
2008
|
-
day: "numeric"
|
|
2009
|
-
}, "month"),
|
|
2010
|
-
weekday = (length, standalone) => knownEnglish ? weekdayForDateTime(dt, length) : string(standalone ? {
|
|
2011
|
-
weekday: length
|
|
2012
|
-
} : {
|
|
2013
|
-
weekday: length,
|
|
2014
|
-
month: "long",
|
|
2015
|
-
day: "numeric"
|
|
2016
|
-
}, "weekday"),
|
|
2017
|
-
maybeMacro = token => {
|
|
2018
|
-
const formatOpts = Formatter.macroTokenToFormatOpts(token);
|
|
2019
|
-
if (formatOpts) {
|
|
2020
|
-
return this.formatWithSystemDefault(dt, formatOpts);
|
|
2021
|
-
} else {
|
|
2022
|
-
return token;
|
|
2023
|
-
}
|
|
2024
|
-
},
|
|
2025
|
-
era = length => knownEnglish ? eraForDateTime(dt, length) : string({
|
|
2026
|
-
era: length
|
|
2027
|
-
}, "era"),
|
|
2028
|
-
tokenToString = token => {
|
|
2029
|
-
// Where possible: http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles
|
|
2030
|
-
switch (token) {
|
|
2031
|
-
// ms
|
|
2032
|
-
case "S":
|
|
2033
|
-
return this.num(dt.millisecond);
|
|
2034
|
-
case "u":
|
|
2035
|
-
// falls through
|
|
2036
|
-
case "SSS":
|
|
2037
|
-
return this.num(dt.millisecond, 3);
|
|
2038
|
-
// seconds
|
|
2039
|
-
case "s":
|
|
2040
|
-
return this.num(dt.second);
|
|
2041
|
-
case "ss":
|
|
2042
|
-
return this.num(dt.second, 2);
|
|
2043
|
-
// fractional seconds
|
|
2044
|
-
case "uu":
|
|
2045
|
-
return this.num(Math.floor(dt.millisecond / 10), 2);
|
|
2046
|
-
case "uuu":
|
|
2047
|
-
return this.num(Math.floor(dt.millisecond / 100));
|
|
2048
|
-
// minutes
|
|
2049
|
-
case "m":
|
|
2050
|
-
return this.num(dt.minute);
|
|
2051
|
-
case "mm":
|
|
2052
|
-
return this.num(dt.minute, 2);
|
|
2053
|
-
// hours
|
|
2054
|
-
case "h":
|
|
2055
|
-
return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12);
|
|
2056
|
-
case "hh":
|
|
2057
|
-
return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12, 2);
|
|
2058
|
-
case "H":
|
|
2059
|
-
return this.num(dt.hour);
|
|
2060
|
-
case "HH":
|
|
2061
|
-
return this.num(dt.hour, 2);
|
|
2062
|
-
// offset
|
|
2063
|
-
case "Z":
|
|
2064
|
-
// like +6
|
|
2065
|
-
return formatOffset({
|
|
2066
|
-
format: "narrow",
|
|
2067
|
-
allowZ: this.opts.allowZ
|
|
2068
|
-
});
|
|
2069
|
-
case "ZZ":
|
|
2070
|
-
// like +06:00
|
|
2071
|
-
return formatOffset({
|
|
2072
|
-
format: "short",
|
|
2073
|
-
allowZ: this.opts.allowZ
|
|
2074
|
-
});
|
|
2075
|
-
case "ZZZ":
|
|
2076
|
-
// like +0600
|
|
2077
|
-
return formatOffset({
|
|
2078
|
-
format: "techie",
|
|
2079
|
-
allowZ: this.opts.allowZ
|
|
2080
|
-
});
|
|
2081
|
-
case "ZZZZ":
|
|
2082
|
-
// like EST
|
|
2083
|
-
return dt.zone.offsetName(dt.ts, {
|
|
2084
|
-
format: "short",
|
|
2085
|
-
locale: this.loc.locale
|
|
2086
|
-
});
|
|
2087
|
-
case "ZZZZZ":
|
|
2088
|
-
// like Eastern Standard Time
|
|
2089
|
-
return dt.zone.offsetName(dt.ts, {
|
|
2090
|
-
format: "long",
|
|
2091
|
-
locale: this.loc.locale
|
|
2092
|
-
});
|
|
2093
|
-
// zone
|
|
2094
|
-
case "z":
|
|
2095
|
-
// like America/New_York
|
|
2096
|
-
return dt.zoneName;
|
|
2097
|
-
// meridiems
|
|
2098
|
-
case "a":
|
|
2099
|
-
return meridiem();
|
|
2100
|
-
// dates
|
|
2101
|
-
case "d":
|
|
2102
|
-
return useDateTimeFormatter ? string({
|
|
2103
|
-
day: "numeric"
|
|
2104
|
-
}, "day") : this.num(dt.day);
|
|
2105
|
-
case "dd":
|
|
2106
|
-
return useDateTimeFormatter ? string({
|
|
2107
|
-
day: "2-digit"
|
|
2108
|
-
}, "day") : this.num(dt.day, 2);
|
|
2109
|
-
// weekdays - standalone
|
|
2110
|
-
case "c":
|
|
2111
|
-
// like 1
|
|
2112
|
-
return this.num(dt.weekday);
|
|
2113
|
-
case "ccc":
|
|
2114
|
-
// like 'Tues'
|
|
2115
|
-
return weekday("short", true);
|
|
2116
|
-
case "cccc":
|
|
2117
|
-
// like 'Tuesday'
|
|
2118
|
-
return weekday("long", true);
|
|
2119
|
-
case "ccccc":
|
|
2120
|
-
// like 'T'
|
|
2121
|
-
return weekday("narrow", true);
|
|
2122
|
-
// weekdays - format
|
|
2123
|
-
case "E":
|
|
2124
|
-
// like 1
|
|
2125
|
-
return this.num(dt.weekday);
|
|
2126
|
-
case "EEE":
|
|
2127
|
-
// like 'Tues'
|
|
2128
|
-
return weekday("short", false);
|
|
2129
|
-
case "EEEE":
|
|
2130
|
-
// like 'Tuesday'
|
|
2131
|
-
return weekday("long", false);
|
|
2132
|
-
case "EEEEE":
|
|
2133
|
-
// like 'T'
|
|
2134
|
-
return weekday("narrow", false);
|
|
2135
|
-
// months - standalone
|
|
2136
|
-
case "L":
|
|
2137
|
-
// like 1
|
|
2138
|
-
return useDateTimeFormatter ? string({
|
|
2139
|
-
month: "numeric",
|
|
2140
|
-
day: "numeric"
|
|
2141
|
-
}, "month") : this.num(dt.month);
|
|
2142
|
-
case "LL":
|
|
2143
|
-
// like 01, doesn't seem to work
|
|
2144
|
-
return useDateTimeFormatter ? string({
|
|
2145
|
-
month: "2-digit",
|
|
2146
|
-
day: "numeric"
|
|
2147
|
-
}, "month") : this.num(dt.month, 2);
|
|
2148
|
-
case "LLL":
|
|
2149
|
-
// like Jan
|
|
2150
|
-
return month("short", true);
|
|
2151
|
-
case "LLLL":
|
|
2152
|
-
// like January
|
|
2153
|
-
return month("long", true);
|
|
2154
|
-
case "LLLLL":
|
|
2155
|
-
// like J
|
|
2156
|
-
return month("narrow", true);
|
|
2157
|
-
// months - format
|
|
2158
|
-
case "M":
|
|
2159
|
-
// like 1
|
|
2160
|
-
return useDateTimeFormatter ? string({
|
|
2161
|
-
month: "numeric"
|
|
2162
|
-
}, "month") : this.num(dt.month);
|
|
2163
|
-
case "MM":
|
|
2164
|
-
// like 01
|
|
2165
|
-
return useDateTimeFormatter ? string({
|
|
2166
|
-
month: "2-digit"
|
|
2167
|
-
}, "month") : this.num(dt.month, 2);
|
|
2168
|
-
case "MMM":
|
|
2169
|
-
// like Jan
|
|
2170
|
-
return month("short", false);
|
|
2171
|
-
case "MMMM":
|
|
2172
|
-
// like January
|
|
2173
|
-
return month("long", false);
|
|
2174
|
-
case "MMMMM":
|
|
2175
|
-
// like J
|
|
2176
|
-
return month("narrow", false);
|
|
2177
|
-
// years
|
|
2178
|
-
case "y":
|
|
2179
|
-
// like 2014
|
|
2180
|
-
return useDateTimeFormatter ? string({
|
|
2181
|
-
year: "numeric"
|
|
2182
|
-
}, "year") : this.num(dt.year);
|
|
2183
|
-
case "yy":
|
|
2184
|
-
// like 14
|
|
2185
|
-
return useDateTimeFormatter ? string({
|
|
2186
|
-
year: "2-digit"
|
|
2187
|
-
}, "year") : this.num(dt.year.toString().slice(-2), 2);
|
|
2188
|
-
case "yyyy":
|
|
2189
|
-
// like 0012
|
|
2190
|
-
return useDateTimeFormatter ? string({
|
|
2191
|
-
year: "numeric"
|
|
2192
|
-
}, "year") : this.num(dt.year, 4);
|
|
2193
|
-
case "yyyyyy":
|
|
2194
|
-
// like 000012
|
|
2195
|
-
return useDateTimeFormatter ? string({
|
|
2196
|
-
year: "numeric"
|
|
2197
|
-
}, "year") : this.num(dt.year, 6);
|
|
2198
|
-
// eras
|
|
2199
|
-
case "G":
|
|
2200
|
-
// like AD
|
|
2201
|
-
return era("short");
|
|
2202
|
-
case "GG":
|
|
2203
|
-
// like Anno Domini
|
|
2204
|
-
return era("long");
|
|
2205
|
-
case "GGGGG":
|
|
2206
|
-
return era("narrow");
|
|
2207
|
-
case "kk":
|
|
2208
|
-
return this.num(dt.weekYear.toString().slice(-2), 2);
|
|
2209
|
-
case "kkkk":
|
|
2210
|
-
return this.num(dt.weekYear, 4);
|
|
2211
|
-
case "W":
|
|
2212
|
-
return this.num(dt.weekNumber);
|
|
2213
|
-
case "WW":
|
|
2214
|
-
return this.num(dt.weekNumber, 2);
|
|
2215
|
-
case "o":
|
|
2216
|
-
return this.num(dt.ordinal);
|
|
2217
|
-
case "ooo":
|
|
2218
|
-
return this.num(dt.ordinal, 3);
|
|
2219
|
-
case "q":
|
|
2220
|
-
// like 1
|
|
2221
|
-
return this.num(dt.quarter);
|
|
2222
|
-
case "qq":
|
|
2223
|
-
// like 01
|
|
2224
|
-
return this.num(dt.quarter, 2);
|
|
2225
|
-
case "X":
|
|
2226
|
-
return this.num(Math.floor(dt.ts / 1000));
|
|
2227
|
-
case "x":
|
|
2228
|
-
return this.num(dt.ts);
|
|
2229
|
-
default:
|
|
2230
|
-
return maybeMacro(token);
|
|
2231
|
-
}
|
|
2232
|
-
};
|
|
2233
|
-
return stringifyTokens(Formatter.parseFormat(fmt), tokenToString);
|
|
2234
|
-
}
|
|
2235
|
-
formatDurationFromString(dur, fmt) {
|
|
2236
|
-
const tokenToField = token => {
|
|
2237
|
-
switch (token[0]) {
|
|
2238
|
-
case "S":
|
|
2239
|
-
return "millisecond";
|
|
2240
|
-
case "s":
|
|
2241
|
-
return "second";
|
|
2242
|
-
case "m":
|
|
2243
|
-
return "minute";
|
|
2244
|
-
case "h":
|
|
2245
|
-
return "hour";
|
|
2246
|
-
case "d":
|
|
2247
|
-
return "day";
|
|
2248
|
-
case "w":
|
|
2249
|
-
return "week";
|
|
2250
|
-
case "M":
|
|
2251
|
-
return "month";
|
|
2252
|
-
case "y":
|
|
2253
|
-
return "year";
|
|
2254
|
-
default:
|
|
2255
|
-
return null;
|
|
2256
|
-
}
|
|
2257
|
-
},
|
|
2258
|
-
tokenToString = lildur => token => {
|
|
2259
|
-
const mapped = tokenToField(token);
|
|
2260
|
-
if (mapped) {
|
|
2261
|
-
return this.num(lildur.get(mapped), token.length);
|
|
2262
|
-
} else {
|
|
2263
|
-
return token;
|
|
2264
|
-
}
|
|
2265
|
-
},
|
|
2266
|
-
tokens = Formatter.parseFormat(fmt),
|
|
2267
|
-
realTokens = tokens.reduce((found, {
|
|
2268
|
-
literal,
|
|
2269
|
-
val
|
|
2270
|
-
}) => literal ? found : found.concat(val), []),
|
|
2271
|
-
collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter(t => t));
|
|
2272
|
-
return stringifyTokens(tokens, tokenToString(collapsed));
|
|
2273
|
-
}
|
|
2274
|
-
}
|
|
2275
|
-
|
|
2276
|
-
class Invalid {
|
|
2277
|
-
constructor(reason, explanation) {
|
|
2278
|
-
this.reason = reason;
|
|
2279
|
-
this.explanation = explanation;
|
|
2280
|
-
}
|
|
2281
|
-
toMessage() {
|
|
2282
|
-
if (this.explanation) {
|
|
2283
|
-
return `${this.reason}: ${this.explanation}`;
|
|
2284
|
-
} else {
|
|
2285
|
-
return this.reason;
|
|
2286
|
-
}
|
|
2287
|
-
}
|
|
2288
|
-
}
|
|
2289
|
-
|
|
2290
1524
|
/**
|
|
2291
1525
|
* @interface
|
|
2292
1526
|
*/
|
|
@@ -2620,6 +1854,435 @@
|
|
|
2620
1854
|
}
|
|
2621
1855
|
}
|
|
2622
1856
|
|
|
1857
|
+
// todo - remap caching
|
|
1858
|
+
|
|
1859
|
+
let intlLFCache = {};
|
|
1860
|
+
function getCachedLF(locString, opts = {}) {
|
|
1861
|
+
const key = JSON.stringify([locString, opts]);
|
|
1862
|
+
let dtf = intlLFCache[key];
|
|
1863
|
+
if (!dtf) {
|
|
1864
|
+
dtf = new Intl.ListFormat(locString, opts);
|
|
1865
|
+
intlLFCache[key] = dtf;
|
|
1866
|
+
}
|
|
1867
|
+
return dtf;
|
|
1868
|
+
}
|
|
1869
|
+
let intlDTCache = {};
|
|
1870
|
+
function getCachedDTF(locString, opts = {}) {
|
|
1871
|
+
const key = JSON.stringify([locString, opts]);
|
|
1872
|
+
let dtf = intlDTCache[key];
|
|
1873
|
+
if (!dtf) {
|
|
1874
|
+
dtf = new Intl.DateTimeFormat(locString, opts);
|
|
1875
|
+
intlDTCache[key] = dtf;
|
|
1876
|
+
}
|
|
1877
|
+
return dtf;
|
|
1878
|
+
}
|
|
1879
|
+
let intlNumCache = {};
|
|
1880
|
+
function getCachedINF(locString, opts = {}) {
|
|
1881
|
+
const key = JSON.stringify([locString, opts]);
|
|
1882
|
+
let inf = intlNumCache[key];
|
|
1883
|
+
if (!inf) {
|
|
1884
|
+
inf = new Intl.NumberFormat(locString, opts);
|
|
1885
|
+
intlNumCache[key] = inf;
|
|
1886
|
+
}
|
|
1887
|
+
return inf;
|
|
1888
|
+
}
|
|
1889
|
+
let intlRelCache = {};
|
|
1890
|
+
function getCachedRTF(locString, opts = {}) {
|
|
1891
|
+
const {
|
|
1892
|
+
base,
|
|
1893
|
+
...cacheKeyOpts
|
|
1894
|
+
} = opts; // exclude `base` from the options
|
|
1895
|
+
const key = JSON.stringify([locString, cacheKeyOpts]);
|
|
1896
|
+
let inf = intlRelCache[key];
|
|
1897
|
+
if (!inf) {
|
|
1898
|
+
inf = new Intl.RelativeTimeFormat(locString, opts);
|
|
1899
|
+
intlRelCache[key] = inf;
|
|
1900
|
+
}
|
|
1901
|
+
return inf;
|
|
1902
|
+
}
|
|
1903
|
+
let sysLocaleCache = null;
|
|
1904
|
+
function systemLocale() {
|
|
1905
|
+
if (sysLocaleCache) {
|
|
1906
|
+
return sysLocaleCache;
|
|
1907
|
+
} else {
|
|
1908
|
+
sysLocaleCache = new Intl.DateTimeFormat().resolvedOptions().locale;
|
|
1909
|
+
return sysLocaleCache;
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
function parseLocaleString(localeStr) {
|
|
1913
|
+
// I really want to avoid writing a BCP 47 parser
|
|
1914
|
+
// see, e.g. https://github.com/wooorm/bcp-47
|
|
1915
|
+
// Instead, we'll do this:
|
|
1916
|
+
|
|
1917
|
+
// a) if the string has no -u extensions, just leave it alone
|
|
1918
|
+
// b) if it does, use Intl to resolve everything
|
|
1919
|
+
// c) if Intl fails, try again without the -u
|
|
1920
|
+
|
|
1921
|
+
// private subtags and unicode subtags have ordering requirements,
|
|
1922
|
+
// and we're not properly parsing this, so just strip out the
|
|
1923
|
+
// private ones if they exist.
|
|
1924
|
+
const xIndex = localeStr.indexOf("-x-");
|
|
1925
|
+
if (xIndex !== -1) {
|
|
1926
|
+
localeStr = localeStr.substring(0, xIndex);
|
|
1927
|
+
}
|
|
1928
|
+
const uIndex = localeStr.indexOf("-u-");
|
|
1929
|
+
if (uIndex === -1) {
|
|
1930
|
+
return [localeStr];
|
|
1931
|
+
} else {
|
|
1932
|
+
let options;
|
|
1933
|
+
let selectedStr;
|
|
1934
|
+
try {
|
|
1935
|
+
options = getCachedDTF(localeStr).resolvedOptions();
|
|
1936
|
+
selectedStr = localeStr;
|
|
1937
|
+
} catch (e) {
|
|
1938
|
+
const smaller = localeStr.substring(0, uIndex);
|
|
1939
|
+
options = getCachedDTF(smaller).resolvedOptions();
|
|
1940
|
+
selectedStr = smaller;
|
|
1941
|
+
}
|
|
1942
|
+
const {
|
|
1943
|
+
numberingSystem,
|
|
1944
|
+
calendar
|
|
1945
|
+
} = options;
|
|
1946
|
+
return [selectedStr, numberingSystem, calendar];
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
function intlConfigString(localeStr, numberingSystem, outputCalendar) {
|
|
1950
|
+
if (outputCalendar || numberingSystem) {
|
|
1951
|
+
if (!localeStr.includes("-u-")) {
|
|
1952
|
+
localeStr += "-u";
|
|
1953
|
+
}
|
|
1954
|
+
if (outputCalendar) {
|
|
1955
|
+
localeStr += `-ca-${outputCalendar}`;
|
|
1956
|
+
}
|
|
1957
|
+
if (numberingSystem) {
|
|
1958
|
+
localeStr += `-nu-${numberingSystem}`;
|
|
1959
|
+
}
|
|
1960
|
+
return localeStr;
|
|
1961
|
+
} else {
|
|
1962
|
+
return localeStr;
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
function mapMonths(f) {
|
|
1966
|
+
const ms = [];
|
|
1967
|
+
for (let i = 1; i <= 12; i++) {
|
|
1968
|
+
const dt = DateTime.utc(2016, i, 1);
|
|
1969
|
+
ms.push(f(dt));
|
|
1970
|
+
}
|
|
1971
|
+
return ms;
|
|
1972
|
+
}
|
|
1973
|
+
function mapWeekdays(f) {
|
|
1974
|
+
const ms = [];
|
|
1975
|
+
for (let i = 1; i <= 7; i++) {
|
|
1976
|
+
const dt = DateTime.utc(2016, 11, 13 + i);
|
|
1977
|
+
ms.push(f(dt));
|
|
1978
|
+
}
|
|
1979
|
+
return ms;
|
|
1980
|
+
}
|
|
1981
|
+
function listStuff(loc, length, defaultOK, englishFn, intlFn) {
|
|
1982
|
+
const mode = loc.listingMode(defaultOK);
|
|
1983
|
+
if (mode === "error") {
|
|
1984
|
+
return null;
|
|
1985
|
+
} else if (mode === "en") {
|
|
1986
|
+
return englishFn(length);
|
|
1987
|
+
} else {
|
|
1988
|
+
return intlFn(length);
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
function supportsFastNumbers(loc) {
|
|
1992
|
+
if (loc.numberingSystem && loc.numberingSystem !== "latn") {
|
|
1993
|
+
return false;
|
|
1994
|
+
} else {
|
|
1995
|
+
return loc.numberingSystem === "latn" || !loc.locale || loc.locale.startsWith("en") || new Intl.DateTimeFormat(loc.intl).resolvedOptions().numberingSystem === "latn";
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
/**
|
|
2000
|
+
* @private
|
|
2001
|
+
*/
|
|
2002
|
+
|
|
2003
|
+
class PolyNumberFormatter {
|
|
2004
|
+
constructor(intl, forceSimple, opts) {
|
|
2005
|
+
this.padTo = opts.padTo || 0;
|
|
2006
|
+
this.floor = opts.floor || false;
|
|
2007
|
+
const {
|
|
2008
|
+
padTo,
|
|
2009
|
+
floor,
|
|
2010
|
+
...otherOpts
|
|
2011
|
+
} = opts;
|
|
2012
|
+
if (!forceSimple || Object.keys(otherOpts).length > 0) {
|
|
2013
|
+
const intlOpts = {
|
|
2014
|
+
useGrouping: false,
|
|
2015
|
+
...opts
|
|
2016
|
+
};
|
|
2017
|
+
if (opts.padTo > 0) intlOpts.minimumIntegerDigits = opts.padTo;
|
|
2018
|
+
this.inf = getCachedINF(intl, intlOpts);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
format(i) {
|
|
2022
|
+
if (this.inf) {
|
|
2023
|
+
const fixed = this.floor ? Math.floor(i) : i;
|
|
2024
|
+
return this.inf.format(fixed);
|
|
2025
|
+
} else {
|
|
2026
|
+
// to match the browser's numberformatter defaults
|
|
2027
|
+
const fixed = this.floor ? Math.floor(i) : roundTo(i, 3);
|
|
2028
|
+
return padStart(fixed, this.padTo);
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
/**
|
|
2034
|
+
* @private
|
|
2035
|
+
*/
|
|
2036
|
+
|
|
2037
|
+
class PolyDateFormatter {
|
|
2038
|
+
constructor(dt, intl, opts) {
|
|
2039
|
+
this.opts = opts;
|
|
2040
|
+
let z = undefined;
|
|
2041
|
+
if (dt.zone.isUniversal) {
|
|
2042
|
+
// UTC-8 or Etc/UTC-8 are not part of tzdata, only Etc/GMT+8 and the like.
|
|
2043
|
+
// That is why fixed-offset TZ is set to that unless it is:
|
|
2044
|
+
// 1. Representing offset 0 when UTC is used to maintain previous behavior and does not become GMT.
|
|
2045
|
+
// 2. Unsupported by the browser:
|
|
2046
|
+
// - some do not support Etc/
|
|
2047
|
+
// - < Etc/GMT-14, > Etc/GMT+12, and 30-minute or 45-minute offsets are not part of tzdata
|
|
2048
|
+
const gmtOffset = -1 * (dt.offset / 60);
|
|
2049
|
+
const offsetZ = gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}`;
|
|
2050
|
+
if (dt.offset !== 0 && IANAZone.create(offsetZ).valid) {
|
|
2051
|
+
z = offsetZ;
|
|
2052
|
+
this.dt = dt;
|
|
2053
|
+
} else {
|
|
2054
|
+
// Not all fixed-offset zones like Etc/+4:30 are present in tzdata.
|
|
2055
|
+
// So we have to make do. Two cases:
|
|
2056
|
+
// 1. The format options tell us to show the zone. We can't do that, so the best
|
|
2057
|
+
// we can do is format the date in UTC.
|
|
2058
|
+
// 2. The format options don't tell us to show the zone. Then we can adjust them
|
|
2059
|
+
// the time and tell the formatter to show it to us in UTC, so that the time is right
|
|
2060
|
+
// and the bad zone doesn't show up.
|
|
2061
|
+
z = "UTC";
|
|
2062
|
+
if (opts.timeZoneName) {
|
|
2063
|
+
this.dt = dt;
|
|
2064
|
+
} else {
|
|
2065
|
+
this.dt = dt.offset === 0 ? dt : DateTime.fromMillis(dt.ts + dt.offset * 60 * 1000);
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
} else if (dt.zone.type === "system") {
|
|
2069
|
+
this.dt = dt;
|
|
2070
|
+
} else {
|
|
2071
|
+
this.dt = dt;
|
|
2072
|
+
z = dt.zone.name;
|
|
2073
|
+
}
|
|
2074
|
+
const intlOpts = {
|
|
2075
|
+
...this.opts
|
|
2076
|
+
};
|
|
2077
|
+
intlOpts.timeZone = intlOpts.timeZone || z;
|
|
2078
|
+
this.dtf = getCachedDTF(intl, intlOpts);
|
|
2079
|
+
}
|
|
2080
|
+
format() {
|
|
2081
|
+
return this.dtf.format(this.dt.toJSDate());
|
|
2082
|
+
}
|
|
2083
|
+
formatToParts() {
|
|
2084
|
+
return this.dtf.formatToParts(this.dt.toJSDate());
|
|
2085
|
+
}
|
|
2086
|
+
resolvedOptions() {
|
|
2087
|
+
return this.dtf.resolvedOptions();
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
/**
|
|
2092
|
+
* @private
|
|
2093
|
+
*/
|
|
2094
|
+
class PolyRelFormatter {
|
|
2095
|
+
constructor(intl, isEnglish, opts) {
|
|
2096
|
+
this.opts = {
|
|
2097
|
+
style: "long",
|
|
2098
|
+
...opts
|
|
2099
|
+
};
|
|
2100
|
+
if (!isEnglish && hasRelative()) {
|
|
2101
|
+
this.rtf = getCachedRTF(intl, opts);
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
format(count, unit) {
|
|
2105
|
+
if (this.rtf) {
|
|
2106
|
+
return this.rtf.format(count, unit);
|
|
2107
|
+
} else {
|
|
2108
|
+
return formatRelativeTime(unit, count, this.opts.numeric, this.opts.style !== "long");
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
formatToParts(count, unit) {
|
|
2112
|
+
if (this.rtf) {
|
|
2113
|
+
return this.rtf.formatToParts(count, unit);
|
|
2114
|
+
} else {
|
|
2115
|
+
return [];
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
/**
|
|
2121
|
+
* @private
|
|
2122
|
+
*/
|
|
2123
|
+
|
|
2124
|
+
class Locale {
|
|
2125
|
+
static fromOpts(opts) {
|
|
2126
|
+
return Locale.create(opts.locale, opts.numberingSystem, opts.outputCalendar, opts.defaultToEN);
|
|
2127
|
+
}
|
|
2128
|
+
static create(locale, numberingSystem, outputCalendar, defaultToEN = false) {
|
|
2129
|
+
const specifiedLocale = locale || Settings.defaultLocale;
|
|
2130
|
+
// the system locale is useful for human readable strings but annoying for parsing/formatting known formats
|
|
2131
|
+
const localeR = specifiedLocale || (defaultToEN ? "en-US" : systemLocale());
|
|
2132
|
+
const numberingSystemR = numberingSystem || Settings.defaultNumberingSystem;
|
|
2133
|
+
const outputCalendarR = outputCalendar || Settings.defaultOutputCalendar;
|
|
2134
|
+
return new Locale(localeR, numberingSystemR, outputCalendarR, specifiedLocale);
|
|
2135
|
+
}
|
|
2136
|
+
static resetCache() {
|
|
2137
|
+
sysLocaleCache = null;
|
|
2138
|
+
intlDTCache = {};
|
|
2139
|
+
intlNumCache = {};
|
|
2140
|
+
intlRelCache = {};
|
|
2141
|
+
}
|
|
2142
|
+
static fromObject({
|
|
2143
|
+
locale,
|
|
2144
|
+
numberingSystem,
|
|
2145
|
+
outputCalendar
|
|
2146
|
+
} = {}) {
|
|
2147
|
+
return Locale.create(locale, numberingSystem, outputCalendar);
|
|
2148
|
+
}
|
|
2149
|
+
constructor(locale, numbering, outputCalendar, specifiedLocale) {
|
|
2150
|
+
const [parsedLocale, parsedNumberingSystem, parsedOutputCalendar] = parseLocaleString(locale);
|
|
2151
|
+
this.locale = parsedLocale;
|
|
2152
|
+
this.numberingSystem = numbering || parsedNumberingSystem || null;
|
|
2153
|
+
this.outputCalendar = outputCalendar || parsedOutputCalendar || null;
|
|
2154
|
+
this.intl = intlConfigString(this.locale, this.numberingSystem, this.outputCalendar);
|
|
2155
|
+
this.weekdaysCache = {
|
|
2156
|
+
format: {},
|
|
2157
|
+
standalone: {}
|
|
2158
|
+
};
|
|
2159
|
+
this.monthsCache = {
|
|
2160
|
+
format: {},
|
|
2161
|
+
standalone: {}
|
|
2162
|
+
};
|
|
2163
|
+
this.meridiemCache = null;
|
|
2164
|
+
this.eraCache = {};
|
|
2165
|
+
this.specifiedLocale = specifiedLocale;
|
|
2166
|
+
this.fastNumbersCached = null;
|
|
2167
|
+
}
|
|
2168
|
+
get fastNumbers() {
|
|
2169
|
+
if (this.fastNumbersCached == null) {
|
|
2170
|
+
this.fastNumbersCached = supportsFastNumbers(this);
|
|
2171
|
+
}
|
|
2172
|
+
return this.fastNumbersCached;
|
|
2173
|
+
}
|
|
2174
|
+
listingMode() {
|
|
2175
|
+
const isActuallyEn = this.isEnglish();
|
|
2176
|
+
const hasNoWeirdness = (this.numberingSystem === null || this.numberingSystem === "latn") && (this.outputCalendar === null || this.outputCalendar === "gregory");
|
|
2177
|
+
return isActuallyEn && hasNoWeirdness ? "en" : "intl";
|
|
2178
|
+
}
|
|
2179
|
+
clone(alts) {
|
|
2180
|
+
if (!alts || Object.getOwnPropertyNames(alts).length === 0) {
|
|
2181
|
+
return this;
|
|
2182
|
+
} else {
|
|
2183
|
+
return Locale.create(alts.locale || this.specifiedLocale, alts.numberingSystem || this.numberingSystem, alts.outputCalendar || this.outputCalendar, alts.defaultToEN || false);
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
redefaultToEN(alts = {}) {
|
|
2187
|
+
return this.clone({
|
|
2188
|
+
...alts,
|
|
2189
|
+
defaultToEN: true
|
|
2190
|
+
});
|
|
2191
|
+
}
|
|
2192
|
+
redefaultToSystem(alts = {}) {
|
|
2193
|
+
return this.clone({
|
|
2194
|
+
...alts,
|
|
2195
|
+
defaultToEN: false
|
|
2196
|
+
});
|
|
2197
|
+
}
|
|
2198
|
+
months(length, format = false, defaultOK = true) {
|
|
2199
|
+
return listStuff(this, length, defaultOK, months, () => {
|
|
2200
|
+
const intl = format ? {
|
|
2201
|
+
month: length,
|
|
2202
|
+
day: "numeric"
|
|
2203
|
+
} : {
|
|
2204
|
+
month: length
|
|
2205
|
+
},
|
|
2206
|
+
formatStr = format ? "format" : "standalone";
|
|
2207
|
+
if (!this.monthsCache[formatStr][length]) {
|
|
2208
|
+
this.monthsCache[formatStr][length] = mapMonths(dt => this.extract(dt, intl, "month"));
|
|
2209
|
+
}
|
|
2210
|
+
return this.monthsCache[formatStr][length];
|
|
2211
|
+
});
|
|
2212
|
+
}
|
|
2213
|
+
weekdays(length, format = false, defaultOK = true) {
|
|
2214
|
+
return listStuff(this, length, defaultOK, weekdays, () => {
|
|
2215
|
+
const intl = format ? {
|
|
2216
|
+
weekday: length,
|
|
2217
|
+
year: "numeric",
|
|
2218
|
+
month: "long",
|
|
2219
|
+
day: "numeric"
|
|
2220
|
+
} : {
|
|
2221
|
+
weekday: length
|
|
2222
|
+
},
|
|
2223
|
+
formatStr = format ? "format" : "standalone";
|
|
2224
|
+
if (!this.weekdaysCache[formatStr][length]) {
|
|
2225
|
+
this.weekdaysCache[formatStr][length] = mapWeekdays(dt => this.extract(dt, intl, "weekday"));
|
|
2226
|
+
}
|
|
2227
|
+
return this.weekdaysCache[formatStr][length];
|
|
2228
|
+
});
|
|
2229
|
+
}
|
|
2230
|
+
meridiems(defaultOK = true) {
|
|
2231
|
+
return listStuff(this, undefined, defaultOK, () => meridiems, () => {
|
|
2232
|
+
// In theory there could be aribitrary day periods. We're gonna assume there are exactly two
|
|
2233
|
+
// for AM and PM. This is probably wrong, but it's makes parsing way easier.
|
|
2234
|
+
if (!this.meridiemCache) {
|
|
2235
|
+
const intl = {
|
|
2236
|
+
hour: "numeric",
|
|
2237
|
+
hourCycle: "h12"
|
|
2238
|
+
};
|
|
2239
|
+
this.meridiemCache = [DateTime.utc(2016, 11, 13, 9), DateTime.utc(2016, 11, 13, 19)].map(dt => this.extract(dt, intl, "dayperiod"));
|
|
2240
|
+
}
|
|
2241
|
+
return this.meridiemCache;
|
|
2242
|
+
});
|
|
2243
|
+
}
|
|
2244
|
+
eras(length, defaultOK = true) {
|
|
2245
|
+
return listStuff(this, length, defaultOK, eras, () => {
|
|
2246
|
+
const intl = {
|
|
2247
|
+
era: length
|
|
2248
|
+
};
|
|
2249
|
+
|
|
2250
|
+
// This is problematic. Different calendars are going to define eras totally differently. What I need is the minimum set of dates
|
|
2251
|
+
// to definitely enumerate them.
|
|
2252
|
+
if (!this.eraCache[length]) {
|
|
2253
|
+
this.eraCache[length] = [DateTime.utc(-40, 1, 1), DateTime.utc(2017, 1, 1)].map(dt => this.extract(dt, intl, "era"));
|
|
2254
|
+
}
|
|
2255
|
+
return this.eraCache[length];
|
|
2256
|
+
});
|
|
2257
|
+
}
|
|
2258
|
+
extract(dt, intlOpts, field) {
|
|
2259
|
+
const df = this.dtFormatter(dt, intlOpts),
|
|
2260
|
+
results = df.formatToParts(),
|
|
2261
|
+
matching = results.find(m => m.type.toLowerCase() === field);
|
|
2262
|
+
return matching ? matching.value : null;
|
|
2263
|
+
}
|
|
2264
|
+
numberFormatter(opts = {}) {
|
|
2265
|
+
// this forcesimple option is never used (the only caller short-circuits on it, but it seems safer to leave)
|
|
2266
|
+
// (in contrast, the rest of the condition is used heavily)
|
|
2267
|
+
return new PolyNumberFormatter(this.intl, opts.forceSimple || this.fastNumbers, opts);
|
|
2268
|
+
}
|
|
2269
|
+
dtFormatter(dt, intlOpts = {}) {
|
|
2270
|
+
return new PolyDateFormatter(dt, this.intl, intlOpts);
|
|
2271
|
+
}
|
|
2272
|
+
relFormatter(opts = {}) {
|
|
2273
|
+
return new PolyRelFormatter(this.intl, this.isEnglish(), opts);
|
|
2274
|
+
}
|
|
2275
|
+
listFormatter(opts = {}) {
|
|
2276
|
+
return getCachedLF(this.intl, opts);
|
|
2277
|
+
}
|
|
2278
|
+
isEnglish() {
|
|
2279
|
+
return this.locale === "en" || this.locale.toLowerCase() === "en-us" || new Intl.DateTimeFormat(this.intl).resolvedOptions().locale.startsWith("en-us");
|
|
2280
|
+
}
|
|
2281
|
+
equals(other) {
|
|
2282
|
+
return this.locale === other.locale && this.numberingSystem === other.numberingSystem && this.outputCalendar === other.outputCalendar;
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2623
2286
|
let singleton = null;
|
|
2624
2287
|
|
|
2625
2288
|
/**
|
|
@@ -2797,6 +2460,7 @@
|
|
|
2797
2460
|
defaultLocale = null,
|
|
2798
2461
|
defaultNumberingSystem = null,
|
|
2799
2462
|
defaultOutputCalendar = null,
|
|
2463
|
+
twoDigitCutoffYear = 60,
|
|
2800
2464
|
throwOnInvalid;
|
|
2801
2465
|
|
|
2802
2466
|
/**
|
|
@@ -2888,6 +2552,26 @@
|
|
|
2888
2552
|
defaultOutputCalendar = outputCalendar;
|
|
2889
2553
|
}
|
|
2890
2554
|
|
|
2555
|
+
/**
|
|
2556
|
+
* Get the cutoff year after which a string encoding a year as two digits is interpreted to occur in the current century.
|
|
2557
|
+
* @type {number}
|
|
2558
|
+
*/
|
|
2559
|
+
static get twoDigitCutoffYear() {
|
|
2560
|
+
return twoDigitCutoffYear;
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2563
|
+
/**
|
|
2564
|
+
* Set the cutoff year after which a string encoding a year as two digits is interpreted to occur in the current century.
|
|
2565
|
+
* @type {number}
|
|
2566
|
+
* @example Settings.twoDigitCutoffYear = 0 // cut-off year is 0, so all 'yy' are interpretted as current century
|
|
2567
|
+
* @example Settings.twoDigitCutoffYear = 50 // '49' -> 1949; '50' -> 2050
|
|
2568
|
+
* @example Settings.twoDigitCutoffYear = 1950 // interpretted as 50
|
|
2569
|
+
* @example Settings.twoDigitCutoffYear = 2050 // ALSO interpretted as 50
|
|
2570
|
+
*/
|
|
2571
|
+
static set twoDigitCutoffYear(cutoffYear) {
|
|
2572
|
+
twoDigitCutoffYear = cutoffYear % 100;
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2891
2575
|
/**
|
|
2892
2576
|
* Get whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals
|
|
2893
2577
|
* @type {boolean}
|
|
@@ -2896,441 +2580,793 @@
|
|
|
2896
2580
|
return throwOnInvalid;
|
|
2897
2581
|
}
|
|
2898
2582
|
|
|
2899
|
-
/**
|
|
2900
|
-
* Set whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals
|
|
2901
|
-
* @type {boolean}
|
|
2902
|
-
*/
|
|
2903
|
-
static set throwOnInvalid(t) {
|
|
2904
|
-
throwOnInvalid = t;
|
|
2905
|
-
}
|
|
2583
|
+
/**
|
|
2584
|
+
* Set whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals
|
|
2585
|
+
* @type {boolean}
|
|
2586
|
+
*/
|
|
2587
|
+
static set throwOnInvalid(t) {
|
|
2588
|
+
throwOnInvalid = t;
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
/**
|
|
2592
|
+
* Reset Luxon's global caches. Should only be necessary in testing scenarios.
|
|
2593
|
+
* @return {void}
|
|
2594
|
+
*/
|
|
2595
|
+
static resetCaches() {
|
|
2596
|
+
Locale.resetCache();
|
|
2597
|
+
IANAZone.resetCache();
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2601
|
+
/*
|
|
2602
|
+
This is just a junk drawer, containing anything used across multiple classes.
|
|
2603
|
+
Because Luxon is small(ish), this should stay small and we won't worry about splitting
|
|
2604
|
+
it up into, say, parsingUtil.js and basicUtil.js and so on. But they are divided up by feature area.
|
|
2605
|
+
*/
|
|
2606
|
+
|
|
2607
|
+
/**
|
|
2608
|
+
* @private
|
|
2609
|
+
*/
|
|
2610
|
+
|
|
2611
|
+
// TYPES
|
|
2612
|
+
|
|
2613
|
+
function isUndefined$1(o) {
|
|
2614
|
+
return typeof o === "undefined";
|
|
2615
|
+
}
|
|
2616
|
+
function isNumber$2(o) {
|
|
2617
|
+
return typeof o === "number";
|
|
2618
|
+
}
|
|
2619
|
+
function isInteger(o) {
|
|
2620
|
+
return typeof o === "number" && o % 1 === 0;
|
|
2621
|
+
}
|
|
2622
|
+
function isString$2(o) {
|
|
2623
|
+
return typeof o === "string";
|
|
2624
|
+
}
|
|
2625
|
+
function isDate(o) {
|
|
2626
|
+
return Object.prototype.toString.call(o) === "[object Date]";
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
// CAPABILITIES
|
|
2630
|
+
|
|
2631
|
+
function hasRelative() {
|
|
2632
|
+
try {
|
|
2633
|
+
return typeof Intl !== "undefined" && !!Intl.RelativeTimeFormat;
|
|
2634
|
+
} catch (e) {
|
|
2635
|
+
return false;
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
// OBJECTS AND ARRAYS
|
|
2640
|
+
|
|
2641
|
+
function maybeArray(thing) {
|
|
2642
|
+
return Array.isArray(thing) ? thing : [thing];
|
|
2643
|
+
}
|
|
2644
|
+
function bestBy(arr, by, compare) {
|
|
2645
|
+
if (arr.length === 0) {
|
|
2646
|
+
return undefined;
|
|
2647
|
+
}
|
|
2648
|
+
return arr.reduce((best, next) => {
|
|
2649
|
+
const pair = [by(next), next];
|
|
2650
|
+
if (!best) {
|
|
2651
|
+
return pair;
|
|
2652
|
+
} else if (compare(best[0], pair[0]) === best[0]) {
|
|
2653
|
+
return best;
|
|
2654
|
+
} else {
|
|
2655
|
+
return pair;
|
|
2656
|
+
}
|
|
2657
|
+
}, null)[1];
|
|
2658
|
+
}
|
|
2659
|
+
function pick(obj, keys) {
|
|
2660
|
+
return keys.reduce((a, k) => {
|
|
2661
|
+
a[k] = obj[k];
|
|
2662
|
+
return a;
|
|
2663
|
+
}, {});
|
|
2664
|
+
}
|
|
2665
|
+
function hasOwnProperty(obj, prop) {
|
|
2666
|
+
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2669
|
+
// NUMBERS AND STRINGS
|
|
2906
2670
|
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
* @return {void}
|
|
2910
|
-
*/
|
|
2911
|
-
static resetCaches() {
|
|
2912
|
-
Locale.resetCache();
|
|
2913
|
-
IANAZone.resetCache();
|
|
2914
|
-
}
|
|
2671
|
+
function integerBetween(thing, bottom, top) {
|
|
2672
|
+
return isInteger(thing) && thing >= bottom && thing <= top;
|
|
2915
2673
|
}
|
|
2916
2674
|
|
|
2917
|
-
//
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
function getCachedLF(locString, opts = {}) {
|
|
2921
|
-
const key = JSON.stringify([locString, opts]);
|
|
2922
|
-
let dtf = intlLFCache[key];
|
|
2923
|
-
if (!dtf) {
|
|
2924
|
-
dtf = new Intl.ListFormat(locString, opts);
|
|
2925
|
-
intlLFCache[key] = dtf;
|
|
2926
|
-
}
|
|
2927
|
-
return dtf;
|
|
2675
|
+
// x % n but takes the sign of n instead of x
|
|
2676
|
+
function floorMod(x, n) {
|
|
2677
|
+
return x - n * Math.floor(x / n);
|
|
2928
2678
|
}
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2679
|
+
function padStart(input, n = 2) {
|
|
2680
|
+
const isNeg = input < 0;
|
|
2681
|
+
let padded;
|
|
2682
|
+
if (isNeg) {
|
|
2683
|
+
padded = "-" + ("" + -input).padStart(n, "0");
|
|
2684
|
+
} else {
|
|
2685
|
+
padded = ("" + input).padStart(n, "0");
|
|
2936
2686
|
}
|
|
2937
|
-
return
|
|
2687
|
+
return padded;
|
|
2938
2688
|
}
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
inf = new Intl.NumberFormat(locString, opts);
|
|
2945
|
-
intlNumCache[key] = inf;
|
|
2689
|
+
function parseInteger(string) {
|
|
2690
|
+
if (isUndefined$1(string) || string === null || string === "") {
|
|
2691
|
+
return undefined;
|
|
2692
|
+
} else {
|
|
2693
|
+
return parseInt(string, 10);
|
|
2946
2694
|
}
|
|
2947
|
-
return inf;
|
|
2948
2695
|
}
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
} = opts; // exclude `base` from the options
|
|
2955
|
-
const key = JSON.stringify([locString, cacheKeyOpts]);
|
|
2956
|
-
let inf = intlRelCache[key];
|
|
2957
|
-
if (!inf) {
|
|
2958
|
-
inf = new Intl.RelativeTimeFormat(locString, opts);
|
|
2959
|
-
intlRelCache[key] = inf;
|
|
2696
|
+
function parseFloating(string) {
|
|
2697
|
+
if (isUndefined$1(string) || string === null || string === "") {
|
|
2698
|
+
return undefined;
|
|
2699
|
+
} else {
|
|
2700
|
+
return parseFloat(string);
|
|
2960
2701
|
}
|
|
2961
|
-
return inf;
|
|
2962
2702
|
}
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
if (
|
|
2966
|
-
return
|
|
2703
|
+
function parseMillis(fraction) {
|
|
2704
|
+
// Return undefined (instead of 0) in these cases, where fraction is not set
|
|
2705
|
+
if (isUndefined$1(fraction) || fraction === null || fraction === "") {
|
|
2706
|
+
return undefined;
|
|
2967
2707
|
} else {
|
|
2968
|
-
|
|
2969
|
-
return
|
|
2708
|
+
const f = parseFloat("0." + fraction) * 1000;
|
|
2709
|
+
return Math.floor(f);
|
|
2970
2710
|
}
|
|
2971
2711
|
}
|
|
2972
|
-
function
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2712
|
+
function roundTo(number, digits, towardZero = false) {
|
|
2713
|
+
const factor = 10 ** digits,
|
|
2714
|
+
rounder = towardZero ? Math.trunc : Math.round;
|
|
2715
|
+
return rounder(number * factor) / factor;
|
|
2716
|
+
}
|
|
2976
2717
|
|
|
2977
|
-
|
|
2978
|
-
// b) if it does, use Intl to resolve everything
|
|
2979
|
-
// c) if Intl fails, try again without the -u
|
|
2718
|
+
// DATE BASICS
|
|
2980
2719
|
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
return [localeStr];
|
|
2984
|
-
} else {
|
|
2985
|
-
let options;
|
|
2986
|
-
const smaller = localeStr.substring(0, uIndex);
|
|
2987
|
-
try {
|
|
2988
|
-
options = getCachedDTF(localeStr).resolvedOptions();
|
|
2989
|
-
} catch (e) {
|
|
2990
|
-
options = getCachedDTF(smaller).resolvedOptions();
|
|
2991
|
-
}
|
|
2992
|
-
const {
|
|
2993
|
-
numberingSystem,
|
|
2994
|
-
calendar
|
|
2995
|
-
} = options;
|
|
2996
|
-
// return the smaller one so that we can append the calendar and numbering overrides to it
|
|
2997
|
-
return [smaller, numberingSystem, calendar];
|
|
2998
|
-
}
|
|
2720
|
+
function isLeapYear(year) {
|
|
2721
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
2999
2722
|
}
|
|
3000
|
-
function
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
}
|
|
3009
|
-
return localeStr;
|
|
2723
|
+
function daysInYear(year) {
|
|
2724
|
+
return isLeapYear(year) ? 366 : 365;
|
|
2725
|
+
}
|
|
2726
|
+
function daysInMonth(year, month) {
|
|
2727
|
+
const modMonth = floorMod(month - 1, 12) + 1,
|
|
2728
|
+
modYear = year + (month - modMonth) / 12;
|
|
2729
|
+
if (modMonth === 2) {
|
|
2730
|
+
return isLeapYear(modYear) ? 29 : 28;
|
|
3010
2731
|
} else {
|
|
3011
|
-
return
|
|
2732
|
+
return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][modMonth - 1];
|
|
3012
2733
|
}
|
|
3013
2734
|
}
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
2735
|
+
|
|
2736
|
+
// covert a calendar object to a local timestamp (epoch, but with the offset baked in)
|
|
2737
|
+
function objToLocalTS(obj) {
|
|
2738
|
+
let d = Date.UTC(obj.year, obj.month - 1, obj.day, obj.hour, obj.minute, obj.second, obj.millisecond);
|
|
2739
|
+
|
|
2740
|
+
// for legacy reasons, years between 0 and 99 are interpreted as 19XX; revert that
|
|
2741
|
+
if (obj.year < 100 && obj.year >= 0) {
|
|
2742
|
+
d = new Date(d);
|
|
2743
|
+
d.setUTCFullYear(d.getUTCFullYear() - 1900);
|
|
3019
2744
|
}
|
|
3020
|
-
return
|
|
2745
|
+
return +d;
|
|
3021
2746
|
}
|
|
3022
|
-
function
|
|
3023
|
-
const
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
}
|
|
3028
|
-
return ms;
|
|
2747
|
+
function weeksInWeekYear(weekYear) {
|
|
2748
|
+
const p1 = (weekYear + Math.floor(weekYear / 4) - Math.floor(weekYear / 100) + Math.floor(weekYear / 400)) % 7,
|
|
2749
|
+
last = weekYear - 1,
|
|
2750
|
+
p2 = (last + Math.floor(last / 4) - Math.floor(last / 100) + Math.floor(last / 400)) % 7;
|
|
2751
|
+
return p1 === 4 || p2 === 3 ? 53 : 52;
|
|
3029
2752
|
}
|
|
3030
|
-
function
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
2753
|
+
function untruncateYear(year) {
|
|
2754
|
+
if (year > 99) {
|
|
2755
|
+
return year;
|
|
2756
|
+
} else return year > Settings.twoDigitCutoffYear ? 1900 + year : 2000 + year;
|
|
2757
|
+
}
|
|
2758
|
+
|
|
2759
|
+
// PARSING
|
|
2760
|
+
|
|
2761
|
+
function parseZoneInfo(ts, offsetFormat, locale, timeZone = null) {
|
|
2762
|
+
const date = new Date(ts),
|
|
2763
|
+
intlOpts = {
|
|
2764
|
+
hourCycle: "h23",
|
|
2765
|
+
year: "numeric",
|
|
2766
|
+
month: "2-digit",
|
|
2767
|
+
day: "2-digit",
|
|
2768
|
+
hour: "2-digit",
|
|
2769
|
+
minute: "2-digit"
|
|
2770
|
+
};
|
|
2771
|
+
if (timeZone) {
|
|
2772
|
+
intlOpts.timeZone = timeZone;
|
|
3038
2773
|
}
|
|
2774
|
+
const modified = {
|
|
2775
|
+
timeZoneName: offsetFormat,
|
|
2776
|
+
...intlOpts
|
|
2777
|
+
};
|
|
2778
|
+
const parsed = new Intl.DateTimeFormat(locale, modified).formatToParts(date).find(m => m.type.toLowerCase() === "timezonename");
|
|
2779
|
+
return parsed ? parsed.value : null;
|
|
3039
2780
|
}
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
2781
|
+
|
|
2782
|
+
// signedOffset('-5', '30') -> -330
|
|
2783
|
+
function signedOffset(offHourStr, offMinuteStr) {
|
|
2784
|
+
let offHour = parseInt(offHourStr, 10);
|
|
2785
|
+
|
|
2786
|
+
// don't || this because we want to preserve -0
|
|
2787
|
+
if (Number.isNaN(offHour)) {
|
|
2788
|
+
offHour = 0;
|
|
3045
2789
|
}
|
|
2790
|
+
const offMin = parseInt(offMinuteStr, 10) || 0,
|
|
2791
|
+
offMinSigned = offHour < 0 || Object.is(offHour, -0) ? -offMin : offMin;
|
|
2792
|
+
return offHour * 60 + offMinSigned;
|
|
3046
2793
|
}
|
|
3047
2794
|
|
|
3048
|
-
|
|
3049
|
-
* @private
|
|
3050
|
-
*/
|
|
2795
|
+
// COERCION
|
|
3051
2796
|
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
...opts
|
|
3065
|
-
};
|
|
3066
|
-
if (opts.padTo > 0) intlOpts.minimumIntegerDigits = opts.padTo;
|
|
3067
|
-
this.inf = getCachedINF(intl, intlOpts);
|
|
2797
|
+
function asNumber(value) {
|
|
2798
|
+
const numericValue = Number(value);
|
|
2799
|
+
if (typeof value === "boolean" || value === "" || Number.isNaN(numericValue)) throw new InvalidArgumentError(`Invalid unit value ${value}`);
|
|
2800
|
+
return numericValue;
|
|
2801
|
+
}
|
|
2802
|
+
function normalizeObject(obj, normalizer) {
|
|
2803
|
+
const normalized = {};
|
|
2804
|
+
for (const u in obj) {
|
|
2805
|
+
if (hasOwnProperty(obj, u)) {
|
|
2806
|
+
const v = obj[u];
|
|
2807
|
+
if (v === undefined || v === null) continue;
|
|
2808
|
+
normalized[normalizer(u)] = asNumber(v);
|
|
3068
2809
|
}
|
|
3069
2810
|
}
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
2811
|
+
return normalized;
|
|
2812
|
+
}
|
|
2813
|
+
function formatOffset(offset, format) {
|
|
2814
|
+
const hours = Math.trunc(Math.abs(offset / 60)),
|
|
2815
|
+
minutes = Math.trunc(Math.abs(offset % 60)),
|
|
2816
|
+
sign = offset >= 0 ? "+" : "-";
|
|
2817
|
+
switch (format) {
|
|
2818
|
+
case "short":
|
|
2819
|
+
return `${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}`;
|
|
2820
|
+
case "narrow":
|
|
2821
|
+
return `${sign}${hours}${minutes > 0 ? `:${minutes}` : ""}`;
|
|
2822
|
+
case "techie":
|
|
2823
|
+
return `${sign}${padStart(hours, 2)}${padStart(minutes, 2)}`;
|
|
2824
|
+
default:
|
|
2825
|
+
throw new RangeError(`Value format ${format} is out of range for property format`);
|
|
3079
2826
|
}
|
|
3080
2827
|
}
|
|
2828
|
+
function timeObject(obj) {
|
|
2829
|
+
return pick(obj, ["hour", "minute", "second", "millisecond"]);
|
|
2830
|
+
}
|
|
3081
2831
|
|
|
3082
2832
|
/**
|
|
3083
2833
|
* @private
|
|
3084
2834
|
*/
|
|
3085
2835
|
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
// Not all fixed-offset zones like Etc/+4:30 are present in tzdata.
|
|
3104
|
-
// So we have to make do. Two cases:
|
|
3105
|
-
// 1. The format options tell us to show the zone. We can't do that, so the best
|
|
3106
|
-
// we can do is format the date in UTC.
|
|
3107
|
-
// 2. The format options don't tell us to show the zone. Then we can adjust them
|
|
3108
|
-
// the time and tell the formatter to show it to us in UTC, so that the time is right
|
|
3109
|
-
// and the bad zone doesn't show up.
|
|
3110
|
-
z = "UTC";
|
|
3111
|
-
if (opts.timeZoneName) {
|
|
3112
|
-
this.dt = dt;
|
|
3113
|
-
} else {
|
|
3114
|
-
this.dt = dt.offset === 0 ? dt : DateTime.fromMillis(dt.ts + dt.offset * 60 * 1000);
|
|
3115
|
-
}
|
|
3116
|
-
}
|
|
3117
|
-
} else if (dt.zone.type === "system") {
|
|
3118
|
-
this.dt = dt;
|
|
3119
|
-
} else {
|
|
3120
|
-
this.dt = dt;
|
|
3121
|
-
z = dt.zone.name;
|
|
3122
|
-
}
|
|
3123
|
-
const intlOpts = {
|
|
3124
|
-
...this.opts
|
|
3125
|
-
};
|
|
3126
|
-
if (z) {
|
|
3127
|
-
intlOpts.timeZone = z;
|
|
3128
|
-
}
|
|
3129
|
-
this.dtf = getCachedDTF(intl, intlOpts);
|
|
3130
|
-
}
|
|
3131
|
-
format() {
|
|
3132
|
-
return this.dtf.format(this.dt.toJSDate());
|
|
3133
|
-
}
|
|
3134
|
-
formatToParts() {
|
|
3135
|
-
return this.dtf.formatToParts(this.dt.toJSDate());
|
|
2836
|
+
const monthsLong = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
2837
|
+
const monthsShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
2838
|
+
const monthsNarrow = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"];
|
|
2839
|
+
function months(length) {
|
|
2840
|
+
switch (length) {
|
|
2841
|
+
case "narrow":
|
|
2842
|
+
return [...monthsNarrow];
|
|
2843
|
+
case "short":
|
|
2844
|
+
return [...monthsShort];
|
|
2845
|
+
case "long":
|
|
2846
|
+
return [...monthsLong];
|
|
2847
|
+
case "numeric":
|
|
2848
|
+
return ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
|
|
2849
|
+
case "2-digit":
|
|
2850
|
+
return ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
|
|
2851
|
+
default:
|
|
2852
|
+
return null;
|
|
3136
2853
|
}
|
|
3137
|
-
|
|
3138
|
-
|
|
2854
|
+
}
|
|
2855
|
+
const weekdaysLong = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
|
2856
|
+
const weekdaysShort = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
2857
|
+
const weekdaysNarrow = ["M", "T", "W", "T", "F", "S", "S"];
|
|
2858
|
+
function weekdays(length) {
|
|
2859
|
+
switch (length) {
|
|
2860
|
+
case "narrow":
|
|
2861
|
+
return [...weekdaysNarrow];
|
|
2862
|
+
case "short":
|
|
2863
|
+
return [...weekdaysShort];
|
|
2864
|
+
case "long":
|
|
2865
|
+
return [...weekdaysLong];
|
|
2866
|
+
case "numeric":
|
|
2867
|
+
return ["1", "2", "3", "4", "5", "6", "7"];
|
|
2868
|
+
default:
|
|
2869
|
+
return null;
|
|
3139
2870
|
}
|
|
3140
2871
|
}
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
2872
|
+
const meridiems = ["AM", "PM"];
|
|
2873
|
+
const erasLong = ["Before Christ", "Anno Domini"];
|
|
2874
|
+
const erasShort = ["BC", "AD"];
|
|
2875
|
+
const erasNarrow = ["B", "A"];
|
|
2876
|
+
function eras(length) {
|
|
2877
|
+
switch (length) {
|
|
2878
|
+
case "narrow":
|
|
2879
|
+
return [...erasNarrow];
|
|
2880
|
+
case "short":
|
|
2881
|
+
return [...erasShort];
|
|
2882
|
+
case "long":
|
|
2883
|
+
return [...erasLong];
|
|
2884
|
+
default:
|
|
2885
|
+
return null;
|
|
3154
2886
|
}
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
2887
|
+
}
|
|
2888
|
+
function meridiemForDateTime(dt) {
|
|
2889
|
+
return meridiems[dt.hour < 12 ? 0 : 1];
|
|
2890
|
+
}
|
|
2891
|
+
function weekdayForDateTime(dt, length) {
|
|
2892
|
+
return weekdays(length)[dt.weekday - 1];
|
|
2893
|
+
}
|
|
2894
|
+
function monthForDateTime(dt, length) {
|
|
2895
|
+
return months(length)[dt.month - 1];
|
|
2896
|
+
}
|
|
2897
|
+
function eraForDateTime(dt, length) {
|
|
2898
|
+
return eras(length)[dt.year < 0 ? 0 : 1];
|
|
2899
|
+
}
|
|
2900
|
+
function formatRelativeTime(unit, count, numeric = "always", narrow = false) {
|
|
2901
|
+
const units = {
|
|
2902
|
+
years: ["year", "yr."],
|
|
2903
|
+
quarters: ["quarter", "qtr."],
|
|
2904
|
+
months: ["month", "mo."],
|
|
2905
|
+
weeks: ["week", "wk."],
|
|
2906
|
+
days: ["day", "day", "days"],
|
|
2907
|
+
hours: ["hour", "hr."],
|
|
2908
|
+
minutes: ["minute", "min."],
|
|
2909
|
+
seconds: ["second", "sec."]
|
|
2910
|
+
};
|
|
2911
|
+
const lastable = ["hours", "minutes", "seconds"].indexOf(unit) === -1;
|
|
2912
|
+
if (numeric === "auto" && lastable) {
|
|
2913
|
+
const isDay = unit === "days";
|
|
2914
|
+
switch (count) {
|
|
2915
|
+
case 1:
|
|
2916
|
+
return isDay ? "tomorrow" : `next ${units[unit][0]}`;
|
|
2917
|
+
case -1:
|
|
2918
|
+
return isDay ? "yesterday" : `last ${units[unit][0]}`;
|
|
2919
|
+
case 0:
|
|
2920
|
+
return isDay ? "today" : `this ${units[unit][0]}`;
|
|
3160
2921
|
}
|
|
3161
2922
|
}
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
2923
|
+
|
|
2924
|
+
const isInPast = Object.is(count, -0) || count < 0,
|
|
2925
|
+
fmtValue = Math.abs(count),
|
|
2926
|
+
singular = fmtValue === 1,
|
|
2927
|
+
lilUnits = units[unit],
|
|
2928
|
+
fmtUnit = narrow ? singular ? lilUnits[1] : lilUnits[2] || lilUnits[1] : singular ? units[unit][0] : unit;
|
|
2929
|
+
return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}`;
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2932
|
+
function stringifyTokens(splits, tokenToString) {
|
|
2933
|
+
let s = "";
|
|
2934
|
+
for (const token of splits) {
|
|
2935
|
+
if (token.literal) {
|
|
2936
|
+
s += token.val;
|
|
3165
2937
|
} else {
|
|
3166
|
-
|
|
2938
|
+
s += tokenToString(token.val);
|
|
3167
2939
|
}
|
|
3168
2940
|
}
|
|
2941
|
+
return s;
|
|
3169
2942
|
}
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
constructor(locale, numbering, outputCalendar, specifiedLocale) {
|
|
3201
|
-
const [parsedLocale, parsedNumberingSystem, parsedOutputCalendar] = parseLocaleString(locale);
|
|
3202
|
-
this.locale = parsedLocale;
|
|
3203
|
-
this.numberingSystem = numbering || parsedNumberingSystem || null;
|
|
3204
|
-
this.outputCalendar = outputCalendar || parsedOutputCalendar || null;
|
|
3205
|
-
this.intl = intlConfigString(this.locale, this.numberingSystem, this.outputCalendar);
|
|
3206
|
-
this.weekdaysCache = {
|
|
3207
|
-
format: {},
|
|
3208
|
-
standalone: {}
|
|
3209
|
-
};
|
|
3210
|
-
this.monthsCache = {
|
|
3211
|
-
format: {},
|
|
3212
|
-
standalone: {}
|
|
3213
|
-
};
|
|
3214
|
-
this.meridiemCache = null;
|
|
3215
|
-
this.eraCache = {};
|
|
3216
|
-
this.specifiedLocale = specifiedLocale;
|
|
3217
|
-
this.fastNumbersCached = null;
|
|
2943
|
+
const macroTokenToFormatOpts = {
|
|
2944
|
+
D: DATE_SHORT,
|
|
2945
|
+
DD: DATE_MED,
|
|
2946
|
+
DDD: DATE_FULL,
|
|
2947
|
+
DDDD: DATE_HUGE,
|
|
2948
|
+
t: TIME_SIMPLE,
|
|
2949
|
+
tt: TIME_WITH_SECONDS,
|
|
2950
|
+
ttt: TIME_WITH_SHORT_OFFSET,
|
|
2951
|
+
tttt: TIME_WITH_LONG_OFFSET,
|
|
2952
|
+
T: TIME_24_SIMPLE,
|
|
2953
|
+
TT: TIME_24_WITH_SECONDS,
|
|
2954
|
+
TTT: TIME_24_WITH_SHORT_OFFSET,
|
|
2955
|
+
TTTT: TIME_24_WITH_LONG_OFFSET,
|
|
2956
|
+
f: DATETIME_SHORT,
|
|
2957
|
+
ff: DATETIME_MED,
|
|
2958
|
+
fff: DATETIME_FULL,
|
|
2959
|
+
ffff: DATETIME_HUGE,
|
|
2960
|
+
F: DATETIME_SHORT_WITH_SECONDS,
|
|
2961
|
+
FF: DATETIME_MED_WITH_SECONDS,
|
|
2962
|
+
FFF: DATETIME_FULL_WITH_SECONDS,
|
|
2963
|
+
FFFF: DATETIME_HUGE_WITH_SECONDS
|
|
2964
|
+
};
|
|
2965
|
+
|
|
2966
|
+
/**
|
|
2967
|
+
* @private
|
|
2968
|
+
*/
|
|
2969
|
+
|
|
2970
|
+
class Formatter {
|
|
2971
|
+
static create(locale, opts = {}) {
|
|
2972
|
+
return new Formatter(locale, opts);
|
|
3218
2973
|
}
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
2974
|
+
static parseFormat(fmt) {
|
|
2975
|
+
let current = null,
|
|
2976
|
+
currentFull = "",
|
|
2977
|
+
bracketed = false;
|
|
2978
|
+
const splits = [];
|
|
2979
|
+
for (let i = 0; i < fmt.length; i++) {
|
|
2980
|
+
const c = fmt.charAt(i);
|
|
2981
|
+
if (c === "'") {
|
|
2982
|
+
if (currentFull.length > 0) {
|
|
2983
|
+
splits.push({
|
|
2984
|
+
literal: bracketed,
|
|
2985
|
+
val: currentFull
|
|
2986
|
+
});
|
|
2987
|
+
}
|
|
2988
|
+
current = null;
|
|
2989
|
+
currentFull = "";
|
|
2990
|
+
bracketed = !bracketed;
|
|
2991
|
+
} else if (bracketed) {
|
|
2992
|
+
currentFull += c;
|
|
2993
|
+
} else if (c === current) {
|
|
2994
|
+
currentFull += c;
|
|
2995
|
+
} else {
|
|
2996
|
+
if (currentFull.length > 0) {
|
|
2997
|
+
splits.push({
|
|
2998
|
+
literal: false,
|
|
2999
|
+
val: currentFull
|
|
3000
|
+
});
|
|
3001
|
+
}
|
|
3002
|
+
currentFull = c;
|
|
3003
|
+
current = c;
|
|
3004
|
+
}
|
|
3222
3005
|
}
|
|
3223
|
-
|
|
3006
|
+
if (currentFull.length > 0) {
|
|
3007
|
+
splits.push({
|
|
3008
|
+
literal: bracketed,
|
|
3009
|
+
val: currentFull
|
|
3010
|
+
});
|
|
3011
|
+
}
|
|
3012
|
+
return splits;
|
|
3224
3013
|
}
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
const hasNoWeirdness = (this.numberingSystem === null || this.numberingSystem === "latn") && (this.outputCalendar === null || this.outputCalendar === "gregory");
|
|
3228
|
-
return isActuallyEn && hasNoWeirdness ? "en" : "intl";
|
|
3014
|
+
static macroTokenToFormatOpts(token) {
|
|
3015
|
+
return macroTokenToFormatOpts[token];
|
|
3229
3016
|
}
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
return Locale.create(alts.locale || this.specifiedLocale, alts.numberingSystem || this.numberingSystem, alts.outputCalendar || this.outputCalendar, alts.defaultToEN || false);
|
|
3235
|
-
}
|
|
3017
|
+
constructor(locale, formatOpts) {
|
|
3018
|
+
this.opts = formatOpts;
|
|
3019
|
+
this.loc = locale;
|
|
3020
|
+
this.systemLoc = null;
|
|
3236
3021
|
}
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3022
|
+
formatWithSystemDefault(dt, opts) {
|
|
3023
|
+
if (this.systemLoc === null) {
|
|
3024
|
+
this.systemLoc = this.loc.redefaultToSystem();
|
|
3025
|
+
}
|
|
3026
|
+
const df = this.systemLoc.dtFormatter(dt, {
|
|
3027
|
+
...this.opts,
|
|
3028
|
+
...opts
|
|
3241
3029
|
});
|
|
3030
|
+
return df.format();
|
|
3242
3031
|
}
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
...
|
|
3246
|
-
|
|
3032
|
+
formatDateTime(dt, opts = {}) {
|
|
3033
|
+
const df = this.loc.dtFormatter(dt, {
|
|
3034
|
+
...this.opts,
|
|
3035
|
+
...opts
|
|
3247
3036
|
});
|
|
3037
|
+
return df.format();
|
|
3248
3038
|
}
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
day: "numeric"
|
|
3254
|
-
} : {
|
|
3255
|
-
month: length
|
|
3256
|
-
},
|
|
3257
|
-
formatStr = format ? "format" : "standalone";
|
|
3258
|
-
if (!this.monthsCache[formatStr][length]) {
|
|
3259
|
-
this.monthsCache[formatStr][length] = mapMonths(dt => this.extract(dt, intl, "month"));
|
|
3260
|
-
}
|
|
3261
|
-
return this.monthsCache[formatStr][length];
|
|
3039
|
+
formatDateTimeParts(dt, opts = {}) {
|
|
3040
|
+
const df = this.loc.dtFormatter(dt, {
|
|
3041
|
+
...this.opts,
|
|
3042
|
+
...opts
|
|
3262
3043
|
});
|
|
3044
|
+
return df.formatToParts();
|
|
3263
3045
|
}
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
year: "numeric",
|
|
3269
|
-
month: "long",
|
|
3270
|
-
day: "numeric"
|
|
3271
|
-
} : {
|
|
3272
|
-
weekday: length
|
|
3273
|
-
},
|
|
3274
|
-
formatStr = format ? "format" : "standalone";
|
|
3275
|
-
if (!this.weekdaysCache[formatStr][length]) {
|
|
3276
|
-
this.weekdaysCache[formatStr][length] = mapWeekdays(dt => this.extract(dt, intl, "weekday"));
|
|
3277
|
-
}
|
|
3278
|
-
return this.weekdaysCache[formatStr][length];
|
|
3046
|
+
formatInterval(interval, opts = {}) {
|
|
3047
|
+
const df = this.loc.dtFormatter(interval.start, {
|
|
3048
|
+
...this.opts,
|
|
3049
|
+
...opts
|
|
3279
3050
|
});
|
|
3051
|
+
return df.dtf.formatRange(interval.start.toJSDate(), interval.end.toJSDate());
|
|
3280
3052
|
}
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
if (!this.meridiemCache) {
|
|
3286
|
-
const intl = {
|
|
3287
|
-
hour: "numeric",
|
|
3288
|
-
hourCycle: "h12"
|
|
3289
|
-
};
|
|
3290
|
-
this.meridiemCache = [DateTime.utc(2016, 11, 13, 9), DateTime.utc(2016, 11, 13, 19)].map(dt => this.extract(dt, intl, "dayperiod"));
|
|
3291
|
-
}
|
|
3292
|
-
return this.meridiemCache;
|
|
3053
|
+
resolvedOptions(dt, opts = {}) {
|
|
3054
|
+
const df = this.loc.dtFormatter(dt, {
|
|
3055
|
+
...this.opts,
|
|
3056
|
+
...opts
|
|
3293
3057
|
});
|
|
3058
|
+
return df.resolvedOptions();
|
|
3294
3059
|
}
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3060
|
+
num(n, p = 0) {
|
|
3061
|
+
// we get some perf out of doing this here, annoyingly
|
|
3062
|
+
if (this.opts.forceSimple) {
|
|
3063
|
+
return padStart(n, p);
|
|
3064
|
+
}
|
|
3065
|
+
const opts = {
|
|
3066
|
+
...this.opts
|
|
3067
|
+
};
|
|
3068
|
+
if (p > 0) {
|
|
3069
|
+
opts.padTo = p;
|
|
3070
|
+
}
|
|
3071
|
+
return this.loc.numberFormatter(opts).format(n);
|
|
3072
|
+
}
|
|
3073
|
+
formatDateTimeFromString(dt, fmt) {
|
|
3074
|
+
const knownEnglish = this.loc.listingMode() === "en",
|
|
3075
|
+
useDateTimeFormatter = this.loc.outputCalendar && this.loc.outputCalendar !== "gregory",
|
|
3076
|
+
string = (opts, extract) => this.loc.extract(dt, opts, extract),
|
|
3077
|
+
formatOffset = opts => {
|
|
3078
|
+
if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) {
|
|
3079
|
+
return "Z";
|
|
3080
|
+
}
|
|
3081
|
+
return dt.isValid ? dt.zone.formatOffset(dt.ts, opts.format) : "";
|
|
3082
|
+
},
|
|
3083
|
+
meridiem = () => knownEnglish ? meridiemForDateTime(dt) : string({
|
|
3084
|
+
hour: "numeric",
|
|
3085
|
+
hourCycle: "h12"
|
|
3086
|
+
}, "dayperiod"),
|
|
3087
|
+
month = (length, standalone) => knownEnglish ? monthForDateTime(dt, length) : string(standalone ? {
|
|
3088
|
+
month: length
|
|
3089
|
+
} : {
|
|
3090
|
+
month: length,
|
|
3091
|
+
day: "numeric"
|
|
3092
|
+
}, "month"),
|
|
3093
|
+
weekday = (length, standalone) => knownEnglish ? weekdayForDateTime(dt, length) : string(standalone ? {
|
|
3094
|
+
weekday: length
|
|
3095
|
+
} : {
|
|
3096
|
+
weekday: length,
|
|
3097
|
+
month: "long",
|
|
3098
|
+
day: "numeric"
|
|
3099
|
+
}, "weekday"),
|
|
3100
|
+
maybeMacro = token => {
|
|
3101
|
+
const formatOpts = Formatter.macroTokenToFormatOpts(token);
|
|
3102
|
+
if (formatOpts) {
|
|
3103
|
+
return this.formatWithSystemDefault(dt, formatOpts);
|
|
3104
|
+
} else {
|
|
3105
|
+
return token;
|
|
3106
|
+
}
|
|
3107
|
+
},
|
|
3108
|
+
era = length => knownEnglish ? eraForDateTime(dt, length) : string({
|
|
3298
3109
|
era: length
|
|
3110
|
+
}, "era"),
|
|
3111
|
+
tokenToString = token => {
|
|
3112
|
+
// Where possible: http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles
|
|
3113
|
+
switch (token) {
|
|
3114
|
+
// ms
|
|
3115
|
+
case "S":
|
|
3116
|
+
return this.num(dt.millisecond);
|
|
3117
|
+
case "u":
|
|
3118
|
+
// falls through
|
|
3119
|
+
case "SSS":
|
|
3120
|
+
return this.num(dt.millisecond, 3);
|
|
3121
|
+
// seconds
|
|
3122
|
+
case "s":
|
|
3123
|
+
return this.num(dt.second);
|
|
3124
|
+
case "ss":
|
|
3125
|
+
return this.num(dt.second, 2);
|
|
3126
|
+
// fractional seconds
|
|
3127
|
+
case "uu":
|
|
3128
|
+
return this.num(Math.floor(dt.millisecond / 10), 2);
|
|
3129
|
+
case "uuu":
|
|
3130
|
+
return this.num(Math.floor(dt.millisecond / 100));
|
|
3131
|
+
// minutes
|
|
3132
|
+
case "m":
|
|
3133
|
+
return this.num(dt.minute);
|
|
3134
|
+
case "mm":
|
|
3135
|
+
return this.num(dt.minute, 2);
|
|
3136
|
+
// hours
|
|
3137
|
+
case "h":
|
|
3138
|
+
return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12);
|
|
3139
|
+
case "hh":
|
|
3140
|
+
return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12, 2);
|
|
3141
|
+
case "H":
|
|
3142
|
+
return this.num(dt.hour);
|
|
3143
|
+
case "HH":
|
|
3144
|
+
return this.num(dt.hour, 2);
|
|
3145
|
+
// offset
|
|
3146
|
+
case "Z":
|
|
3147
|
+
// like +6
|
|
3148
|
+
return formatOffset({
|
|
3149
|
+
format: "narrow",
|
|
3150
|
+
allowZ: this.opts.allowZ
|
|
3151
|
+
});
|
|
3152
|
+
case "ZZ":
|
|
3153
|
+
// like +06:00
|
|
3154
|
+
return formatOffset({
|
|
3155
|
+
format: "short",
|
|
3156
|
+
allowZ: this.opts.allowZ
|
|
3157
|
+
});
|
|
3158
|
+
case "ZZZ":
|
|
3159
|
+
// like +0600
|
|
3160
|
+
return formatOffset({
|
|
3161
|
+
format: "techie",
|
|
3162
|
+
allowZ: this.opts.allowZ
|
|
3163
|
+
});
|
|
3164
|
+
case "ZZZZ":
|
|
3165
|
+
// like EST
|
|
3166
|
+
return dt.zone.offsetName(dt.ts, {
|
|
3167
|
+
format: "short",
|
|
3168
|
+
locale: this.loc.locale
|
|
3169
|
+
});
|
|
3170
|
+
case "ZZZZZ":
|
|
3171
|
+
// like Eastern Standard Time
|
|
3172
|
+
return dt.zone.offsetName(dt.ts, {
|
|
3173
|
+
format: "long",
|
|
3174
|
+
locale: this.loc.locale
|
|
3175
|
+
});
|
|
3176
|
+
// zone
|
|
3177
|
+
case "z":
|
|
3178
|
+
// like America/New_York
|
|
3179
|
+
return dt.zoneName;
|
|
3180
|
+
// meridiems
|
|
3181
|
+
case "a":
|
|
3182
|
+
return meridiem();
|
|
3183
|
+
// dates
|
|
3184
|
+
case "d":
|
|
3185
|
+
return useDateTimeFormatter ? string({
|
|
3186
|
+
day: "numeric"
|
|
3187
|
+
}, "day") : this.num(dt.day);
|
|
3188
|
+
case "dd":
|
|
3189
|
+
return useDateTimeFormatter ? string({
|
|
3190
|
+
day: "2-digit"
|
|
3191
|
+
}, "day") : this.num(dt.day, 2);
|
|
3192
|
+
// weekdays - standalone
|
|
3193
|
+
case "c":
|
|
3194
|
+
// like 1
|
|
3195
|
+
return this.num(dt.weekday);
|
|
3196
|
+
case "ccc":
|
|
3197
|
+
// like 'Tues'
|
|
3198
|
+
return weekday("short", true);
|
|
3199
|
+
case "cccc":
|
|
3200
|
+
// like 'Tuesday'
|
|
3201
|
+
return weekday("long", true);
|
|
3202
|
+
case "ccccc":
|
|
3203
|
+
// like 'T'
|
|
3204
|
+
return weekday("narrow", true);
|
|
3205
|
+
// weekdays - format
|
|
3206
|
+
case "E":
|
|
3207
|
+
// like 1
|
|
3208
|
+
return this.num(dt.weekday);
|
|
3209
|
+
case "EEE":
|
|
3210
|
+
// like 'Tues'
|
|
3211
|
+
return weekday("short", false);
|
|
3212
|
+
case "EEEE":
|
|
3213
|
+
// like 'Tuesday'
|
|
3214
|
+
return weekday("long", false);
|
|
3215
|
+
case "EEEEE":
|
|
3216
|
+
// like 'T'
|
|
3217
|
+
return weekday("narrow", false);
|
|
3218
|
+
// months - standalone
|
|
3219
|
+
case "L":
|
|
3220
|
+
// like 1
|
|
3221
|
+
return useDateTimeFormatter ? string({
|
|
3222
|
+
month: "numeric",
|
|
3223
|
+
day: "numeric"
|
|
3224
|
+
}, "month") : this.num(dt.month);
|
|
3225
|
+
case "LL":
|
|
3226
|
+
// like 01, doesn't seem to work
|
|
3227
|
+
return useDateTimeFormatter ? string({
|
|
3228
|
+
month: "2-digit",
|
|
3229
|
+
day: "numeric"
|
|
3230
|
+
}, "month") : this.num(dt.month, 2);
|
|
3231
|
+
case "LLL":
|
|
3232
|
+
// like Jan
|
|
3233
|
+
return month("short", true);
|
|
3234
|
+
case "LLLL":
|
|
3235
|
+
// like January
|
|
3236
|
+
return month("long", true);
|
|
3237
|
+
case "LLLLL":
|
|
3238
|
+
// like J
|
|
3239
|
+
return month("narrow", true);
|
|
3240
|
+
// months - format
|
|
3241
|
+
case "M":
|
|
3242
|
+
// like 1
|
|
3243
|
+
return useDateTimeFormatter ? string({
|
|
3244
|
+
month: "numeric"
|
|
3245
|
+
}, "month") : this.num(dt.month);
|
|
3246
|
+
case "MM":
|
|
3247
|
+
// like 01
|
|
3248
|
+
return useDateTimeFormatter ? string({
|
|
3249
|
+
month: "2-digit"
|
|
3250
|
+
}, "month") : this.num(dt.month, 2);
|
|
3251
|
+
case "MMM":
|
|
3252
|
+
// like Jan
|
|
3253
|
+
return month("short", false);
|
|
3254
|
+
case "MMMM":
|
|
3255
|
+
// like January
|
|
3256
|
+
return month("long", false);
|
|
3257
|
+
case "MMMMM":
|
|
3258
|
+
// like J
|
|
3259
|
+
return month("narrow", false);
|
|
3260
|
+
// years
|
|
3261
|
+
case "y":
|
|
3262
|
+
// like 2014
|
|
3263
|
+
return useDateTimeFormatter ? string({
|
|
3264
|
+
year: "numeric"
|
|
3265
|
+
}, "year") : this.num(dt.year);
|
|
3266
|
+
case "yy":
|
|
3267
|
+
// like 14
|
|
3268
|
+
return useDateTimeFormatter ? string({
|
|
3269
|
+
year: "2-digit"
|
|
3270
|
+
}, "year") : this.num(dt.year.toString().slice(-2), 2);
|
|
3271
|
+
case "yyyy":
|
|
3272
|
+
// like 0012
|
|
3273
|
+
return useDateTimeFormatter ? string({
|
|
3274
|
+
year: "numeric"
|
|
3275
|
+
}, "year") : this.num(dt.year, 4);
|
|
3276
|
+
case "yyyyyy":
|
|
3277
|
+
// like 000012
|
|
3278
|
+
return useDateTimeFormatter ? string({
|
|
3279
|
+
year: "numeric"
|
|
3280
|
+
}, "year") : this.num(dt.year, 6);
|
|
3281
|
+
// eras
|
|
3282
|
+
case "G":
|
|
3283
|
+
// like AD
|
|
3284
|
+
return era("short");
|
|
3285
|
+
case "GG":
|
|
3286
|
+
// like Anno Domini
|
|
3287
|
+
return era("long");
|
|
3288
|
+
case "GGGGG":
|
|
3289
|
+
return era("narrow");
|
|
3290
|
+
case "kk":
|
|
3291
|
+
return this.num(dt.weekYear.toString().slice(-2), 2);
|
|
3292
|
+
case "kkkk":
|
|
3293
|
+
return this.num(dt.weekYear, 4);
|
|
3294
|
+
case "W":
|
|
3295
|
+
return this.num(dt.weekNumber);
|
|
3296
|
+
case "WW":
|
|
3297
|
+
return this.num(dt.weekNumber, 2);
|
|
3298
|
+
case "o":
|
|
3299
|
+
return this.num(dt.ordinal);
|
|
3300
|
+
case "ooo":
|
|
3301
|
+
return this.num(dt.ordinal, 3);
|
|
3302
|
+
case "q":
|
|
3303
|
+
// like 1
|
|
3304
|
+
return this.num(dt.quarter);
|
|
3305
|
+
case "qq":
|
|
3306
|
+
// like 01
|
|
3307
|
+
return this.num(dt.quarter, 2);
|
|
3308
|
+
case "X":
|
|
3309
|
+
return this.num(Math.floor(dt.ts / 1000));
|
|
3310
|
+
case "x":
|
|
3311
|
+
return this.num(dt.ts);
|
|
3312
|
+
default:
|
|
3313
|
+
return maybeMacro(token);
|
|
3314
|
+
}
|
|
3299
3315
|
};
|
|
3300
|
-
|
|
3301
|
-
// This is problematic. Different calendars are going to define eras totally differently. What I need is the minimum set of dates
|
|
3302
|
-
// to definitely enumerate them.
|
|
3303
|
-
if (!this.eraCache[length]) {
|
|
3304
|
-
this.eraCache[length] = [DateTime.utc(-40, 1, 1), DateTime.utc(2017, 1, 1)].map(dt => this.extract(dt, intl, "era"));
|
|
3305
|
-
}
|
|
3306
|
-
return this.eraCache[length];
|
|
3307
|
-
});
|
|
3308
|
-
}
|
|
3309
|
-
extract(dt, intlOpts, field) {
|
|
3310
|
-
const df = this.dtFormatter(dt, intlOpts),
|
|
3311
|
-
results = df.formatToParts(),
|
|
3312
|
-
matching = results.find(m => m.type.toLowerCase() === field);
|
|
3313
|
-
return matching ? matching.value : null;
|
|
3314
|
-
}
|
|
3315
|
-
numberFormatter(opts = {}) {
|
|
3316
|
-
// this forcesimple option is never used (the only caller short-circuits on it, but it seems safer to leave)
|
|
3317
|
-
// (in contrast, the rest of the condition is used heavily)
|
|
3318
|
-
return new PolyNumberFormatter(this.intl, opts.forceSimple || this.fastNumbers, opts);
|
|
3319
|
-
}
|
|
3320
|
-
dtFormatter(dt, intlOpts = {}) {
|
|
3321
|
-
return new PolyDateFormatter(dt, this.intl, intlOpts);
|
|
3322
|
-
}
|
|
3323
|
-
relFormatter(opts = {}) {
|
|
3324
|
-
return new PolyRelFormatter(this.intl, this.isEnglish(), opts);
|
|
3316
|
+
return stringifyTokens(Formatter.parseFormat(fmt), tokenToString);
|
|
3325
3317
|
}
|
|
3326
|
-
|
|
3327
|
-
|
|
3318
|
+
formatDurationFromString(dur, fmt) {
|
|
3319
|
+
const tokenToField = token => {
|
|
3320
|
+
switch (token[0]) {
|
|
3321
|
+
case "S":
|
|
3322
|
+
return "millisecond";
|
|
3323
|
+
case "s":
|
|
3324
|
+
return "second";
|
|
3325
|
+
case "m":
|
|
3326
|
+
return "minute";
|
|
3327
|
+
case "h":
|
|
3328
|
+
return "hour";
|
|
3329
|
+
case "d":
|
|
3330
|
+
return "day";
|
|
3331
|
+
case "w":
|
|
3332
|
+
return "week";
|
|
3333
|
+
case "M":
|
|
3334
|
+
return "month";
|
|
3335
|
+
case "y":
|
|
3336
|
+
return "year";
|
|
3337
|
+
default:
|
|
3338
|
+
return null;
|
|
3339
|
+
}
|
|
3340
|
+
},
|
|
3341
|
+
tokenToString = lildur => token => {
|
|
3342
|
+
const mapped = tokenToField(token);
|
|
3343
|
+
if (mapped) {
|
|
3344
|
+
return this.num(lildur.get(mapped), token.length);
|
|
3345
|
+
} else {
|
|
3346
|
+
return token;
|
|
3347
|
+
}
|
|
3348
|
+
},
|
|
3349
|
+
tokens = Formatter.parseFormat(fmt),
|
|
3350
|
+
realTokens = tokens.reduce((found, {
|
|
3351
|
+
literal,
|
|
3352
|
+
val
|
|
3353
|
+
}) => literal ? found : found.concat(val), []),
|
|
3354
|
+
collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter(t => t));
|
|
3355
|
+
return stringifyTokens(tokens, tokenToString(collapsed));
|
|
3328
3356
|
}
|
|
3329
|
-
|
|
3330
|
-
|
|
3357
|
+
}
|
|
3358
|
+
|
|
3359
|
+
class Invalid {
|
|
3360
|
+
constructor(reason, explanation) {
|
|
3361
|
+
this.reason = reason;
|
|
3362
|
+
this.explanation = explanation;
|
|
3331
3363
|
}
|
|
3332
|
-
|
|
3333
|
-
|
|
3364
|
+
toMessage() {
|
|
3365
|
+
if (this.explanation) {
|
|
3366
|
+
return `${this.reason}: ${this.explanation}`;
|
|
3367
|
+
} else {
|
|
3368
|
+
return this.reason;
|
|
3369
|
+
}
|
|
3334
3370
|
}
|
|
3335
3371
|
}
|
|
3336
3372
|
|
|
@@ -3344,6 +3380,7 @@
|
|
|
3344
3380
|
* Some extractions are super dumb and simpleParse and fromStrings help DRY them.
|
|
3345
3381
|
*/
|
|
3346
3382
|
|
|
3383
|
+
const ianaRegex = /[A-Za-z_+-]{1,256}(?::?\/[A-Za-z0-9_+-]{1,256}(?:\/[A-Za-z0-9_+-]{1,256})?)?/;
|
|
3347
3384
|
function combineRegexes(...regexes) {
|
|
3348
3385
|
const full = regexes.reduce((f, r) => f + r.source, "");
|
|
3349
3386
|
return RegExp(`^${full}$`);
|
|
@@ -3496,7 +3533,7 @@
|
|
|
3496
3533
|
}
|
|
3497
3534
|
function preprocessRFC2822(s) {
|
|
3498
3535
|
// Remove comments and folding whitespace and replace multiple-spaces with a single space
|
|
3499
|
-
return s.replace(/\([^)]*\)|[\n\t]/g, " ").replace(/(\s\s+)/g, " ").trim();
|
|
3536
|
+
return s.replace(/\([^()]*\)|[\n\t]/g, " ").replace(/(\s\s+)/g, " ").trim();
|
|
3500
3537
|
}
|
|
3501
3538
|
|
|
3502
3539
|
// http date
|
|
@@ -3690,6 +3727,17 @@
|
|
|
3690
3727
|
}, null);
|
|
3691
3728
|
}
|
|
3692
3729
|
|
|
3730
|
+
// Remove all properties with a value of 0 from an object
|
|
3731
|
+
function removeZeroes(vals) {
|
|
3732
|
+
const newVals = {};
|
|
3733
|
+
for (const [key, value] of Object.entries(vals)) {
|
|
3734
|
+
if (value !== 0) {
|
|
3735
|
+
newVals[key] = value;
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
return newVals;
|
|
3739
|
+
}
|
|
3740
|
+
|
|
3693
3741
|
/**
|
|
3694
3742
|
* A Duration object represents a period of time, like "2 months" or "1 day, 1 hour". Conceptually, it's just a map of units to their quantities, accompanied by some additional configuration and methods for creating, parsing, interrogating, transforming, and formatting them. They can be used on their own or in conjunction with other Luxon types; for example, you can use {@link DateTime#plus} to add a Duration object to a DateTime, producing another DateTime.
|
|
3695
3743
|
*
|
|
@@ -4238,6 +4286,19 @@
|
|
|
4238
4286
|
}, true);
|
|
4239
4287
|
}
|
|
4240
4288
|
|
|
4289
|
+
/**
|
|
4290
|
+
* Rescale units to its largest representation
|
|
4291
|
+
* @example Duration.fromObject({ milliseconds: 90000 }).rescale().toObject() //=> { minutes: 1, seconds: 30 }
|
|
4292
|
+
* @return {Duration}
|
|
4293
|
+
*/
|
|
4294
|
+
rescale() {
|
|
4295
|
+
if (!this.isValid) return this;
|
|
4296
|
+
const vals = removeZeroes(this.normalize().shiftToAll().toObject());
|
|
4297
|
+
return clone$2(this, {
|
|
4298
|
+
values: vals
|
|
4299
|
+
}, true);
|
|
4300
|
+
}
|
|
4301
|
+
|
|
4241
4302
|
/**
|
|
4242
4303
|
* Convert this Duration into its representation in a different set of units.
|
|
4243
4304
|
* @example Duration.fromObject({ hours: 1, seconds: 30 }).shiftTo('minutes', 'milliseconds').toObject() //=> { minutes: 60, milliseconds: 30000 }
|
|
@@ -4296,6 +4357,16 @@
|
|
|
4296
4357
|
}, true).normalize();
|
|
4297
4358
|
}
|
|
4298
4359
|
|
|
4360
|
+
/**
|
|
4361
|
+
* Shift this Duration to all available units.
|
|
4362
|
+
* Same as shiftTo("years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds")
|
|
4363
|
+
* @return {Duration}
|
|
4364
|
+
*/
|
|
4365
|
+
shiftToAll() {
|
|
4366
|
+
if (!this.isValid) return this;
|
|
4367
|
+
return this.shiftTo("years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds");
|
|
4368
|
+
}
|
|
4369
|
+
|
|
4299
4370
|
/**
|
|
4300
4371
|
* Return the negative of this Duration.
|
|
4301
4372
|
* @example Duration.fromObject({ hours: 1, seconds: 30 }).negate().toObject() //=> { hours: -1, seconds: -30 }
|
|
@@ -4461,7 +4532,7 @@
|
|
|
4461
4532
|
* * **Interrogation** To analyze the Interval, use {@link Interval#count}, {@link Interval#length}, {@link Interval#hasSame}, {@link Interval#contains}, {@link Interval#isAfter}, or {@link Interval#isBefore}.
|
|
4462
4533
|
* * **Transformation** To create other Intervals out of this one, use {@link Interval#set}, {@link Interval#splitAt}, {@link Interval#splitBy}, {@link Interval#divideEqually}, {@link Interval.merge}, {@link Interval.xor}, {@link Interval#union}, {@link Interval#intersection}, or {@link Interval#difference}.
|
|
4463
4534
|
* * **Comparison** To compare this Interval to another one, use {@link Interval#equals}, {@link Interval#overlaps}, {@link Interval#abutsStart}, {@link Interval#abutsEnd}, {@link Interval#engulfs}
|
|
4464
|
-
* * **Output** To convert the Interval into other representations, see {@link Interval#toString}, {@link Interval#toISO}, {@link Interval#toISODate}, {@link Interval#toISOTime}, {@link Interval#toFormat}, and {@link Interval#toDuration}.
|
|
4535
|
+
* * **Output** To convert the Interval into other representations, see {@link Interval#toString}, {@link Interval#toLocaleString}, {@link Interval#toISO}, {@link Interval#toISODate}, {@link Interval#toISOTime}, {@link Interval#toFormat}, and {@link Interval#toDuration}.
|
|
4465
4536
|
*/
|
|
4466
4537
|
class Interval {
|
|
4467
4538
|
/**
|
|
@@ -4941,6 +5012,28 @@
|
|
|
4941
5012
|
return `[${this.s.toISO()} – ${this.e.toISO()})`;
|
|
4942
5013
|
}
|
|
4943
5014
|
|
|
5015
|
+
/**
|
|
5016
|
+
* Returns a localized string representing this Interval. Accepts the same options as the
|
|
5017
|
+
* Intl.DateTimeFormat constructor and any presets defined by Luxon, such as
|
|
5018
|
+
* {@link DateTime.DATE_FULL} or {@link DateTime.TIME_SIMPLE}. The exact behavior of this method
|
|
5019
|
+
* is browser-specific, but in general it will return an appropriate representation of the
|
|
5020
|
+
* Interval in the assigned locale. Defaults to the system's locale if no locale has been
|
|
5021
|
+
* specified.
|
|
5022
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
|
|
5023
|
+
* @param {Object} [formatOpts=DateTime.DATE_SHORT] - Either a DateTime preset or
|
|
5024
|
+
* Intl.DateTimeFormat constructor options.
|
|
5025
|
+
* @param {Object} opts - Options to override the configuration of the start DateTime.
|
|
5026
|
+
* @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(); //=> 11/7/2022 – 11/8/2022
|
|
5027
|
+
* @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(DateTime.DATE_FULL); //=> November 7 – 8, 2022
|
|
5028
|
+
* @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(DateTime.DATE_FULL, { locale: 'fr-FR' }); //=> 7–8 novembre 2022
|
|
5029
|
+
* @example Interval.fromISO('2022-11-07T17:00Z/2022-11-07T19:00Z').toLocaleString(DateTime.TIME_SIMPLE); //=> 6:00 – 8:00 PM
|
|
5030
|
+
* @example Interval.fromISO('2022-11-07T17:00Z/2022-11-07T19:00Z').toLocaleString({ weekday: 'short', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }); //=> Mon, Nov 07, 6:00 – 8:00 p
|
|
5031
|
+
* @return {string}
|
|
5032
|
+
*/
|
|
5033
|
+
toLocaleString(formatOpts = DATE_SHORT, opts = {}) {
|
|
5034
|
+
return this.isValid ? Formatter.create(this.s.loc.clone(opts), formatOpts).formatInterval(this) : INVALID$3;
|
|
5035
|
+
}
|
|
5036
|
+
|
|
4944
5037
|
/**
|
|
4945
5038
|
* Returns an ISO 8601-compliant string representation of this Interval.
|
|
4946
5039
|
* @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals
|
|
@@ -4976,10 +5069,14 @@
|
|
|
4976
5069
|
}
|
|
4977
5070
|
|
|
4978
5071
|
/**
|
|
4979
|
-
* Returns a string representation of this Interval formatted according to the specified format
|
|
4980
|
-
*
|
|
4981
|
-
*
|
|
4982
|
-
* @param {string}
|
|
5072
|
+
* Returns a string representation of this Interval formatted according to the specified format
|
|
5073
|
+
* string. **You may not want this.** See {@link Interval#toLocaleString} for a more flexible
|
|
5074
|
+
* formatting tool.
|
|
5075
|
+
* @param {string} dateFormat - The format string. This string formats the start and end time.
|
|
5076
|
+
* See {@link DateTime#toFormat} for details.
|
|
5077
|
+
* @param {Object} opts - Options.
|
|
5078
|
+
* @param {string} [opts.separator = ' – '] - A separator to place between the start and end
|
|
5079
|
+
* representations.
|
|
4983
5080
|
* @return {string}
|
|
4984
5081
|
*/
|
|
4985
5082
|
toFormat(dateFormat, {
|
|
@@ -5213,23 +5310,19 @@
|
|
|
5213
5310
|
return (days - days % 7) / 7;
|
|
5214
5311
|
}], ["days", dayDiff]];
|
|
5215
5312
|
const results = {};
|
|
5313
|
+
const earlier = cursor;
|
|
5216
5314
|
let lowestOrder, highWater;
|
|
5217
5315
|
for (const [unit, differ] of differs) {
|
|
5218
5316
|
if (units.indexOf(unit) >= 0) {
|
|
5219
5317
|
lowestOrder = unit;
|
|
5220
|
-
|
|
5221
|
-
highWater =
|
|
5222
|
-
[unit]: delta
|
|
5223
|
-
});
|
|
5318
|
+
results[unit] = differ(cursor, later);
|
|
5319
|
+
highWater = earlier.plus(results);
|
|
5224
5320
|
if (highWater > later) {
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
});
|
|
5228
|
-
delta -= 1;
|
|
5321
|
+
results[unit]--;
|
|
5322
|
+
cursor = earlier.plus(results);
|
|
5229
5323
|
} else {
|
|
5230
5324
|
cursor = highWater;
|
|
5231
5325
|
}
|
|
5232
|
-
results[unit] = delta;
|
|
5233
5326
|
}
|
|
5234
5327
|
}
|
|
5235
5328
|
return [cursor, results, highWater, lowestOrder];
|
|
@@ -5554,7 +5647,7 @@
|
|
|
5554
5647
|
short: "ZZZ"
|
|
5555
5648
|
}
|
|
5556
5649
|
};
|
|
5557
|
-
function tokenForPart(part,
|
|
5650
|
+
function tokenForPart(part, formatOpts) {
|
|
5558
5651
|
const {
|
|
5559
5652
|
type,
|
|
5560
5653
|
value
|
|
@@ -5743,7 +5836,7 @@
|
|
|
5743
5836
|
}
|
|
5744
5837
|
const formatter = Formatter.create(locale, formatOpts);
|
|
5745
5838
|
const parts = formatter.formatDateTimeParts(getDummyDateTime());
|
|
5746
|
-
return parts.map(p => tokenForPart(p,
|
|
5839
|
+
return parts.map(p => tokenForPart(p, formatOpts));
|
|
5747
5840
|
}
|
|
5748
5841
|
|
|
5749
5842
|
const nonLeapLadder = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
|
|
@@ -7765,7 +7858,7 @@
|
|
|
7765
7858
|
|
|
7766
7859
|
/**
|
|
7767
7860
|
* Equality check
|
|
7768
|
-
* Two DateTimes are equal
|
|
7861
|
+
* Two DateTimes are equal if and only if they represent the same millisecond, have the same zone and location, and are both valid.
|
|
7769
7862
|
* To compare just the millisecond values, use `+dt1 === +dt2`.
|
|
7770
7863
|
* @param {DateTime} other - the other DateTime
|
|
7771
7864
|
* @return {boolean}
|
|
@@ -47486,7 +47579,7 @@
|
|
|
47486
47579
|
return e$1("div", {
|
|
47487
47580
|
class: "fjs-palette-field fjs-drag-copy fjs-no-drop",
|
|
47488
47581
|
"data-field-type": type,
|
|
47489
|
-
title: `Create
|
|
47582
|
+
title: `Create ${getIndefiniteArticle(type)} ${label} element`,
|
|
47490
47583
|
children: [Icon ? e$1(Icon, {
|
|
47491
47584
|
class: "fjs-palette-field-icon",
|
|
47492
47585
|
width: "36",
|
|
@@ -47525,6 +47618,12 @@
|
|
|
47525
47618
|
});
|
|
47526
47619
|
return groups.filter(g => g.entries.length);
|
|
47527
47620
|
}
|
|
47621
|
+
function getIndefiniteArticle(type) {
|
|
47622
|
+
if (['image'].includes(type)) {
|
|
47623
|
+
return 'an';
|
|
47624
|
+
}
|
|
47625
|
+
return 'a';
|
|
47626
|
+
}
|
|
47528
47627
|
const CURSOR_CLS_PATTERN = /^fjs-cursor-.*$/;
|
|
47529
47628
|
function set(mode) {
|
|
47530
47629
|
const classes$1 = classes(document.body);
|
|
@@ -52289,6 +52388,7 @@
|
|
|
52289
52388
|
setValue
|
|
52290
52389
|
});
|
|
52291
52390
|
}
|
|
52391
|
+
const EMPTY_OPTION = null;
|
|
52292
52392
|
function DefaultOptionEntry(props) {
|
|
52293
52393
|
const {
|
|
52294
52394
|
editField,
|
|
@@ -52434,13 +52534,14 @@
|
|
|
52434
52534
|
label
|
|
52435
52535
|
} = props;
|
|
52436
52536
|
const {
|
|
52437
|
-
defaultValue,
|
|
52537
|
+
defaultValue = EMPTY_OPTION,
|
|
52438
52538
|
values = []
|
|
52439
52539
|
} = field;
|
|
52440
52540
|
const path = ['defaultValue'];
|
|
52441
52541
|
const getOptions = () => {
|
|
52442
52542
|
return [{
|
|
52443
|
-
label: '<none>'
|
|
52543
|
+
label: '<none>',
|
|
52544
|
+
value: EMPTY_OPTION
|
|
52444
52545
|
}, ...values];
|
|
52445
52546
|
};
|
|
52446
52547
|
const setValue = value => {
|