@nmshd/runtime 2.2.0 → 2.2.1
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/buildInformation.js +5 -5
- package/dist/useCases/transport/relationshipTemplates/CreateOwnRelationshipTemplate.d.ts +4 -1
- package/dist/useCases/transport/relationshipTemplates/CreateOwnRelationshipTemplate.js +24 -1
- package/dist/useCases/transport/relationshipTemplates/CreateOwnRelationshipTemplate.js.map +1 -1
- package/lib-web/nmshd.runtime.js +1538 -1491
- package/lib-web/nmshd.runtime.js.map +1 -1
- package/lib-web/nmshd.runtime.min.js +2 -2
- package/lib-web/nmshd.runtime.min.js.map +1 -1
- package/package.json +6 -6
package/lib-web/nmshd.runtime.js
CHANGED
|
@@ -466,11 +466,11 @@ const content_1 = __webpack_require__(/*! @nmshd/content */ "@nmshd/content");
|
|
|
466
466
|
const crypto_1 = __webpack_require__(/*! @nmshd/crypto */ "@nmshd/crypto");
|
|
467
467
|
const transport_1 = __webpack_require__(/*! @nmshd/transport */ "@nmshd/transport");
|
|
468
468
|
exports.buildInformation = {
|
|
469
|
-
version: "2.2.
|
|
470
|
-
build: "
|
|
471
|
-
date: "2022-12-
|
|
472
|
-
commit: "
|
|
473
|
-
dependencies: {"@js-soft/docdb-querytranslator":"1.1.0","@js-soft/logging-abstractions":"1.0.0","@js-soft/ts-serval":"2.0.5","@js-soft/ts-utils":"^2.3.0","@nmshd/consumption":"2.3.0","@nmshd/content":"2.1.2","@nmshd/crypto":"2.0.3","@nmshd/transport":"2.0.0","ajv":"^8.11.2","ajv-errors":"^3.0.0","ajv-formats":"^2.1.1","json-stringify-safe":"^5.0.1","luxon":"^3.1.
|
|
469
|
+
version: "2.2.1",
|
|
470
|
+
build: "134",
|
|
471
|
+
date: "2022-12-06T13:09:23+00:00",
|
|
472
|
+
commit: "d7f19253acca6735402d45f41ccc4c30d42ff2b5",
|
|
473
|
+
dependencies: {"@js-soft/docdb-querytranslator":"1.1.0","@js-soft/logging-abstractions":"1.0.0","@js-soft/ts-serval":"2.0.5","@js-soft/ts-utils":"^2.3.0","@nmshd/consumption":"2.3.0","@nmshd/content":"2.1.2","@nmshd/crypto":"2.0.3","@nmshd/transport":"2.0.0","ajv":"^8.11.2","ajv-errors":"^3.0.0","ajv-formats":"^2.1.1","json-stringify-safe":"^5.0.1","luxon":"^3.1.1","qrcode":"1.5.1","reflect-metadata":"0.1.13","ts-simple-nameof":"1.3.1","typescript-ioc":"3.2.2"},
|
|
474
474
|
libraries: {
|
|
475
475
|
serval: ts_serval_1.buildInformation,
|
|
476
476
|
consumption: consumption_1.buildInformation,
|
|
@@ -32464,7 +32464,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
32464
32464
|
};
|
|
32465
32465
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
32466
32466
|
exports.CreateOwnRelationshipTemplateUseCase = void 0;
|
|
32467
|
+
const ts_serval_1 = __webpack_require__(/*! @js-soft/ts-serval */ "@js-soft/ts-serval");
|
|
32467
32468
|
const ts_utils_1 = __webpack_require__(/*! @js-soft/ts-utils */ "./node_modules/@js-soft/ts-utils/dist/index.js");
|
|
32469
|
+
const consumption_1 = __webpack_require__(/*! @nmshd/consumption */ "@nmshd/consumption");
|
|
32470
|
+
const content_1 = __webpack_require__(/*! @nmshd/content */ "@nmshd/content");
|
|
32468
32471
|
const transport_1 = __webpack_require__(/*! @nmshd/transport */ "@nmshd/transport");
|
|
32469
32472
|
const luxon_1 = __webpack_require__(/*! luxon */ "./node_modules/luxon/build/node/luxon.js");
|
|
32470
32473
|
const ts_simple_nameof_1 = __webpack_require__(/*! ts-simple-nameof */ "./node_modules/ts-simple-nameof/index.js");
|
|
@@ -32490,12 +32493,16 @@ Validator = __decorate([
|
|
|
32490
32493
|
__metadata("design:paramtypes", [common_1.SchemaRepository])
|
|
32491
32494
|
], Validator);
|
|
32492
32495
|
let CreateOwnRelationshipTemplateUseCase = class CreateOwnRelationshipTemplateUseCase extends common_1.UseCase {
|
|
32493
|
-
constructor(templateController, accountController, validator) {
|
|
32496
|
+
constructor(templateController, accountController, outgoingRequestsController, validator) {
|
|
32494
32497
|
super(validator);
|
|
32495
32498
|
this.templateController = templateController;
|
|
32496
32499
|
this.accountController = accountController;
|
|
32500
|
+
this.outgoingRequestsController = outgoingRequestsController;
|
|
32497
32501
|
}
|
|
32498
32502
|
async executeInternal(request) {
|
|
32503
|
+
const validationError = await this.validateRelationshipTemplateContent(request.content);
|
|
32504
|
+
if (validationError)
|
|
32505
|
+
return ts_utils_1.Result.fail(validationError);
|
|
32499
32506
|
const relationshipTemplate = await this.templateController.sendRelationshipTemplate({
|
|
32500
32507
|
content: request.content,
|
|
32501
32508
|
expiresAt: transport_1.CoreDate.from(request.expiresAt),
|
|
@@ -32504,13 +32511,29 @@ let CreateOwnRelationshipTemplateUseCase = class CreateOwnRelationshipTemplateUs
|
|
|
32504
32511
|
await this.accountController.syncDatawallet();
|
|
32505
32512
|
return ts_utils_1.Result.ok(RelationshipTemplateMapper_1.RelationshipTemplateMapper.toRelationshipTemplateDTO(relationshipTemplate));
|
|
32506
32513
|
}
|
|
32514
|
+
async validateRelationshipTemplateContent(content) {
|
|
32515
|
+
const transformedContent = ts_serval_1.Serializable.fromUnknown(content);
|
|
32516
|
+
if (!(transformedContent instanceof content_1.RelationshipTemplateContent))
|
|
32517
|
+
return;
|
|
32518
|
+
const validationResult = await this.outgoingRequestsController.canCreate({ content: transformedContent.onNewRelationship });
|
|
32519
|
+
if (validationResult.isError())
|
|
32520
|
+
return validationResult.error;
|
|
32521
|
+
if (transformedContent.onExistingRelationship) {
|
|
32522
|
+
const validationResult = await this.outgoingRequestsController.canCreate({ content: transformedContent.onExistingRelationship });
|
|
32523
|
+
if (validationResult.isError())
|
|
32524
|
+
return validationResult.error;
|
|
32525
|
+
}
|
|
32526
|
+
return;
|
|
32527
|
+
}
|
|
32507
32528
|
};
|
|
32508
32529
|
CreateOwnRelationshipTemplateUseCase = __decorate([
|
|
32509
32530
|
__param(0, typescript_ioc_1.Inject),
|
|
32510
32531
|
__param(1, typescript_ioc_1.Inject),
|
|
32511
32532
|
__param(2, typescript_ioc_1.Inject),
|
|
32533
|
+
__param(3, typescript_ioc_1.Inject),
|
|
32512
32534
|
__metadata("design:paramtypes", [transport_1.RelationshipTemplateController,
|
|
32513
32535
|
transport_1.AccountController,
|
|
32536
|
+
consumption_1.OutgoingRequestsController,
|
|
32514
32537
|
Validator])
|
|
32515
32538
|
], CreateOwnRelationshipTemplateUseCase);
|
|
32516
32539
|
exports.CreateOwnRelationshipTemplateUseCase = CreateOwnRelationshipTemplateUseCase;
|
|
@@ -45671,1351 +45694,975 @@ const DATETIME_HUGE_WITH_SECONDS = {
|
|
|
45671
45694
|
timeZoneName: l
|
|
45672
45695
|
};
|
|
45673
45696
|
|
|
45674
|
-
/*
|
|
45675
|
-
This is just a junk drawer, containing anything used across multiple classes.
|
|
45676
|
-
Because Luxon is small(ish), this should stay small and we won't worry about splitting
|
|
45677
|
-
it up into, say, parsingUtil.js and basicUtil.js and so on. But they are divided up by feature area.
|
|
45678
|
-
*/
|
|
45679
45697
|
/**
|
|
45680
|
-
* @
|
|
45698
|
+
* @interface
|
|
45681
45699
|
*/
|
|
45682
|
-
// TYPES
|
|
45683
|
-
|
|
45684
|
-
function isUndefined(o) {
|
|
45685
|
-
return typeof o === "undefined";
|
|
45686
|
-
}
|
|
45687
|
-
function isNumber(o) {
|
|
45688
|
-
return typeof o === "number";
|
|
45689
|
-
}
|
|
45690
|
-
function isInteger(o) {
|
|
45691
|
-
return typeof o === "number" && o % 1 === 0;
|
|
45692
|
-
}
|
|
45693
|
-
function isString(o) {
|
|
45694
|
-
return typeof o === "string";
|
|
45695
|
-
}
|
|
45696
|
-
function isDate(o) {
|
|
45697
|
-
return Object.prototype.toString.call(o) === "[object Date]";
|
|
45698
|
-
} // CAPABILITIES
|
|
45699
|
-
|
|
45700
|
-
function hasRelative() {
|
|
45701
|
-
try {
|
|
45702
|
-
return typeof Intl !== "undefined" && !!Intl.RelativeTimeFormat;
|
|
45703
|
-
} catch (e) {
|
|
45704
|
-
return false;
|
|
45705
|
-
}
|
|
45706
|
-
} // OBJECTS AND ARRAYS
|
|
45707
45700
|
|
|
45708
|
-
|
|
45709
|
-
|
|
45710
|
-
|
|
45711
|
-
|
|
45712
|
-
|
|
45713
|
-
|
|
45701
|
+
class Zone {
|
|
45702
|
+
/**
|
|
45703
|
+
* The type of zone
|
|
45704
|
+
* @abstract
|
|
45705
|
+
* @type {string}
|
|
45706
|
+
*/
|
|
45707
|
+
get type() {
|
|
45708
|
+
throw new ZoneIsAbstractError();
|
|
45714
45709
|
}
|
|
45710
|
+
/**
|
|
45711
|
+
* The name of this zone.
|
|
45712
|
+
* @abstract
|
|
45713
|
+
* @type {string}
|
|
45714
|
+
*/
|
|
45715
45715
|
|
|
45716
|
-
return arr.reduce((best, next) => {
|
|
45717
|
-
const pair = [by(next), next];
|
|
45718
45716
|
|
|
45719
|
-
|
|
45720
|
-
|
|
45721
|
-
|
|
45722
|
-
return best;
|
|
45723
|
-
} else {
|
|
45724
|
-
return pair;
|
|
45725
|
-
}
|
|
45726
|
-
}, null)[1];
|
|
45727
|
-
}
|
|
45728
|
-
function pick(obj, keys) {
|
|
45729
|
-
return keys.reduce((a, k) => {
|
|
45730
|
-
a[k] = obj[k];
|
|
45731
|
-
return a;
|
|
45732
|
-
}, {});
|
|
45733
|
-
}
|
|
45734
|
-
function hasOwnProperty(obj, prop) {
|
|
45735
|
-
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
45736
|
-
} // NUMBERS AND STRINGS
|
|
45717
|
+
get name() {
|
|
45718
|
+
throw new ZoneIsAbstractError();
|
|
45719
|
+
}
|
|
45737
45720
|
|
|
45738
|
-
|
|
45739
|
-
|
|
45740
|
-
}
|
|
45721
|
+
get ianaName() {
|
|
45722
|
+
return this.name;
|
|
45723
|
+
}
|
|
45724
|
+
/**
|
|
45725
|
+
* Returns whether the offset is known to be fixed for the whole year.
|
|
45726
|
+
* @abstract
|
|
45727
|
+
* @type {boolean}
|
|
45728
|
+
*/
|
|
45741
45729
|
|
|
45742
|
-
function floorMod(x, n) {
|
|
45743
|
-
return x - n * Math.floor(x / n);
|
|
45744
|
-
}
|
|
45745
|
-
function padStart(input, n = 2) {
|
|
45746
|
-
const isNeg = input < 0;
|
|
45747
|
-
let padded;
|
|
45748
45730
|
|
|
45749
|
-
|
|
45750
|
-
|
|
45751
|
-
} else {
|
|
45752
|
-
padded = ("" + input).padStart(n, "0");
|
|
45731
|
+
get isUniversal() {
|
|
45732
|
+
throw new ZoneIsAbstractError();
|
|
45753
45733
|
}
|
|
45734
|
+
/**
|
|
45735
|
+
* Returns the offset's common name (such as EST) at the specified timestamp
|
|
45736
|
+
* @abstract
|
|
45737
|
+
* @param {number} ts - Epoch milliseconds for which to get the name
|
|
45738
|
+
* @param {Object} opts - Options to affect the format
|
|
45739
|
+
* @param {string} opts.format - What style of offset to return. Accepts 'long' or 'short'.
|
|
45740
|
+
* @param {string} opts.locale - What locale to return the offset name in.
|
|
45741
|
+
* @return {string}
|
|
45742
|
+
*/
|
|
45754
45743
|
|
|
45755
|
-
|
|
45756
|
-
|
|
45757
|
-
|
|
45758
|
-
if (isUndefined(string) || string === null || string === "") {
|
|
45759
|
-
return undefined;
|
|
45760
|
-
} else {
|
|
45761
|
-
return parseInt(string, 10);
|
|
45762
|
-
}
|
|
45763
|
-
}
|
|
45764
|
-
function parseFloating(string) {
|
|
45765
|
-
if (isUndefined(string) || string === null || string === "") {
|
|
45766
|
-
return undefined;
|
|
45767
|
-
} else {
|
|
45768
|
-
return parseFloat(string);
|
|
45769
|
-
}
|
|
45770
|
-
}
|
|
45771
|
-
function parseMillis(fraction) {
|
|
45772
|
-
// Return undefined (instead of 0) in these cases, where fraction is not set
|
|
45773
|
-
if (isUndefined(fraction) || fraction === null || fraction === "") {
|
|
45774
|
-
return undefined;
|
|
45775
|
-
} else {
|
|
45776
|
-
const f = parseFloat("0." + fraction) * 1000;
|
|
45777
|
-
return Math.floor(f);
|
|
45744
|
+
|
|
45745
|
+
offsetName(ts, opts) {
|
|
45746
|
+
throw new ZoneIsAbstractError();
|
|
45778
45747
|
}
|
|
45779
|
-
|
|
45780
|
-
|
|
45781
|
-
|
|
45782
|
-
|
|
45783
|
-
|
|
45784
|
-
|
|
45748
|
+
/**
|
|
45749
|
+
* Returns the offset's value as a string
|
|
45750
|
+
* @abstract
|
|
45751
|
+
* @param {number} ts - Epoch milliseconds for which to get the offset
|
|
45752
|
+
* @param {string} format - What style of offset to return.
|
|
45753
|
+
* Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively
|
|
45754
|
+
* @return {string}
|
|
45755
|
+
*/
|
|
45785
45756
|
|
|
45786
|
-
function isLeapYear(year) {
|
|
45787
|
-
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
45788
|
-
}
|
|
45789
|
-
function daysInYear(year) {
|
|
45790
|
-
return isLeapYear(year) ? 366 : 365;
|
|
45791
|
-
}
|
|
45792
|
-
function daysInMonth(year, month) {
|
|
45793
|
-
const modMonth = floorMod(month - 1, 12) + 1,
|
|
45794
|
-
modYear = year + (month - modMonth) / 12;
|
|
45795
45757
|
|
|
45796
|
-
|
|
45797
|
-
|
|
45798
|
-
} else {
|
|
45799
|
-
return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][modMonth - 1];
|
|
45758
|
+
formatOffset(ts, format) {
|
|
45759
|
+
throw new ZoneIsAbstractError();
|
|
45800
45760
|
}
|
|
45801
|
-
|
|
45761
|
+
/**
|
|
45762
|
+
* Return the offset in minutes for this zone at the specified timestamp.
|
|
45763
|
+
* @abstract
|
|
45764
|
+
* @param {number} ts - Epoch milliseconds for which to compute the offset
|
|
45765
|
+
* @return {number}
|
|
45766
|
+
*/
|
|
45802
45767
|
|
|
45803
|
-
function objToLocalTS(obj) {
|
|
45804
|
-
let d = Date.UTC(obj.year, obj.month - 1, obj.day, obj.hour, obj.minute, obj.second, obj.millisecond); // for legacy reasons, years between 0 and 99 are interpreted as 19XX; revert that
|
|
45805
45768
|
|
|
45806
|
-
|
|
45807
|
-
|
|
45808
|
-
d.setUTCFullYear(d.getUTCFullYear() - 1900);
|
|
45769
|
+
offset(ts) {
|
|
45770
|
+
throw new ZoneIsAbstractError();
|
|
45809
45771
|
}
|
|
45772
|
+
/**
|
|
45773
|
+
* Return whether this Zone is equal to another zone
|
|
45774
|
+
* @abstract
|
|
45775
|
+
* @param {Zone} otherZone - the zone to compare
|
|
45776
|
+
* @return {boolean}
|
|
45777
|
+
*/
|
|
45810
45778
|
|
|
45811
|
-
return +d;
|
|
45812
|
-
}
|
|
45813
|
-
function weeksInWeekYear(weekYear) {
|
|
45814
|
-
const p1 = (weekYear + Math.floor(weekYear / 4) - Math.floor(weekYear / 100) + Math.floor(weekYear / 400)) % 7,
|
|
45815
|
-
last = weekYear - 1,
|
|
45816
|
-
p2 = (last + Math.floor(last / 4) - Math.floor(last / 100) + Math.floor(last / 400)) % 7;
|
|
45817
|
-
return p1 === 4 || p2 === 3 ? 53 : 52;
|
|
45818
|
-
}
|
|
45819
|
-
function untruncateYear(year) {
|
|
45820
|
-
if (year > 99) {
|
|
45821
|
-
return year;
|
|
45822
|
-
} else return year > 60 ? 1900 + year : 2000 + year;
|
|
45823
|
-
} // PARSING
|
|
45824
|
-
|
|
45825
|
-
function parseZoneInfo(ts, offsetFormat, locale, timeZone = null) {
|
|
45826
|
-
const date = new Date(ts),
|
|
45827
|
-
intlOpts = {
|
|
45828
|
-
hourCycle: "h23",
|
|
45829
|
-
year: "numeric",
|
|
45830
|
-
month: "2-digit",
|
|
45831
|
-
day: "2-digit",
|
|
45832
|
-
hour: "2-digit",
|
|
45833
|
-
minute: "2-digit"
|
|
45834
|
-
};
|
|
45835
45779
|
|
|
45836
|
-
|
|
45837
|
-
|
|
45780
|
+
equals(otherZone) {
|
|
45781
|
+
throw new ZoneIsAbstractError();
|
|
45838
45782
|
}
|
|
45783
|
+
/**
|
|
45784
|
+
* Return whether this Zone is valid.
|
|
45785
|
+
* @abstract
|
|
45786
|
+
* @type {boolean}
|
|
45787
|
+
*/
|
|
45839
45788
|
|
|
45840
|
-
const modified = {
|
|
45841
|
-
timeZoneName: offsetFormat,
|
|
45842
|
-
...intlOpts
|
|
45843
|
-
};
|
|
45844
|
-
const parsed = new Intl.DateTimeFormat(locale, modified).formatToParts(date).find(m => m.type.toLowerCase() === "timezonename");
|
|
45845
|
-
return parsed ? parsed.value : null;
|
|
45846
|
-
} // signedOffset('-5', '30') -> -330
|
|
45847
|
-
|
|
45848
|
-
function signedOffset(offHourStr, offMinuteStr) {
|
|
45849
|
-
let offHour = parseInt(offHourStr, 10); // don't || this because we want to preserve -0
|
|
45850
45789
|
|
|
45851
|
-
|
|
45852
|
-
|
|
45790
|
+
get isValid() {
|
|
45791
|
+
throw new ZoneIsAbstractError();
|
|
45853
45792
|
}
|
|
45854
45793
|
|
|
45855
|
-
const offMin = parseInt(offMinuteStr, 10) || 0,
|
|
45856
|
-
offMinSigned = offHour < 0 || Object.is(offHour, -0) ? -offMin : offMin;
|
|
45857
|
-
return offHour * 60 + offMinSigned;
|
|
45858
|
-
} // COERCION
|
|
45859
|
-
|
|
45860
|
-
function asNumber(value) {
|
|
45861
|
-
const numericValue = Number(value);
|
|
45862
|
-
if (typeof value === "boolean" || value === "" || Number.isNaN(numericValue)) throw new InvalidArgumentError(`Invalid unit value ${value}`);
|
|
45863
|
-
return numericValue;
|
|
45864
45794
|
}
|
|
45865
|
-
function normalizeObject(obj, normalizer) {
|
|
45866
|
-
const normalized = {};
|
|
45867
45795
|
|
|
45868
|
-
|
|
45869
|
-
|
|
45870
|
-
|
|
45871
|
-
|
|
45872
|
-
|
|
45796
|
+
let singleton$1 = null;
|
|
45797
|
+
/**
|
|
45798
|
+
* Represents the local zone for this JavaScript environment.
|
|
45799
|
+
* @implements {Zone}
|
|
45800
|
+
*/
|
|
45801
|
+
|
|
45802
|
+
class SystemZone extends Zone {
|
|
45803
|
+
/**
|
|
45804
|
+
* Get a singleton instance of the local zone
|
|
45805
|
+
* @return {SystemZone}
|
|
45806
|
+
*/
|
|
45807
|
+
static get instance() {
|
|
45808
|
+
if (singleton$1 === null) {
|
|
45809
|
+
singleton$1 = new SystemZone();
|
|
45873
45810
|
}
|
|
45874
|
-
}
|
|
45875
45811
|
|
|
45876
|
-
|
|
45877
|
-
}
|
|
45878
|
-
|
|
45879
|
-
const hours = Math.trunc(Math.abs(offset / 60)),
|
|
45880
|
-
minutes = Math.trunc(Math.abs(offset % 60)),
|
|
45881
|
-
sign = offset >= 0 ? "+" : "-";
|
|
45812
|
+
return singleton$1;
|
|
45813
|
+
}
|
|
45814
|
+
/** @override **/
|
|
45882
45815
|
|
|
45883
|
-
switch (format) {
|
|
45884
|
-
case "short":
|
|
45885
|
-
return `${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}`;
|
|
45886
45816
|
|
|
45887
|
-
|
|
45888
|
-
|
|
45817
|
+
get type() {
|
|
45818
|
+
return "system";
|
|
45819
|
+
}
|
|
45820
|
+
/** @override **/
|
|
45889
45821
|
|
|
45890
|
-
case "techie":
|
|
45891
|
-
return `${sign}${padStart(hours, 2)}${padStart(minutes, 2)}`;
|
|
45892
45822
|
|
|
45893
|
-
|
|
45894
|
-
|
|
45823
|
+
get name() {
|
|
45824
|
+
return new Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
45895
45825
|
}
|
|
45896
|
-
|
|
45897
|
-
function timeObject(obj) {
|
|
45898
|
-
return pick(obj, ["hour", "minute", "second", "millisecond"]);
|
|
45899
|
-
}
|
|
45900
|
-
const ianaRegex = /[A-Za-z_+-]{1,256}(?::?\/[A-Za-z0-9_+-]{1,256}(?:\/[A-Za-z0-9_+-]{1,256})?)?/;
|
|
45826
|
+
/** @override **/
|
|
45901
45827
|
|
|
45902
|
-
/**
|
|
45903
|
-
* @private
|
|
45904
|
-
*/
|
|
45905
45828
|
|
|
45829
|
+
get isUniversal() {
|
|
45830
|
+
return false;
|
|
45831
|
+
}
|
|
45832
|
+
/** @override **/
|
|
45906
45833
|
|
|
45907
|
-
const monthsLong = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
45908
|
-
const monthsShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
45909
|
-
const monthsNarrow = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"];
|
|
45910
|
-
function months(length) {
|
|
45911
|
-
switch (length) {
|
|
45912
|
-
case "narrow":
|
|
45913
|
-
return [...monthsNarrow];
|
|
45914
45834
|
|
|
45915
|
-
|
|
45916
|
-
|
|
45835
|
+
offsetName(ts, {
|
|
45836
|
+
format,
|
|
45837
|
+
locale
|
|
45838
|
+
}) {
|
|
45839
|
+
return parseZoneInfo(ts, format, locale);
|
|
45840
|
+
}
|
|
45841
|
+
/** @override **/
|
|
45917
45842
|
|
|
45918
|
-
case "long":
|
|
45919
|
-
return [...monthsLong];
|
|
45920
45843
|
|
|
45921
|
-
|
|
45922
|
-
|
|
45844
|
+
formatOffset(ts, format) {
|
|
45845
|
+
return formatOffset(this.offset(ts), format);
|
|
45846
|
+
}
|
|
45847
|
+
/** @override **/
|
|
45923
45848
|
|
|
45924
|
-
case "2-digit":
|
|
45925
|
-
return ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
|
|
45926
45849
|
|
|
45927
|
-
|
|
45928
|
-
|
|
45850
|
+
offset(ts) {
|
|
45851
|
+
return -new Date(ts).getTimezoneOffset();
|
|
45929
45852
|
}
|
|
45930
|
-
|
|
45931
|
-
const weekdaysLong = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
|
45932
|
-
const weekdaysShort = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
45933
|
-
const weekdaysNarrow = ["M", "T", "W", "T", "F", "S", "S"];
|
|
45934
|
-
function weekdays(length) {
|
|
45935
|
-
switch (length) {
|
|
45936
|
-
case "narrow":
|
|
45937
|
-
return [...weekdaysNarrow];
|
|
45853
|
+
/** @override **/
|
|
45938
45854
|
|
|
45939
|
-
case "short":
|
|
45940
|
-
return [...weekdaysShort];
|
|
45941
45855
|
|
|
45942
|
-
|
|
45943
|
-
|
|
45856
|
+
equals(otherZone) {
|
|
45857
|
+
return otherZone.type === "system";
|
|
45858
|
+
}
|
|
45859
|
+
/** @override **/
|
|
45944
45860
|
|
|
45945
|
-
case "numeric":
|
|
45946
|
-
return ["1", "2", "3", "4", "5", "6", "7"];
|
|
45947
45861
|
|
|
45948
|
-
|
|
45949
|
-
|
|
45862
|
+
get isValid() {
|
|
45863
|
+
return true;
|
|
45950
45864
|
}
|
|
45951
|
-
}
|
|
45952
|
-
const meridiems = ["AM", "PM"];
|
|
45953
|
-
const erasLong = ["Before Christ", "Anno Domini"];
|
|
45954
|
-
const erasShort = ["BC", "AD"];
|
|
45955
|
-
const erasNarrow = ["B", "A"];
|
|
45956
|
-
function eras(length) {
|
|
45957
|
-
switch (length) {
|
|
45958
|
-
case "narrow":
|
|
45959
|
-
return [...erasNarrow];
|
|
45960
45865
|
|
|
45961
|
-
|
|
45962
|
-
return [...erasShort];
|
|
45866
|
+
}
|
|
45963
45867
|
|
|
45964
|
-
|
|
45965
|
-
return [...erasLong];
|
|
45868
|
+
let dtfCache = {};
|
|
45966
45869
|
|
|
45967
|
-
|
|
45968
|
-
|
|
45870
|
+
function makeDTF(zone) {
|
|
45871
|
+
if (!dtfCache[zone]) {
|
|
45872
|
+
dtfCache[zone] = new Intl.DateTimeFormat("en-US", {
|
|
45873
|
+
hour12: false,
|
|
45874
|
+
timeZone: zone,
|
|
45875
|
+
year: "numeric",
|
|
45876
|
+
month: "2-digit",
|
|
45877
|
+
day: "2-digit",
|
|
45878
|
+
hour: "2-digit",
|
|
45879
|
+
minute: "2-digit",
|
|
45880
|
+
second: "2-digit",
|
|
45881
|
+
era: "short"
|
|
45882
|
+
});
|
|
45969
45883
|
}
|
|
45884
|
+
|
|
45885
|
+
return dtfCache[zone];
|
|
45970
45886
|
}
|
|
45971
|
-
function meridiemForDateTime(dt) {
|
|
45972
|
-
return meridiems[dt.hour < 12 ? 0 : 1];
|
|
45973
|
-
}
|
|
45974
|
-
function weekdayForDateTime(dt, length) {
|
|
45975
|
-
return weekdays(length)[dt.weekday - 1];
|
|
45976
|
-
}
|
|
45977
|
-
function monthForDateTime(dt, length) {
|
|
45978
|
-
return months(length)[dt.month - 1];
|
|
45979
|
-
}
|
|
45980
|
-
function eraForDateTime(dt, length) {
|
|
45981
|
-
return eras(length)[dt.year < 0 ? 0 : 1];
|
|
45982
|
-
}
|
|
45983
|
-
function formatRelativeTime(unit, count, numeric = "always", narrow = false) {
|
|
45984
|
-
const units = {
|
|
45985
|
-
years: ["year", "yr."],
|
|
45986
|
-
quarters: ["quarter", "qtr."],
|
|
45987
|
-
months: ["month", "mo."],
|
|
45988
|
-
weeks: ["week", "wk."],
|
|
45989
|
-
days: ["day", "day", "days"],
|
|
45990
|
-
hours: ["hour", "hr."],
|
|
45991
|
-
minutes: ["minute", "min."],
|
|
45992
|
-
seconds: ["second", "sec."]
|
|
45993
|
-
};
|
|
45994
|
-
const lastable = ["hours", "minutes", "seconds"].indexOf(unit) === -1;
|
|
45995
45887
|
|
|
45996
|
-
|
|
45997
|
-
|
|
45888
|
+
const typeToPos = {
|
|
45889
|
+
year: 0,
|
|
45890
|
+
month: 1,
|
|
45891
|
+
day: 2,
|
|
45892
|
+
era: 3,
|
|
45893
|
+
hour: 4,
|
|
45894
|
+
minute: 5,
|
|
45895
|
+
second: 6
|
|
45896
|
+
};
|
|
45998
45897
|
|
|
45999
|
-
|
|
46000
|
-
|
|
46001
|
-
|
|
45898
|
+
function hackyOffset(dtf, date) {
|
|
45899
|
+
const formatted = dtf.format(date).replace(/\u200E/g, ""),
|
|
45900
|
+
parsed = /(\d+)\/(\d+)\/(\d+) (AD|BC),? (\d+):(\d+):(\d+)/.exec(formatted),
|
|
45901
|
+
[, fMonth, fDay, fYear, fadOrBc, fHour, fMinute, fSecond] = parsed;
|
|
45902
|
+
return [fYear, fMonth, fDay, fadOrBc, fHour, fMinute, fSecond];
|
|
45903
|
+
}
|
|
46002
45904
|
|
|
46003
|
-
|
|
46004
|
-
|
|
45905
|
+
function partsOffset(dtf, date) {
|
|
45906
|
+
const formatted = dtf.formatToParts(date);
|
|
45907
|
+
const filled = [];
|
|
46005
45908
|
|
|
46006
|
-
|
|
46007
|
-
|
|
45909
|
+
for (let i = 0; i < formatted.length; i++) {
|
|
45910
|
+
const {
|
|
45911
|
+
type,
|
|
45912
|
+
value
|
|
45913
|
+
} = formatted[i];
|
|
45914
|
+
const pos = typeToPos[type];
|
|
46008
45915
|
|
|
45916
|
+
if (type === "era") {
|
|
45917
|
+
filled[pos] = value;
|
|
45918
|
+
} else if (!isUndefined(pos)) {
|
|
45919
|
+
filled[pos] = parseInt(value, 10);
|
|
46009
45920
|
}
|
|
46010
45921
|
}
|
|
46011
45922
|
|
|
46012
|
-
|
|
46013
|
-
fmtValue = Math.abs(count),
|
|
46014
|
-
singular = fmtValue === 1,
|
|
46015
|
-
lilUnits = units[unit],
|
|
46016
|
-
fmtUnit = narrow ? singular ? lilUnits[1] : lilUnits[2] || lilUnits[1] : singular ? units[unit][0] : unit;
|
|
46017
|
-
return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}`;
|
|
45923
|
+
return filled;
|
|
46018
45924
|
}
|
|
46019
45925
|
|
|
46020
|
-
|
|
46021
|
-
|
|
45926
|
+
let ianaZoneCache = {};
|
|
45927
|
+
/**
|
|
45928
|
+
* A zone identified by an IANA identifier, like America/New_York
|
|
45929
|
+
* @implements {Zone}
|
|
45930
|
+
*/
|
|
46022
45931
|
|
|
46023
|
-
|
|
46024
|
-
|
|
46025
|
-
|
|
46026
|
-
|
|
46027
|
-
|
|
45932
|
+
class IANAZone extends Zone {
|
|
45933
|
+
/**
|
|
45934
|
+
* @param {string} name - Zone name
|
|
45935
|
+
* @return {IANAZone}
|
|
45936
|
+
*/
|
|
45937
|
+
static create(name) {
|
|
45938
|
+
if (!ianaZoneCache[name]) {
|
|
45939
|
+
ianaZoneCache[name] = new IANAZone(name);
|
|
46028
45940
|
}
|
|
46029
|
-
}
|
|
46030
45941
|
|
|
46031
|
-
|
|
46032
|
-
}
|
|
45942
|
+
return ianaZoneCache[name];
|
|
45943
|
+
}
|
|
45944
|
+
/**
|
|
45945
|
+
* Reset local caches. Should only be necessary in testing scenarios.
|
|
45946
|
+
* @return {void}
|
|
45947
|
+
*/
|
|
46033
45948
|
|
|
46034
|
-
const macroTokenToFormatOpts = {
|
|
46035
|
-
D: DATE_SHORT,
|
|
46036
|
-
DD: DATE_MED,
|
|
46037
|
-
DDD: DATE_FULL,
|
|
46038
|
-
DDDD: DATE_HUGE,
|
|
46039
|
-
t: TIME_SIMPLE,
|
|
46040
|
-
tt: TIME_WITH_SECONDS,
|
|
46041
|
-
ttt: TIME_WITH_SHORT_OFFSET,
|
|
46042
|
-
tttt: TIME_WITH_LONG_OFFSET,
|
|
46043
|
-
T: TIME_24_SIMPLE,
|
|
46044
|
-
TT: TIME_24_WITH_SECONDS,
|
|
46045
|
-
TTT: TIME_24_WITH_SHORT_OFFSET,
|
|
46046
|
-
TTTT: TIME_24_WITH_LONG_OFFSET,
|
|
46047
|
-
f: DATETIME_SHORT,
|
|
46048
|
-
ff: DATETIME_MED,
|
|
46049
|
-
fff: DATETIME_FULL,
|
|
46050
|
-
ffff: DATETIME_HUGE,
|
|
46051
|
-
F: DATETIME_SHORT_WITH_SECONDS,
|
|
46052
|
-
FF: DATETIME_MED_WITH_SECONDS,
|
|
46053
|
-
FFF: DATETIME_FULL_WITH_SECONDS,
|
|
46054
|
-
FFFF: DATETIME_HUGE_WITH_SECONDS
|
|
46055
|
-
};
|
|
46056
|
-
/**
|
|
46057
|
-
* @private
|
|
46058
|
-
*/
|
|
46059
45949
|
|
|
46060
|
-
|
|
46061
|
-
|
|
46062
|
-
|
|
45950
|
+
static resetCache() {
|
|
45951
|
+
ianaZoneCache = {};
|
|
45952
|
+
dtfCache = {};
|
|
46063
45953
|
}
|
|
45954
|
+
/**
|
|
45955
|
+
* Returns whether the provided string is a valid specifier. This only checks the string's format, not that the specifier identifies a known zone; see isValidZone for that.
|
|
45956
|
+
* @param {string} s - The string to check validity on
|
|
45957
|
+
* @example IANAZone.isValidSpecifier("America/New_York") //=> true
|
|
45958
|
+
* @example IANAZone.isValidSpecifier("Sport~~blorp") //=> false
|
|
45959
|
+
* @deprecated This method returns false for some valid IANA names. Use isValidZone instead.
|
|
45960
|
+
* @return {boolean}
|
|
45961
|
+
*/
|
|
46064
45962
|
|
|
46065
|
-
static parseFormat(fmt) {
|
|
46066
|
-
let current = null,
|
|
46067
|
-
currentFull = "",
|
|
46068
|
-
bracketed = false;
|
|
46069
|
-
const splits = [];
|
|
46070
|
-
|
|
46071
|
-
for (let i = 0; i < fmt.length; i++) {
|
|
46072
|
-
const c = fmt.charAt(i);
|
|
46073
45963
|
|
|
46074
|
-
|
|
46075
|
-
|
|
46076
|
-
|
|
46077
|
-
|
|
46078
|
-
|
|
46079
|
-
|
|
46080
|
-
|
|
45964
|
+
static isValidSpecifier(s) {
|
|
45965
|
+
return this.isValidZone(s);
|
|
45966
|
+
}
|
|
45967
|
+
/**
|
|
45968
|
+
* Returns whether the provided string identifies a real zone
|
|
45969
|
+
* @param {string} zone - The string to check
|
|
45970
|
+
* @example IANAZone.isValidZone("America/New_York") //=> true
|
|
45971
|
+
* @example IANAZone.isValidZone("Fantasia/Castle") //=> false
|
|
45972
|
+
* @example IANAZone.isValidZone("Sport~~blorp") //=> false
|
|
45973
|
+
* @return {boolean}
|
|
45974
|
+
*/
|
|
46081
45975
|
|
|
46082
|
-
current = null;
|
|
46083
|
-
currentFull = "";
|
|
46084
|
-
bracketed = !bracketed;
|
|
46085
|
-
} else if (bracketed) {
|
|
46086
|
-
currentFull += c;
|
|
46087
|
-
} else if (c === current) {
|
|
46088
|
-
currentFull += c;
|
|
46089
|
-
} else {
|
|
46090
|
-
if (currentFull.length > 0) {
|
|
46091
|
-
splits.push({
|
|
46092
|
-
literal: false,
|
|
46093
|
-
val: currentFull
|
|
46094
|
-
});
|
|
46095
|
-
}
|
|
46096
45976
|
|
|
46097
|
-
|
|
46098
|
-
|
|
46099
|
-
|
|
45977
|
+
static isValidZone(zone) {
|
|
45978
|
+
if (!zone) {
|
|
45979
|
+
return false;
|
|
46100
45980
|
}
|
|
46101
45981
|
|
|
46102
|
-
|
|
46103
|
-
|
|
46104
|
-
|
|
46105
|
-
|
|
46106
|
-
|
|
45982
|
+
try {
|
|
45983
|
+
new Intl.DateTimeFormat("en-US", {
|
|
45984
|
+
timeZone: zone
|
|
45985
|
+
}).format();
|
|
45986
|
+
return true;
|
|
45987
|
+
} catch (e) {
|
|
45988
|
+
return false;
|
|
46107
45989
|
}
|
|
46108
|
-
|
|
46109
|
-
return splits;
|
|
46110
|
-
}
|
|
46111
|
-
|
|
46112
|
-
static macroTokenToFormatOpts(token) {
|
|
46113
|
-
return macroTokenToFormatOpts[token];
|
|
46114
45990
|
}
|
|
46115
45991
|
|
|
46116
|
-
constructor(
|
|
46117
|
-
|
|
46118
|
-
|
|
46119
|
-
this.systemLoc = null;
|
|
46120
|
-
}
|
|
45992
|
+
constructor(name) {
|
|
45993
|
+
super();
|
|
45994
|
+
/** @private **/
|
|
46121
45995
|
|
|
46122
|
-
|
|
46123
|
-
|
|
46124
|
-
this.systemLoc = this.loc.redefaultToSystem();
|
|
46125
|
-
}
|
|
45996
|
+
this.zoneName = name;
|
|
45997
|
+
/** @private **/
|
|
46126
45998
|
|
|
46127
|
-
|
|
46128
|
-
...opts
|
|
46129
|
-
});
|
|
46130
|
-
return df.format();
|
|
45999
|
+
this.valid = IANAZone.isValidZone(name);
|
|
46131
46000
|
}
|
|
46001
|
+
/** @override **/
|
|
46132
46002
|
|
|
46133
|
-
formatDateTime(dt, opts = {}) {
|
|
46134
|
-
const df = this.loc.dtFormatter(dt, { ...this.opts,
|
|
46135
|
-
...opts
|
|
46136
|
-
});
|
|
46137
|
-
return df.format();
|
|
46138
|
-
}
|
|
46139
46003
|
|
|
46140
|
-
|
|
46141
|
-
|
|
46142
|
-
...opts
|
|
46143
|
-
});
|
|
46144
|
-
return df.formatToParts();
|
|
46004
|
+
get type() {
|
|
46005
|
+
return "iana";
|
|
46145
46006
|
}
|
|
46007
|
+
/** @override **/
|
|
46146
46008
|
|
|
46147
|
-
|
|
46148
|
-
|
|
46149
|
-
|
|
46150
|
-
});
|
|
46151
|
-
return df.resolvedOptions();
|
|
46009
|
+
|
|
46010
|
+
get name() {
|
|
46011
|
+
return this.zoneName;
|
|
46152
46012
|
}
|
|
46013
|
+
/** @override **/
|
|
46153
46014
|
|
|
46154
|
-
num(n, p = 0) {
|
|
46155
|
-
// we get some perf out of doing this here, annoyingly
|
|
46156
|
-
if (this.opts.forceSimple) {
|
|
46157
|
-
return padStart(n, p);
|
|
46158
|
-
}
|
|
46159
46015
|
|
|
46160
|
-
|
|
46161
|
-
|
|
46016
|
+
get isUniversal() {
|
|
46017
|
+
return false;
|
|
46018
|
+
}
|
|
46019
|
+
/** @override **/
|
|
46162
46020
|
|
|
46163
|
-
if (p > 0) {
|
|
46164
|
-
opts.padTo = p;
|
|
46165
|
-
}
|
|
46166
46021
|
|
|
46167
|
-
|
|
46022
|
+
offsetName(ts, {
|
|
46023
|
+
format,
|
|
46024
|
+
locale
|
|
46025
|
+
}) {
|
|
46026
|
+
return parseZoneInfo(ts, format, locale, this.name);
|
|
46168
46027
|
}
|
|
46028
|
+
/** @override **/
|
|
46169
46029
|
|
|
46170
|
-
formatDateTimeFromString(dt, fmt) {
|
|
46171
|
-
const knownEnglish = this.loc.listingMode() === "en",
|
|
46172
|
-
useDateTimeFormatter = this.loc.outputCalendar && this.loc.outputCalendar !== "gregory",
|
|
46173
|
-
string = (opts, extract) => this.loc.extract(dt, opts, extract),
|
|
46174
|
-
formatOffset = opts => {
|
|
46175
|
-
if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) {
|
|
46176
|
-
return "Z";
|
|
46177
|
-
}
|
|
46178
46030
|
|
|
46179
|
-
|
|
46180
|
-
|
|
46181
|
-
|
|
46182
|
-
|
|
46183
|
-
hourCycle: "h12"
|
|
46184
|
-
}, "dayperiod"),
|
|
46185
|
-
month = (length, standalone) => knownEnglish ? monthForDateTime(dt, length) : string(standalone ? {
|
|
46186
|
-
month: length
|
|
46187
|
-
} : {
|
|
46188
|
-
month: length,
|
|
46189
|
-
day: "numeric"
|
|
46190
|
-
}, "month"),
|
|
46191
|
-
weekday = (length, standalone) => knownEnglish ? weekdayForDateTime(dt, length) : string(standalone ? {
|
|
46192
|
-
weekday: length
|
|
46193
|
-
} : {
|
|
46194
|
-
weekday: length,
|
|
46195
|
-
month: "long",
|
|
46196
|
-
day: "numeric"
|
|
46197
|
-
}, "weekday"),
|
|
46198
|
-
maybeMacro = token => {
|
|
46199
|
-
const formatOpts = Formatter.macroTokenToFormatOpts(token);
|
|
46031
|
+
formatOffset(ts, format) {
|
|
46032
|
+
return formatOffset(this.offset(ts), format);
|
|
46033
|
+
}
|
|
46034
|
+
/** @override **/
|
|
46200
46035
|
|
|
46201
|
-
if (formatOpts) {
|
|
46202
|
-
return this.formatWithSystemDefault(dt, formatOpts);
|
|
46203
|
-
} else {
|
|
46204
|
-
return token;
|
|
46205
|
-
}
|
|
46206
|
-
},
|
|
46207
|
-
era = length => knownEnglish ? eraForDateTime(dt, length) : string({
|
|
46208
|
-
era: length
|
|
46209
|
-
}, "era"),
|
|
46210
|
-
tokenToString = token => {
|
|
46211
|
-
// Where possible: http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles
|
|
46212
|
-
switch (token) {
|
|
46213
|
-
// ms
|
|
46214
|
-
case "S":
|
|
46215
|
-
return this.num(dt.millisecond);
|
|
46216
46036
|
|
|
46217
|
-
|
|
46037
|
+
offset(ts) {
|
|
46038
|
+
const date = new Date(ts);
|
|
46039
|
+
if (isNaN(date)) return NaN;
|
|
46040
|
+
const dtf = makeDTF(this.name);
|
|
46041
|
+
let [year, month, day, adOrBc, hour, minute, second] = dtf.formatToParts ? partsOffset(dtf, date) : hackyOffset(dtf, date);
|
|
46218
46042
|
|
|
46219
|
-
|
|
46220
|
-
|
|
46221
|
-
|
|
46043
|
+
if (adOrBc === "BC") {
|
|
46044
|
+
year = -Math.abs(year) + 1;
|
|
46045
|
+
} // because we're using hour12 and https://bugs.chromium.org/p/chromium/issues/detail?id=1025564&can=2&q=%2224%3A00%22%20datetimeformat
|
|
46222
46046
|
|
|
46223
|
-
case "s":
|
|
46224
|
-
return this.num(dt.second);
|
|
46225
46047
|
|
|
46226
|
-
|
|
46227
|
-
|
|
46228
|
-
|
|
46048
|
+
const adjustedHour = hour === 24 ? 0 : hour;
|
|
46049
|
+
const asUTC = objToLocalTS({
|
|
46050
|
+
year,
|
|
46051
|
+
month,
|
|
46052
|
+
day,
|
|
46053
|
+
hour: adjustedHour,
|
|
46054
|
+
minute,
|
|
46055
|
+
second,
|
|
46056
|
+
millisecond: 0
|
|
46057
|
+
});
|
|
46058
|
+
let asTS = +date;
|
|
46059
|
+
const over = asTS % 1000;
|
|
46060
|
+
asTS -= over >= 0 ? over : 1000 + over;
|
|
46061
|
+
return (asUTC - asTS) / (60 * 1000);
|
|
46062
|
+
}
|
|
46063
|
+
/** @override **/
|
|
46229
46064
|
|
|
46230
|
-
case "uu":
|
|
46231
|
-
return this.num(Math.floor(dt.millisecond / 10), 2);
|
|
46232
46065
|
|
|
46233
|
-
|
|
46234
|
-
|
|
46235
|
-
|
|
46066
|
+
equals(otherZone) {
|
|
46067
|
+
return otherZone.type === "iana" && otherZone.name === this.name;
|
|
46068
|
+
}
|
|
46069
|
+
/** @override **/
|
|
46236
46070
|
|
|
46237
|
-
case "m":
|
|
46238
|
-
return this.num(dt.minute);
|
|
46239
46071
|
|
|
46240
|
-
|
|
46241
|
-
|
|
46242
|
-
|
|
46072
|
+
get isValid() {
|
|
46073
|
+
return this.valid;
|
|
46074
|
+
}
|
|
46243
46075
|
|
|
46244
|
-
|
|
46245
|
-
return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12);
|
|
46076
|
+
}
|
|
46246
46077
|
|
|
46247
|
-
|
|
46248
|
-
return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12, 2);
|
|
46078
|
+
let intlLFCache = {};
|
|
46249
46079
|
|
|
46250
|
-
|
|
46251
|
-
|
|
46080
|
+
function getCachedLF(locString, opts = {}) {
|
|
46081
|
+
const key = JSON.stringify([locString, opts]);
|
|
46082
|
+
let dtf = intlLFCache[key];
|
|
46252
46083
|
|
|
46253
|
-
|
|
46254
|
-
|
|
46255
|
-
|
|
46084
|
+
if (!dtf) {
|
|
46085
|
+
dtf = new Intl.ListFormat(locString, opts);
|
|
46086
|
+
intlLFCache[key] = dtf;
|
|
46087
|
+
}
|
|
46256
46088
|
|
|
46257
|
-
|
|
46258
|
-
|
|
46259
|
-
return formatOffset({
|
|
46260
|
-
format: "narrow",
|
|
46261
|
-
allowZ: this.opts.allowZ
|
|
46262
|
-
});
|
|
46089
|
+
return dtf;
|
|
46090
|
+
}
|
|
46263
46091
|
|
|
46264
|
-
|
|
46265
|
-
// like +06:00
|
|
46266
|
-
return formatOffset({
|
|
46267
|
-
format: "short",
|
|
46268
|
-
allowZ: this.opts.allowZ
|
|
46269
|
-
});
|
|
46092
|
+
let intlDTCache = {};
|
|
46270
46093
|
|
|
46271
|
-
|
|
46272
|
-
|
|
46273
|
-
|
|
46274
|
-
format: "techie",
|
|
46275
|
-
allowZ: this.opts.allowZ
|
|
46276
|
-
});
|
|
46094
|
+
function getCachedDTF(locString, opts = {}) {
|
|
46095
|
+
const key = JSON.stringify([locString, opts]);
|
|
46096
|
+
let dtf = intlDTCache[key];
|
|
46277
46097
|
|
|
46278
|
-
|
|
46279
|
-
|
|
46280
|
-
|
|
46281
|
-
|
|
46282
|
-
locale: this.loc.locale
|
|
46283
|
-
});
|
|
46098
|
+
if (!dtf) {
|
|
46099
|
+
dtf = new Intl.DateTimeFormat(locString, opts);
|
|
46100
|
+
intlDTCache[key] = dtf;
|
|
46101
|
+
}
|
|
46284
46102
|
|
|
46285
|
-
|
|
46286
|
-
|
|
46287
|
-
return dt.zone.offsetName(dt.ts, {
|
|
46288
|
-
format: "long",
|
|
46289
|
-
locale: this.loc.locale
|
|
46290
|
-
});
|
|
46291
|
-
// zone
|
|
46103
|
+
return dtf;
|
|
46104
|
+
}
|
|
46292
46105
|
|
|
46293
|
-
|
|
46294
|
-
// like America/New_York
|
|
46295
|
-
return dt.zoneName;
|
|
46296
|
-
// meridiems
|
|
46106
|
+
let intlNumCache = {};
|
|
46297
46107
|
|
|
46298
|
-
|
|
46299
|
-
|
|
46300
|
-
|
|
46108
|
+
function getCachedINF(locString, opts = {}) {
|
|
46109
|
+
const key = JSON.stringify([locString, opts]);
|
|
46110
|
+
let inf = intlNumCache[key];
|
|
46301
46111
|
|
|
46302
|
-
|
|
46303
|
-
|
|
46304
|
-
|
|
46305
|
-
|
|
46112
|
+
if (!inf) {
|
|
46113
|
+
inf = new Intl.NumberFormat(locString, opts);
|
|
46114
|
+
intlNumCache[key] = inf;
|
|
46115
|
+
}
|
|
46306
46116
|
|
|
46307
|
-
|
|
46308
|
-
|
|
46309
|
-
day: "2-digit"
|
|
46310
|
-
}, "day") : this.num(dt.day, 2);
|
|
46311
|
-
// weekdays - standalone
|
|
46117
|
+
return inf;
|
|
46118
|
+
}
|
|
46312
46119
|
|
|
46313
|
-
|
|
46314
|
-
// like 1
|
|
46315
|
-
return this.num(dt.weekday);
|
|
46120
|
+
let intlRelCache = {};
|
|
46316
46121
|
|
|
46317
|
-
|
|
46318
|
-
|
|
46319
|
-
|
|
46122
|
+
function getCachedRTF(locString, opts = {}) {
|
|
46123
|
+
const {
|
|
46124
|
+
base,
|
|
46125
|
+
...cacheKeyOpts
|
|
46126
|
+
} = opts; // exclude `base` from the options
|
|
46320
46127
|
|
|
46321
|
-
|
|
46322
|
-
|
|
46323
|
-
return weekday("long", true);
|
|
46128
|
+
const key = JSON.stringify([locString, cacheKeyOpts]);
|
|
46129
|
+
let inf = intlRelCache[key];
|
|
46324
46130
|
|
|
46325
|
-
|
|
46326
|
-
|
|
46327
|
-
|
|
46328
|
-
|
|
46131
|
+
if (!inf) {
|
|
46132
|
+
inf = new Intl.RelativeTimeFormat(locString, opts);
|
|
46133
|
+
intlRelCache[key] = inf;
|
|
46134
|
+
}
|
|
46329
46135
|
|
|
46330
|
-
|
|
46331
|
-
|
|
46332
|
-
return this.num(dt.weekday);
|
|
46136
|
+
return inf;
|
|
46137
|
+
}
|
|
46333
46138
|
|
|
46334
|
-
|
|
46335
|
-
// like 'Tues'
|
|
46336
|
-
return weekday("short", false);
|
|
46139
|
+
let sysLocaleCache = null;
|
|
46337
46140
|
|
|
46338
|
-
|
|
46339
|
-
|
|
46340
|
-
|
|
46141
|
+
function systemLocale() {
|
|
46142
|
+
if (sysLocaleCache) {
|
|
46143
|
+
return sysLocaleCache;
|
|
46144
|
+
} else {
|
|
46145
|
+
sysLocaleCache = new Intl.DateTimeFormat().resolvedOptions().locale;
|
|
46146
|
+
return sysLocaleCache;
|
|
46147
|
+
}
|
|
46148
|
+
}
|
|
46341
46149
|
|
|
46342
|
-
|
|
46343
|
-
|
|
46344
|
-
|
|
46345
|
-
|
|
46150
|
+
function parseLocaleString(localeStr) {
|
|
46151
|
+
// I really want to avoid writing a BCP 47 parser
|
|
46152
|
+
// see, e.g. https://github.com/wooorm/bcp-47
|
|
46153
|
+
// Instead, we'll do this:
|
|
46154
|
+
// a) if the string has no -u extensions, just leave it alone
|
|
46155
|
+
// b) if it does, use Intl to resolve everything
|
|
46156
|
+
// c) if Intl fails, try again without the -u
|
|
46157
|
+
const uIndex = localeStr.indexOf("-u-");
|
|
46346
46158
|
|
|
46347
|
-
|
|
46348
|
-
|
|
46349
|
-
|
|
46350
|
-
|
|
46351
|
-
|
|
46352
|
-
}, "month") : this.num(dt.month);
|
|
46159
|
+
if (uIndex === -1) {
|
|
46160
|
+
return [localeStr];
|
|
46161
|
+
} else {
|
|
46162
|
+
let options;
|
|
46163
|
+
const smaller = localeStr.substring(0, uIndex);
|
|
46353
46164
|
|
|
46354
|
-
|
|
46355
|
-
|
|
46356
|
-
|
|
46357
|
-
|
|
46358
|
-
|
|
46359
|
-
}, "month") : this.num(dt.month, 2);
|
|
46165
|
+
try {
|
|
46166
|
+
options = getCachedDTF(localeStr).resolvedOptions();
|
|
46167
|
+
} catch (e) {
|
|
46168
|
+
options = getCachedDTF(smaller).resolvedOptions();
|
|
46169
|
+
}
|
|
46360
46170
|
|
|
46361
|
-
|
|
46362
|
-
|
|
46363
|
-
|
|
46171
|
+
const {
|
|
46172
|
+
numberingSystem,
|
|
46173
|
+
calendar
|
|
46174
|
+
} = options; // return the smaller one so that we can append the calendar and numbering overrides to it
|
|
46364
46175
|
|
|
46365
|
-
|
|
46366
|
-
|
|
46367
|
-
|
|
46176
|
+
return [smaller, numberingSystem, calendar];
|
|
46177
|
+
}
|
|
46178
|
+
}
|
|
46368
46179
|
|
|
46369
|
-
|
|
46370
|
-
|
|
46371
|
-
|
|
46372
|
-
// months - format
|
|
46180
|
+
function intlConfigString(localeStr, numberingSystem, outputCalendar) {
|
|
46181
|
+
if (outputCalendar || numberingSystem) {
|
|
46182
|
+
localeStr += "-u";
|
|
46373
46183
|
|
|
46374
|
-
|
|
46375
|
-
|
|
46376
|
-
|
|
46377
|
-
month: "numeric"
|
|
46378
|
-
}, "month") : this.num(dt.month);
|
|
46184
|
+
if (outputCalendar) {
|
|
46185
|
+
localeStr += `-ca-${outputCalendar}`;
|
|
46186
|
+
}
|
|
46379
46187
|
|
|
46380
|
-
|
|
46381
|
-
|
|
46382
|
-
|
|
46383
|
-
month: "2-digit"
|
|
46384
|
-
}, "month") : this.num(dt.month, 2);
|
|
46188
|
+
if (numberingSystem) {
|
|
46189
|
+
localeStr += `-nu-${numberingSystem}`;
|
|
46190
|
+
}
|
|
46385
46191
|
|
|
46386
|
-
|
|
46387
|
-
|
|
46388
|
-
|
|
46192
|
+
return localeStr;
|
|
46193
|
+
} else {
|
|
46194
|
+
return localeStr;
|
|
46195
|
+
}
|
|
46196
|
+
}
|
|
46389
46197
|
|
|
46390
|
-
|
|
46391
|
-
|
|
46392
|
-
return month("long", false);
|
|
46198
|
+
function mapMonths(f) {
|
|
46199
|
+
const ms = [];
|
|
46393
46200
|
|
|
46394
|
-
|
|
46395
|
-
|
|
46396
|
-
|
|
46397
|
-
|
|
46201
|
+
for (let i = 1; i <= 12; i++) {
|
|
46202
|
+
const dt = DateTime.utc(2016, i, 1);
|
|
46203
|
+
ms.push(f(dt));
|
|
46204
|
+
}
|
|
46398
46205
|
|
|
46399
|
-
|
|
46400
|
-
|
|
46401
|
-
return useDateTimeFormatter ? string({
|
|
46402
|
-
year: "numeric"
|
|
46403
|
-
}, "year") : this.num(dt.year);
|
|
46206
|
+
return ms;
|
|
46207
|
+
}
|
|
46404
46208
|
|
|
46405
|
-
|
|
46406
|
-
|
|
46407
|
-
return useDateTimeFormatter ? string({
|
|
46408
|
-
year: "2-digit"
|
|
46409
|
-
}, "year") : this.num(dt.year.toString().slice(-2), 2);
|
|
46209
|
+
function mapWeekdays(f) {
|
|
46210
|
+
const ms = [];
|
|
46410
46211
|
|
|
46411
|
-
|
|
46412
|
-
|
|
46413
|
-
|
|
46414
|
-
|
|
46415
|
-
}, "year") : this.num(dt.year, 4);
|
|
46212
|
+
for (let i = 1; i <= 7; i++) {
|
|
46213
|
+
const dt = DateTime.utc(2016, 11, 13 + i);
|
|
46214
|
+
ms.push(f(dt));
|
|
46215
|
+
}
|
|
46416
46216
|
|
|
46417
|
-
|
|
46418
|
-
|
|
46419
|
-
return useDateTimeFormatter ? string({
|
|
46420
|
-
year: "numeric"
|
|
46421
|
-
}, "year") : this.num(dt.year, 6);
|
|
46422
|
-
// eras
|
|
46217
|
+
return ms;
|
|
46218
|
+
}
|
|
46423
46219
|
|
|
46424
|
-
|
|
46425
|
-
|
|
46426
|
-
return era("short");
|
|
46220
|
+
function listStuff(loc, length, defaultOK, englishFn, intlFn) {
|
|
46221
|
+
const mode = loc.listingMode(defaultOK);
|
|
46427
46222
|
|
|
46428
|
-
|
|
46429
|
-
|
|
46430
|
-
|
|
46223
|
+
if (mode === "error") {
|
|
46224
|
+
return null;
|
|
46225
|
+
} else if (mode === "en") {
|
|
46226
|
+
return englishFn(length);
|
|
46227
|
+
} else {
|
|
46228
|
+
return intlFn(length);
|
|
46229
|
+
}
|
|
46230
|
+
}
|
|
46431
46231
|
|
|
46432
|
-
|
|
46433
|
-
|
|
46434
|
-
|
|
46435
|
-
|
|
46436
|
-
|
|
46232
|
+
function supportsFastNumbers(loc) {
|
|
46233
|
+
if (loc.numberingSystem && loc.numberingSystem !== "latn") {
|
|
46234
|
+
return false;
|
|
46235
|
+
} else {
|
|
46236
|
+
return loc.numberingSystem === "latn" || !loc.locale || loc.locale.startsWith("en") || new Intl.DateTimeFormat(loc.intl).resolvedOptions().numberingSystem === "latn";
|
|
46237
|
+
}
|
|
46238
|
+
}
|
|
46239
|
+
/**
|
|
46240
|
+
* @private
|
|
46241
|
+
*/
|
|
46437
46242
|
|
|
46438
|
-
case "kkkk":
|
|
46439
|
-
return this.num(dt.weekYear, 4);
|
|
46440
46243
|
|
|
46441
|
-
|
|
46442
|
-
|
|
46244
|
+
class PolyNumberFormatter {
|
|
46245
|
+
constructor(intl, forceSimple, opts) {
|
|
46246
|
+
this.padTo = opts.padTo || 0;
|
|
46247
|
+
this.floor = opts.floor || false;
|
|
46248
|
+
const {
|
|
46249
|
+
padTo,
|
|
46250
|
+
floor,
|
|
46251
|
+
...otherOpts
|
|
46252
|
+
} = opts;
|
|
46443
46253
|
|
|
46444
|
-
|
|
46445
|
-
|
|
46254
|
+
if (!forceSimple || Object.keys(otherOpts).length > 0) {
|
|
46255
|
+
const intlOpts = {
|
|
46256
|
+
useGrouping: false,
|
|
46257
|
+
...opts
|
|
46258
|
+
};
|
|
46259
|
+
if (opts.padTo > 0) intlOpts.minimumIntegerDigits = opts.padTo;
|
|
46260
|
+
this.inf = getCachedINF(intl, intlOpts);
|
|
46261
|
+
}
|
|
46262
|
+
}
|
|
46446
46263
|
|
|
46447
|
-
|
|
46448
|
-
|
|
46264
|
+
format(i) {
|
|
46265
|
+
if (this.inf) {
|
|
46266
|
+
const fixed = this.floor ? Math.floor(i) : i;
|
|
46267
|
+
return this.inf.format(fixed);
|
|
46268
|
+
} else {
|
|
46269
|
+
// to match the browser's numberformatter defaults
|
|
46270
|
+
const fixed = this.floor ? Math.floor(i) : roundTo(i, 3);
|
|
46271
|
+
return padStart(fixed, this.padTo);
|
|
46272
|
+
}
|
|
46273
|
+
}
|
|
46449
46274
|
|
|
46450
|
-
|
|
46451
|
-
|
|
46275
|
+
}
|
|
46276
|
+
/**
|
|
46277
|
+
* @private
|
|
46278
|
+
*/
|
|
46452
46279
|
|
|
46453
|
-
case "q":
|
|
46454
|
-
// like 1
|
|
46455
|
-
return this.num(dt.quarter);
|
|
46456
46280
|
|
|
46457
|
-
|
|
46458
|
-
|
|
46459
|
-
|
|
46281
|
+
class PolyDateFormatter {
|
|
46282
|
+
constructor(dt, intl, opts) {
|
|
46283
|
+
this.opts = opts;
|
|
46284
|
+
let z;
|
|
46460
46285
|
|
|
46461
|
-
|
|
46462
|
-
|
|
46286
|
+
if (dt.zone.isUniversal) {
|
|
46287
|
+
// UTC-8 or Etc/UTC-8 are not part of tzdata, only Etc/GMT+8 and the like.
|
|
46288
|
+
// That is why fixed-offset TZ is set to that unless it is:
|
|
46289
|
+
// 1. Representing offset 0 when UTC is used to maintain previous behavior and does not become GMT.
|
|
46290
|
+
// 2. Unsupported by the browser:
|
|
46291
|
+
// - some do not support Etc/
|
|
46292
|
+
// - < Etc/GMT-14, > Etc/GMT+12, and 30-minute or 45-minute offsets are not part of tzdata
|
|
46293
|
+
const gmtOffset = -1 * (dt.offset / 60);
|
|
46294
|
+
const offsetZ = gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}`;
|
|
46463
46295
|
|
|
46464
|
-
|
|
46465
|
-
|
|
46296
|
+
if (dt.offset !== 0 && IANAZone.create(offsetZ).valid) {
|
|
46297
|
+
z = offsetZ;
|
|
46298
|
+
this.dt = dt;
|
|
46299
|
+
} else {
|
|
46300
|
+
// Not all fixed-offset zones like Etc/+4:30 are present in tzdata.
|
|
46301
|
+
// So we have to make do. Two cases:
|
|
46302
|
+
// 1. The format options tell us to show the zone. We can't do that, so the best
|
|
46303
|
+
// we can do is format the date in UTC.
|
|
46304
|
+
// 2. The format options don't tell us to show the zone. Then we can adjust them
|
|
46305
|
+
// the time and tell the formatter to show it to us in UTC, so that the time is right
|
|
46306
|
+
// and the bad zone doesn't show up.
|
|
46307
|
+
z = "UTC";
|
|
46466
46308
|
|
|
46467
|
-
|
|
46468
|
-
|
|
46309
|
+
if (opts.timeZoneName) {
|
|
46310
|
+
this.dt = dt;
|
|
46311
|
+
} else {
|
|
46312
|
+
this.dt = dt.offset === 0 ? dt : DateTime.fromMillis(dt.ts + dt.offset * 60 * 1000);
|
|
46313
|
+
}
|
|
46469
46314
|
}
|
|
46315
|
+
} else if (dt.zone.type === "system") {
|
|
46316
|
+
this.dt = dt;
|
|
46317
|
+
} else {
|
|
46318
|
+
this.dt = dt;
|
|
46319
|
+
z = dt.zone.name;
|
|
46320
|
+
}
|
|
46321
|
+
|
|
46322
|
+
const intlOpts = { ...this.opts
|
|
46470
46323
|
};
|
|
46471
46324
|
|
|
46472
|
-
|
|
46325
|
+
if (z) {
|
|
46326
|
+
intlOpts.timeZone = z;
|
|
46327
|
+
}
|
|
46328
|
+
|
|
46329
|
+
this.dtf = getCachedDTF(intl, intlOpts);
|
|
46473
46330
|
}
|
|
46474
46331
|
|
|
46475
|
-
|
|
46476
|
-
|
|
46477
|
-
|
|
46478
|
-
case "S":
|
|
46479
|
-
return "millisecond";
|
|
46332
|
+
format() {
|
|
46333
|
+
return this.dtf.format(this.dt.toJSDate());
|
|
46334
|
+
}
|
|
46480
46335
|
|
|
46481
|
-
|
|
46482
|
-
|
|
46336
|
+
formatToParts() {
|
|
46337
|
+
return this.dtf.formatToParts(this.dt.toJSDate());
|
|
46338
|
+
}
|
|
46483
46339
|
|
|
46484
|
-
|
|
46485
|
-
|
|
46340
|
+
resolvedOptions() {
|
|
46341
|
+
return this.dtf.resolvedOptions();
|
|
46342
|
+
}
|
|
46486
46343
|
|
|
46487
|
-
|
|
46488
|
-
|
|
46344
|
+
}
|
|
46345
|
+
/**
|
|
46346
|
+
* @private
|
|
46347
|
+
*/
|
|
46489
46348
|
|
|
46490
|
-
case "d":
|
|
46491
|
-
return "day";
|
|
46492
46349
|
|
|
46493
|
-
|
|
46494
|
-
|
|
46350
|
+
class PolyRelFormatter {
|
|
46351
|
+
constructor(intl, isEnglish, opts) {
|
|
46352
|
+
this.opts = {
|
|
46353
|
+
style: "long",
|
|
46354
|
+
...opts
|
|
46355
|
+
};
|
|
46495
46356
|
|
|
46496
|
-
|
|
46497
|
-
|
|
46357
|
+
if (!isEnglish && hasRelative()) {
|
|
46358
|
+
this.rtf = getCachedRTF(intl, opts);
|
|
46359
|
+
}
|
|
46360
|
+
}
|
|
46498
46361
|
|
|
46499
|
-
|
|
46500
|
-
|
|
46362
|
+
format(count, unit) {
|
|
46363
|
+
if (this.rtf) {
|
|
46364
|
+
return this.rtf.format(count, unit);
|
|
46365
|
+
} else {
|
|
46366
|
+
return formatRelativeTime(unit, count, this.opts.numeric, this.opts.style !== "long");
|
|
46367
|
+
}
|
|
46368
|
+
}
|
|
46501
46369
|
|
|
46502
|
-
|
|
46503
|
-
|
|
46504
|
-
|
|
46505
|
-
}
|
|
46506
|
-
|
|
46507
|
-
|
|
46370
|
+
formatToParts(count, unit) {
|
|
46371
|
+
if (this.rtf) {
|
|
46372
|
+
return this.rtf.formatToParts(count, unit);
|
|
46373
|
+
} else {
|
|
46374
|
+
return [];
|
|
46375
|
+
}
|
|
46376
|
+
}
|
|
46508
46377
|
|
|
46509
|
-
|
|
46510
|
-
|
|
46511
|
-
|
|
46512
|
-
|
|
46513
|
-
}
|
|
46514
|
-
},
|
|
46515
|
-
tokens = Formatter.parseFormat(fmt),
|
|
46516
|
-
realTokens = tokens.reduce((found, {
|
|
46517
|
-
literal,
|
|
46518
|
-
val
|
|
46519
|
-
}) => literal ? found : found.concat(val), []),
|
|
46520
|
-
collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter(t => t));
|
|
46378
|
+
}
|
|
46379
|
+
/**
|
|
46380
|
+
* @private
|
|
46381
|
+
*/
|
|
46521
46382
|
|
|
46522
|
-
|
|
46383
|
+
|
|
46384
|
+
class Locale {
|
|
46385
|
+
static fromOpts(opts) {
|
|
46386
|
+
return Locale.create(opts.locale, opts.numberingSystem, opts.outputCalendar, opts.defaultToEN);
|
|
46523
46387
|
}
|
|
46524
46388
|
|
|
46525
|
-
|
|
46389
|
+
static create(locale, numberingSystem, outputCalendar, defaultToEN = false) {
|
|
46390
|
+
const specifiedLocale = locale || Settings.defaultLocale; // the system locale is useful for human readable strings but annoying for parsing/formatting known formats
|
|
46526
46391
|
|
|
46527
|
-
|
|
46528
|
-
|
|
46529
|
-
|
|
46530
|
-
|
|
46392
|
+
const localeR = specifiedLocale || (defaultToEN ? "en-US" : systemLocale());
|
|
46393
|
+
const numberingSystemR = numberingSystem || Settings.defaultNumberingSystem;
|
|
46394
|
+
const outputCalendarR = outputCalendar || Settings.defaultOutputCalendar;
|
|
46395
|
+
return new Locale(localeR, numberingSystemR, outputCalendarR, specifiedLocale);
|
|
46531
46396
|
}
|
|
46532
46397
|
|
|
46533
|
-
|
|
46534
|
-
|
|
46535
|
-
|
|
46536
|
-
|
|
46537
|
-
|
|
46538
|
-
}
|
|
46398
|
+
static resetCache() {
|
|
46399
|
+
sysLocaleCache = null;
|
|
46400
|
+
intlDTCache = {};
|
|
46401
|
+
intlNumCache = {};
|
|
46402
|
+
intlRelCache = {};
|
|
46539
46403
|
}
|
|
46540
46404
|
|
|
46541
|
-
|
|
46405
|
+
static fromObject({
|
|
46406
|
+
locale,
|
|
46407
|
+
numberingSystem,
|
|
46408
|
+
outputCalendar
|
|
46409
|
+
} = {}) {
|
|
46410
|
+
return Locale.create(locale, numberingSystem, outputCalendar);
|
|
46411
|
+
}
|
|
46542
46412
|
|
|
46543
|
-
|
|
46544
|
-
|
|
46545
|
-
|
|
46413
|
+
constructor(locale, numbering, outputCalendar, specifiedLocale) {
|
|
46414
|
+
const [parsedLocale, parsedNumberingSystem, parsedOutputCalendar] = parseLocaleString(locale);
|
|
46415
|
+
this.locale = parsedLocale;
|
|
46416
|
+
this.numberingSystem = numbering || parsedNumberingSystem || null;
|
|
46417
|
+
this.outputCalendar = outputCalendar || parsedOutputCalendar || null;
|
|
46418
|
+
this.intl = intlConfigString(this.locale, this.numberingSystem, this.outputCalendar);
|
|
46419
|
+
this.weekdaysCache = {
|
|
46420
|
+
format: {},
|
|
46421
|
+
standalone: {}
|
|
46422
|
+
};
|
|
46423
|
+
this.monthsCache = {
|
|
46424
|
+
format: {},
|
|
46425
|
+
standalone: {}
|
|
46426
|
+
};
|
|
46427
|
+
this.meridiemCache = null;
|
|
46428
|
+
this.eraCache = {};
|
|
46429
|
+
this.specifiedLocale = specifiedLocale;
|
|
46430
|
+
this.fastNumbersCached = null;
|
|
46431
|
+
}
|
|
46546
46432
|
|
|
46547
|
-
|
|
46548
|
-
|
|
46549
|
-
|
|
46550
|
-
|
|
46551
|
-
|
|
46552
|
-
|
|
46553
|
-
get type() {
|
|
46554
|
-
throw new ZoneIsAbstractError();
|
|
46433
|
+
get fastNumbers() {
|
|
46434
|
+
if (this.fastNumbersCached == null) {
|
|
46435
|
+
this.fastNumbersCached = supportsFastNumbers(this);
|
|
46436
|
+
}
|
|
46437
|
+
|
|
46438
|
+
return this.fastNumbersCached;
|
|
46555
46439
|
}
|
|
46556
|
-
/**
|
|
46557
|
-
* The name of this zone.
|
|
46558
|
-
* @abstract
|
|
46559
|
-
* @type {string}
|
|
46560
|
-
*/
|
|
46561
46440
|
|
|
46441
|
+
listingMode() {
|
|
46442
|
+
const isActuallyEn = this.isEnglish();
|
|
46443
|
+
const hasNoWeirdness = (this.numberingSystem === null || this.numberingSystem === "latn") && (this.outputCalendar === null || this.outputCalendar === "gregory");
|
|
46444
|
+
return isActuallyEn && hasNoWeirdness ? "en" : "intl";
|
|
46445
|
+
}
|
|
46562
46446
|
|
|
46563
|
-
|
|
46564
|
-
|
|
46447
|
+
clone(alts) {
|
|
46448
|
+
if (!alts || Object.getOwnPropertyNames(alts).length === 0) {
|
|
46449
|
+
return this;
|
|
46450
|
+
} else {
|
|
46451
|
+
return Locale.create(alts.locale || this.specifiedLocale, alts.numberingSystem || this.numberingSystem, alts.outputCalendar || this.outputCalendar, alts.defaultToEN || false);
|
|
46452
|
+
}
|
|
46565
46453
|
}
|
|
46566
46454
|
|
|
46567
|
-
|
|
46568
|
-
return this.
|
|
46455
|
+
redefaultToEN(alts = {}) {
|
|
46456
|
+
return this.clone({ ...alts,
|
|
46457
|
+
defaultToEN: true
|
|
46458
|
+
});
|
|
46569
46459
|
}
|
|
46570
|
-
/**
|
|
46571
|
-
* Returns whether the offset is known to be fixed for the whole year.
|
|
46572
|
-
* @abstract
|
|
46573
|
-
* @type {boolean}
|
|
46574
|
-
*/
|
|
46575
46460
|
|
|
46461
|
+
redefaultToSystem(alts = {}) {
|
|
46462
|
+
return this.clone({ ...alts,
|
|
46463
|
+
defaultToEN: false
|
|
46464
|
+
});
|
|
46465
|
+
}
|
|
46576
46466
|
|
|
46577
|
-
|
|
46578
|
-
|
|
46467
|
+
months(length, format = false, defaultOK = true) {
|
|
46468
|
+
return listStuff(this, length, defaultOK, months, () => {
|
|
46469
|
+
const intl = format ? {
|
|
46470
|
+
month: length,
|
|
46471
|
+
day: "numeric"
|
|
46472
|
+
} : {
|
|
46473
|
+
month: length
|
|
46474
|
+
},
|
|
46475
|
+
formatStr = format ? "format" : "standalone";
|
|
46476
|
+
|
|
46477
|
+
if (!this.monthsCache[formatStr][length]) {
|
|
46478
|
+
this.monthsCache[formatStr][length] = mapMonths(dt => this.extract(dt, intl, "month"));
|
|
46479
|
+
}
|
|
46480
|
+
|
|
46481
|
+
return this.monthsCache[formatStr][length];
|
|
46482
|
+
});
|
|
46579
46483
|
}
|
|
46580
|
-
/**
|
|
46581
|
-
* Returns the offset's common name (such as EST) at the specified timestamp
|
|
46582
|
-
* @abstract
|
|
46583
|
-
* @param {number} ts - Epoch milliseconds for which to get the name
|
|
46584
|
-
* @param {Object} opts - Options to affect the format
|
|
46585
|
-
* @param {string} opts.format - What style of offset to return. Accepts 'long' or 'short'.
|
|
46586
|
-
* @param {string} opts.locale - What locale to return the offset name in.
|
|
46587
|
-
* @return {string}
|
|
46588
|
-
*/
|
|
46589
46484
|
|
|
46485
|
+
weekdays(length, format = false, defaultOK = true) {
|
|
46486
|
+
return listStuff(this, length, defaultOK, weekdays, () => {
|
|
46487
|
+
const intl = format ? {
|
|
46488
|
+
weekday: length,
|
|
46489
|
+
year: "numeric",
|
|
46490
|
+
month: "long",
|
|
46491
|
+
day: "numeric"
|
|
46492
|
+
} : {
|
|
46493
|
+
weekday: length
|
|
46494
|
+
},
|
|
46495
|
+
formatStr = format ? "format" : "standalone";
|
|
46590
46496
|
|
|
46591
|
-
|
|
46592
|
-
|
|
46497
|
+
if (!this.weekdaysCache[formatStr][length]) {
|
|
46498
|
+
this.weekdaysCache[formatStr][length] = mapWeekdays(dt => this.extract(dt, intl, "weekday"));
|
|
46499
|
+
}
|
|
46500
|
+
|
|
46501
|
+
return this.weekdaysCache[formatStr][length];
|
|
46502
|
+
});
|
|
46593
46503
|
}
|
|
46594
|
-
/**
|
|
46595
|
-
* Returns the offset's value as a string
|
|
46596
|
-
* @abstract
|
|
46597
|
-
* @param {number} ts - Epoch milliseconds for which to get the offset
|
|
46598
|
-
* @param {string} format - What style of offset to return.
|
|
46599
|
-
* Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively
|
|
46600
|
-
* @return {string}
|
|
46601
|
-
*/
|
|
46602
46504
|
|
|
46505
|
+
meridiems(defaultOK = true) {
|
|
46506
|
+
return listStuff(this, undefined, defaultOK, () => meridiems, () => {
|
|
46507
|
+
// In theory there could be aribitrary day periods. We're gonna assume there are exactly two
|
|
46508
|
+
// for AM and PM. This is probably wrong, but it's makes parsing way easier.
|
|
46509
|
+
if (!this.meridiemCache) {
|
|
46510
|
+
const intl = {
|
|
46511
|
+
hour: "numeric",
|
|
46512
|
+
hourCycle: "h12"
|
|
46513
|
+
};
|
|
46514
|
+
this.meridiemCache = [DateTime.utc(2016, 11, 13, 9), DateTime.utc(2016, 11, 13, 19)].map(dt => this.extract(dt, intl, "dayperiod"));
|
|
46515
|
+
}
|
|
46603
46516
|
|
|
46604
|
-
|
|
46605
|
-
|
|
46517
|
+
return this.meridiemCache;
|
|
46518
|
+
});
|
|
46606
46519
|
}
|
|
46607
|
-
/**
|
|
46608
|
-
* Return the offset in minutes for this zone at the specified timestamp.
|
|
46609
|
-
* @abstract
|
|
46610
|
-
* @param {number} ts - Epoch milliseconds for which to compute the offset
|
|
46611
|
-
* @return {number}
|
|
46612
|
-
*/
|
|
46613
46520
|
|
|
46521
|
+
eras(length, defaultOK = true) {
|
|
46522
|
+
return listStuff(this, length, defaultOK, eras, () => {
|
|
46523
|
+
const intl = {
|
|
46524
|
+
era: length
|
|
46525
|
+
}; // This is problematic. Different calendars are going to define eras totally differently. What I need is the minimum set of dates
|
|
46526
|
+
// to definitely enumerate them.
|
|
46614
46527
|
|
|
46615
|
-
|
|
46616
|
-
|
|
46528
|
+
if (!this.eraCache[length]) {
|
|
46529
|
+
this.eraCache[length] = [DateTime.utc(-40, 1, 1), DateTime.utc(2017, 1, 1)].map(dt => this.extract(dt, intl, "era"));
|
|
46530
|
+
}
|
|
46531
|
+
|
|
46532
|
+
return this.eraCache[length];
|
|
46533
|
+
});
|
|
46617
46534
|
}
|
|
46618
|
-
/**
|
|
46619
|
-
* Return whether this Zone is equal to another zone
|
|
46620
|
-
* @abstract
|
|
46621
|
-
* @param {Zone} otherZone - the zone to compare
|
|
46622
|
-
* @return {boolean}
|
|
46623
|
-
*/
|
|
46624
46535
|
|
|
46536
|
+
extract(dt, intlOpts, field) {
|
|
46537
|
+
const df = this.dtFormatter(dt, intlOpts),
|
|
46538
|
+
results = df.formatToParts(),
|
|
46539
|
+
matching = results.find(m => m.type.toLowerCase() === field);
|
|
46540
|
+
return matching ? matching.value : null;
|
|
46541
|
+
}
|
|
46625
46542
|
|
|
46626
|
-
|
|
46627
|
-
|
|
46543
|
+
numberFormatter(opts = {}) {
|
|
46544
|
+
// this forcesimple option is never used (the only caller short-circuits on it, but it seems safer to leave)
|
|
46545
|
+
// (in contrast, the rest of the condition is used heavily)
|
|
46546
|
+
return new PolyNumberFormatter(this.intl, opts.forceSimple || this.fastNumbers, opts);
|
|
46547
|
+
}
|
|
46548
|
+
|
|
46549
|
+
dtFormatter(dt, intlOpts = {}) {
|
|
46550
|
+
return new PolyDateFormatter(dt, this.intl, intlOpts);
|
|
46628
46551
|
}
|
|
46629
|
-
/**
|
|
46630
|
-
* Return whether this Zone is valid.
|
|
46631
|
-
* @abstract
|
|
46632
|
-
* @type {boolean}
|
|
46633
|
-
*/
|
|
46634
46552
|
|
|
46553
|
+
relFormatter(opts = {}) {
|
|
46554
|
+
return new PolyRelFormatter(this.intl, this.isEnglish(), opts);
|
|
46555
|
+
}
|
|
46635
46556
|
|
|
46636
|
-
|
|
46637
|
-
|
|
46557
|
+
listFormatter(opts = {}) {
|
|
46558
|
+
return getCachedLF(this.intl, opts);
|
|
46559
|
+
}
|
|
46560
|
+
|
|
46561
|
+
isEnglish() {
|
|
46562
|
+
return this.locale === "en" || this.locale.toLowerCase() === "en-us" || new Intl.DateTimeFormat(this.intl).resolvedOptions().locale.startsWith("en-us");
|
|
46563
|
+
}
|
|
46564
|
+
|
|
46565
|
+
equals(other) {
|
|
46566
|
+
return this.locale === other.locale && this.numberingSystem === other.numberingSystem && this.outputCalendar === other.outputCalendar;
|
|
46638
46567
|
}
|
|
46639
46568
|
|
|
46640
46569
|
}
|
|
46641
46570
|
|
|
46642
|
-
let singleton
|
|
46571
|
+
let singleton = null;
|
|
46643
46572
|
/**
|
|
46644
|
-
*
|
|
46573
|
+
* A zone with a fixed offset (meaning no DST)
|
|
46645
46574
|
* @implements {Zone}
|
|
46646
46575
|
*/
|
|
46647
46576
|
|
|
46648
|
-
class
|
|
46577
|
+
class FixedOffsetZone extends Zone {
|
|
46649
46578
|
/**
|
|
46650
|
-
* Get a singleton instance of
|
|
46651
|
-
* @return {
|
|
46579
|
+
* Get a singleton instance of UTC
|
|
46580
|
+
* @return {FixedOffsetZone}
|
|
46652
46581
|
*/
|
|
46653
|
-
static get
|
|
46654
|
-
if (singleton
|
|
46655
|
-
singleton
|
|
46582
|
+
static get utcInstance() {
|
|
46583
|
+
if (singleton === null) {
|
|
46584
|
+
singleton = new FixedOffsetZone(0);
|
|
46656
46585
|
}
|
|
46657
46586
|
|
|
46658
|
-
return singleton
|
|
46587
|
+
return singleton;
|
|
46659
46588
|
}
|
|
46660
|
-
/**
|
|
46589
|
+
/**
|
|
46590
|
+
* Get an instance with a specified offset
|
|
46591
|
+
* @param {number} offset - The offset in minutes
|
|
46592
|
+
* @return {FixedOffsetZone}
|
|
46593
|
+
*/
|
|
46661
46594
|
|
|
46662
46595
|
|
|
46663
|
-
|
|
46664
|
-
return
|
|
46596
|
+
static instance(offset) {
|
|
46597
|
+
return offset === 0 ? FixedOffsetZone.utcInstance : new FixedOffsetZone(offset);
|
|
46665
46598
|
}
|
|
46666
|
-
/**
|
|
46599
|
+
/**
|
|
46600
|
+
* Get an instance of FixedOffsetZone from a UTC offset string, like "UTC+6"
|
|
46601
|
+
* @param {string} s - The offset string to parse
|
|
46602
|
+
* @example FixedOffsetZone.parseSpecifier("UTC+6")
|
|
46603
|
+
* @example FixedOffsetZone.parseSpecifier("UTC+06")
|
|
46604
|
+
* @example FixedOffsetZone.parseSpecifier("UTC-6:00")
|
|
46605
|
+
* @return {FixedOffsetZone}
|
|
46606
|
+
*/
|
|
46667
46607
|
|
|
46668
46608
|
|
|
46669
|
-
|
|
46670
|
-
|
|
46609
|
+
static parseSpecifier(s) {
|
|
46610
|
+
if (s) {
|
|
46611
|
+
const r = s.match(/^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$/i);
|
|
46612
|
+
|
|
46613
|
+
if (r) {
|
|
46614
|
+
return new FixedOffsetZone(signedOffset(r[1], r[2]));
|
|
46615
|
+
}
|
|
46616
|
+
}
|
|
46617
|
+
|
|
46618
|
+
return null;
|
|
46671
46619
|
}
|
|
46672
|
-
/** @override **/
|
|
46673
46620
|
|
|
46621
|
+
constructor(offset) {
|
|
46622
|
+
super();
|
|
46623
|
+
/** @private **/
|
|
46674
46624
|
|
|
46675
|
-
|
|
46676
|
-
return false;
|
|
46625
|
+
this.fixed = offset;
|
|
46677
46626
|
}
|
|
46678
46627
|
/** @override **/
|
|
46679
46628
|
|
|
46680
46629
|
|
|
46681
|
-
|
|
46682
|
-
|
|
46683
|
-
locale
|
|
46684
|
-
}) {
|
|
46685
|
-
return parseZoneInfo(ts, format, locale);
|
|
46630
|
+
get type() {
|
|
46631
|
+
return "fixed";
|
|
46686
46632
|
}
|
|
46687
46633
|
/** @override **/
|
|
46688
46634
|
|
|
46689
46635
|
|
|
46690
|
-
|
|
46691
|
-
return formatOffset(this.
|
|
46636
|
+
get name() {
|
|
46637
|
+
return this.fixed === 0 ? "UTC" : `UTC${formatOffset(this.fixed, "narrow")}`;
|
|
46638
|
+
}
|
|
46639
|
+
|
|
46640
|
+
get ianaName() {
|
|
46641
|
+
if (this.fixed === 0) {
|
|
46642
|
+
return "Etc/UTC";
|
|
46643
|
+
} else {
|
|
46644
|
+
return `Etc/GMT${formatOffset(-this.fixed, "narrow")}`;
|
|
46645
|
+
}
|
|
46692
46646
|
}
|
|
46693
46647
|
/** @override **/
|
|
46694
46648
|
|
|
46695
46649
|
|
|
46696
|
-
|
|
46697
|
-
return
|
|
46650
|
+
offsetName() {
|
|
46651
|
+
return this.name;
|
|
46698
46652
|
}
|
|
46699
46653
|
/** @override **/
|
|
46700
46654
|
|
|
46701
46655
|
|
|
46702
|
-
|
|
46703
|
-
return
|
|
46656
|
+
formatOffset(ts, format) {
|
|
46657
|
+
return formatOffset(this.fixed, format);
|
|
46704
46658
|
}
|
|
46705
46659
|
/** @override **/
|
|
46706
46660
|
|
|
46707
46661
|
|
|
46708
|
-
get
|
|
46662
|
+
get isUniversal() {
|
|
46709
46663
|
return true;
|
|
46710
46664
|
}
|
|
46711
|
-
|
|
46712
|
-
}
|
|
46713
|
-
|
|
46714
|
-
let dtfCache = {};
|
|
46715
|
-
|
|
46716
|
-
function makeDTF(zone) {
|
|
46717
|
-
if (!dtfCache[zone]) {
|
|
46718
|
-
dtfCache[zone] = new Intl.DateTimeFormat("en-US", {
|
|
46719
|
-
hour12: false,
|
|
46720
|
-
timeZone: zone,
|
|
46721
|
-
year: "numeric",
|
|
46722
|
-
month: "2-digit",
|
|
46723
|
-
day: "2-digit",
|
|
46724
|
-
hour: "2-digit",
|
|
46725
|
-
minute: "2-digit",
|
|
46726
|
-
second: "2-digit",
|
|
46727
|
-
era: "short"
|
|
46728
|
-
});
|
|
46729
|
-
}
|
|
46730
|
-
|
|
46731
|
-
return dtfCache[zone];
|
|
46732
|
-
}
|
|
46733
|
-
|
|
46734
|
-
const typeToPos = {
|
|
46735
|
-
year: 0,
|
|
46736
|
-
month: 1,
|
|
46737
|
-
day: 2,
|
|
46738
|
-
era: 3,
|
|
46739
|
-
hour: 4,
|
|
46740
|
-
minute: 5,
|
|
46741
|
-
second: 6
|
|
46742
|
-
};
|
|
46743
|
-
|
|
46744
|
-
function hackyOffset(dtf, date) {
|
|
46745
|
-
const formatted = dtf.format(date).replace(/\u200E/g, ""),
|
|
46746
|
-
parsed = /(\d+)\/(\d+)\/(\d+) (AD|BC),? (\d+):(\d+):(\d+)/.exec(formatted),
|
|
46747
|
-
[, fMonth, fDay, fYear, fadOrBc, fHour, fMinute, fSecond] = parsed;
|
|
46748
|
-
return [fYear, fMonth, fDay, fadOrBc, fHour, fMinute, fSecond];
|
|
46749
|
-
}
|
|
46750
|
-
|
|
46751
|
-
function partsOffset(dtf, date) {
|
|
46752
|
-
const formatted = dtf.formatToParts(date);
|
|
46753
|
-
const filled = [];
|
|
46754
|
-
|
|
46755
|
-
for (let i = 0; i < formatted.length; i++) {
|
|
46756
|
-
const {
|
|
46757
|
-
type,
|
|
46758
|
-
value
|
|
46759
|
-
} = formatted[i];
|
|
46760
|
-
const pos = typeToPos[type];
|
|
46761
|
-
|
|
46762
|
-
if (type === "era") {
|
|
46763
|
-
filled[pos] = value;
|
|
46764
|
-
} else if (!isUndefined(pos)) {
|
|
46765
|
-
filled[pos] = parseInt(value, 10);
|
|
46766
|
-
}
|
|
46767
|
-
}
|
|
46768
|
-
|
|
46769
|
-
return filled;
|
|
46770
|
-
}
|
|
46771
|
-
|
|
46772
|
-
let ianaZoneCache = {};
|
|
46773
|
-
/**
|
|
46774
|
-
* A zone identified by an IANA identifier, like America/New_York
|
|
46775
|
-
* @implements {Zone}
|
|
46776
|
-
*/
|
|
46777
|
-
|
|
46778
|
-
class IANAZone extends Zone {
|
|
46779
|
-
/**
|
|
46780
|
-
* @param {string} name - Zone name
|
|
46781
|
-
* @return {IANAZone}
|
|
46782
|
-
*/
|
|
46783
|
-
static create(name) {
|
|
46784
|
-
if (!ianaZoneCache[name]) {
|
|
46785
|
-
ianaZoneCache[name] = new IANAZone(name);
|
|
46786
|
-
}
|
|
46787
|
-
|
|
46788
|
-
return ianaZoneCache[name];
|
|
46789
|
-
}
|
|
46790
|
-
/**
|
|
46791
|
-
* Reset local caches. Should only be necessary in testing scenarios.
|
|
46792
|
-
* @return {void}
|
|
46793
|
-
*/
|
|
46794
|
-
|
|
46795
|
-
|
|
46796
|
-
static resetCache() {
|
|
46797
|
-
ianaZoneCache = {};
|
|
46798
|
-
dtfCache = {};
|
|
46799
|
-
}
|
|
46800
|
-
/**
|
|
46801
|
-
* Returns whether the provided string is a valid specifier. This only checks the string's format, not that the specifier identifies a known zone; see isValidZone for that.
|
|
46802
|
-
* @param {string} s - The string to check validity on
|
|
46803
|
-
* @example IANAZone.isValidSpecifier("America/New_York") //=> true
|
|
46804
|
-
* @example IANAZone.isValidSpecifier("Sport~~blorp") //=> false
|
|
46805
|
-
* @deprecated This method returns false for some valid IANA names. Use isValidZone instead.
|
|
46806
|
-
* @return {boolean}
|
|
46807
|
-
*/
|
|
46808
|
-
|
|
46809
|
-
|
|
46810
|
-
static isValidSpecifier(s) {
|
|
46811
|
-
return this.isValidZone(s);
|
|
46812
|
-
}
|
|
46813
|
-
/**
|
|
46814
|
-
* Returns whether the provided string identifies a real zone
|
|
46815
|
-
* @param {string} zone - The string to check
|
|
46816
|
-
* @example IANAZone.isValidZone("America/New_York") //=> true
|
|
46817
|
-
* @example IANAZone.isValidZone("Fantasia/Castle") //=> false
|
|
46818
|
-
* @example IANAZone.isValidZone("Sport~~blorp") //=> false
|
|
46819
|
-
* @return {boolean}
|
|
46820
|
-
*/
|
|
46821
|
-
|
|
46822
|
-
|
|
46823
|
-
static isValidZone(zone) {
|
|
46824
|
-
if (!zone) {
|
|
46825
|
-
return false;
|
|
46826
|
-
}
|
|
46827
|
-
|
|
46828
|
-
try {
|
|
46829
|
-
new Intl.DateTimeFormat("en-US", {
|
|
46830
|
-
timeZone: zone
|
|
46831
|
-
}).format();
|
|
46832
|
-
return true;
|
|
46833
|
-
} catch (e) {
|
|
46834
|
-
return false;
|
|
46835
|
-
}
|
|
46836
|
-
}
|
|
46837
|
-
|
|
46838
|
-
constructor(name) {
|
|
46839
|
-
super();
|
|
46840
|
-
/** @private **/
|
|
46841
|
-
|
|
46842
|
-
this.zoneName = name;
|
|
46843
|
-
/** @private **/
|
|
46844
|
-
|
|
46845
|
-
this.valid = IANAZone.isValidZone(name);
|
|
46846
|
-
}
|
|
46847
|
-
/** @override **/
|
|
46848
|
-
|
|
46849
|
-
|
|
46850
|
-
get type() {
|
|
46851
|
-
return "iana";
|
|
46852
|
-
}
|
|
46853
|
-
/** @override **/
|
|
46854
|
-
|
|
46855
|
-
|
|
46856
|
-
get name() {
|
|
46857
|
-
return this.zoneName;
|
|
46858
|
-
}
|
|
46859
|
-
/** @override **/
|
|
46860
|
-
|
|
46861
|
-
|
|
46862
|
-
get isUniversal() {
|
|
46863
|
-
return false;
|
|
46864
|
-
}
|
|
46865
|
-
/** @override **/
|
|
46866
|
-
|
|
46867
|
-
|
|
46868
|
-
offsetName(ts, {
|
|
46869
|
-
format,
|
|
46870
|
-
locale
|
|
46871
|
-
}) {
|
|
46872
|
-
return parseZoneInfo(ts, format, locale, this.name);
|
|
46873
|
-
}
|
|
46874
|
-
/** @override **/
|
|
46875
|
-
|
|
46876
|
-
|
|
46877
|
-
formatOffset(ts, format) {
|
|
46878
|
-
return formatOffset(this.offset(ts), format);
|
|
46879
|
-
}
|
|
46880
|
-
/** @override **/
|
|
46881
|
-
|
|
46882
|
-
|
|
46883
|
-
offset(ts) {
|
|
46884
|
-
const date = new Date(ts);
|
|
46885
|
-
if (isNaN(date)) return NaN;
|
|
46886
|
-
const dtf = makeDTF(this.name);
|
|
46887
|
-
let [year, month, day, adOrBc, hour, minute, second] = dtf.formatToParts ? partsOffset(dtf, date) : hackyOffset(dtf, date);
|
|
46888
|
-
|
|
46889
|
-
if (adOrBc === "BC") {
|
|
46890
|
-
year = -Math.abs(year) + 1;
|
|
46891
|
-
} // because we're using hour12 and https://bugs.chromium.org/p/chromium/issues/detail?id=1025564&can=2&q=%2224%3A00%22%20datetimeformat
|
|
46892
|
-
|
|
46893
|
-
|
|
46894
|
-
const adjustedHour = hour === 24 ? 0 : hour;
|
|
46895
|
-
const asUTC = objToLocalTS({
|
|
46896
|
-
year,
|
|
46897
|
-
month,
|
|
46898
|
-
day,
|
|
46899
|
-
hour: adjustedHour,
|
|
46900
|
-
minute,
|
|
46901
|
-
second,
|
|
46902
|
-
millisecond: 0
|
|
46903
|
-
});
|
|
46904
|
-
let asTS = +date;
|
|
46905
|
-
const over = asTS % 1000;
|
|
46906
|
-
asTS -= over >= 0 ? over : 1000 + over;
|
|
46907
|
-
return (asUTC - asTS) / (60 * 1000);
|
|
46908
|
-
}
|
|
46909
|
-
/** @override **/
|
|
46910
|
-
|
|
46911
|
-
|
|
46912
|
-
equals(otherZone) {
|
|
46913
|
-
return otherZone.type === "iana" && otherZone.name === this.name;
|
|
46914
|
-
}
|
|
46915
|
-
/** @override **/
|
|
46916
|
-
|
|
46917
|
-
|
|
46918
|
-
get isValid() {
|
|
46919
|
-
return this.valid;
|
|
46920
|
-
}
|
|
46921
|
-
|
|
46922
|
-
}
|
|
46923
|
-
|
|
46924
|
-
let singleton = null;
|
|
46925
|
-
/**
|
|
46926
|
-
* A zone with a fixed offset (meaning no DST)
|
|
46927
|
-
* @implements {Zone}
|
|
46928
|
-
*/
|
|
46929
|
-
|
|
46930
|
-
class FixedOffsetZone extends Zone {
|
|
46931
|
-
/**
|
|
46932
|
-
* Get a singleton instance of UTC
|
|
46933
|
-
* @return {FixedOffsetZone}
|
|
46934
|
-
*/
|
|
46935
|
-
static get utcInstance() {
|
|
46936
|
-
if (singleton === null) {
|
|
46937
|
-
singleton = new FixedOffsetZone(0);
|
|
46938
|
-
}
|
|
46939
|
-
|
|
46940
|
-
return singleton;
|
|
46941
|
-
}
|
|
46942
|
-
/**
|
|
46943
|
-
* Get an instance with a specified offset
|
|
46944
|
-
* @param {number} offset - The offset in minutes
|
|
46945
|
-
* @return {FixedOffsetZone}
|
|
46946
|
-
*/
|
|
46947
|
-
|
|
46948
|
-
|
|
46949
|
-
static instance(offset) {
|
|
46950
|
-
return offset === 0 ? FixedOffsetZone.utcInstance : new FixedOffsetZone(offset);
|
|
46951
|
-
}
|
|
46952
|
-
/**
|
|
46953
|
-
* Get an instance of FixedOffsetZone from a UTC offset string, like "UTC+6"
|
|
46954
|
-
* @param {string} s - The offset string to parse
|
|
46955
|
-
* @example FixedOffsetZone.parseSpecifier("UTC+6")
|
|
46956
|
-
* @example FixedOffsetZone.parseSpecifier("UTC+06")
|
|
46957
|
-
* @example FixedOffsetZone.parseSpecifier("UTC-6:00")
|
|
46958
|
-
* @return {FixedOffsetZone}
|
|
46959
|
-
*/
|
|
46960
|
-
|
|
46961
|
-
|
|
46962
|
-
static parseSpecifier(s) {
|
|
46963
|
-
if (s) {
|
|
46964
|
-
const r = s.match(/^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$/i);
|
|
46965
|
-
|
|
46966
|
-
if (r) {
|
|
46967
|
-
return new FixedOffsetZone(signedOffset(r[1], r[2]));
|
|
46968
|
-
}
|
|
46969
|
-
}
|
|
46970
|
-
|
|
46971
|
-
return null;
|
|
46972
|
-
}
|
|
46973
|
-
|
|
46974
|
-
constructor(offset) {
|
|
46975
|
-
super();
|
|
46976
|
-
/** @private **/
|
|
46977
|
-
|
|
46978
|
-
this.fixed = offset;
|
|
46979
|
-
}
|
|
46980
|
-
/** @override **/
|
|
46981
|
-
|
|
46982
|
-
|
|
46983
|
-
get type() {
|
|
46984
|
-
return "fixed";
|
|
46985
|
-
}
|
|
46986
|
-
/** @override **/
|
|
46987
|
-
|
|
46988
|
-
|
|
46989
|
-
get name() {
|
|
46990
|
-
return this.fixed === 0 ? "UTC" : `UTC${formatOffset(this.fixed, "narrow")}`;
|
|
46991
|
-
}
|
|
46992
|
-
|
|
46993
|
-
get ianaName() {
|
|
46994
|
-
if (this.fixed === 0) {
|
|
46995
|
-
return "Etc/UTC";
|
|
46996
|
-
} else {
|
|
46997
|
-
return `Etc/GMT${formatOffset(-this.fixed, "narrow")}`;
|
|
46998
|
-
}
|
|
46999
|
-
}
|
|
47000
|
-
/** @override **/
|
|
47001
|
-
|
|
47002
|
-
|
|
47003
|
-
offsetName() {
|
|
47004
|
-
return this.name;
|
|
47005
|
-
}
|
|
47006
|
-
/** @override **/
|
|
47007
|
-
|
|
47008
|
-
|
|
47009
|
-
formatOffset(ts, format) {
|
|
47010
|
-
return formatOffset(this.fixed, format);
|
|
47011
|
-
}
|
|
47012
|
-
/** @override **/
|
|
47013
|
-
|
|
47014
|
-
|
|
47015
|
-
get isUniversal() {
|
|
47016
|
-
return true;
|
|
47017
|
-
}
|
|
47018
|
-
/** @override **/
|
|
46665
|
+
/** @override **/
|
|
47019
46666
|
|
|
47020
46667
|
|
|
47021
46668
|
offset() {
|
|
@@ -47127,6 +46774,7 @@ let now = () => Date.now(),
|
|
|
47127
46774
|
defaultLocale = null,
|
|
47128
46775
|
defaultNumberingSystem = null,
|
|
47129
46776
|
defaultOutputCalendar = null,
|
|
46777
|
+
twoDigitCutoffYear = 60,
|
|
47130
46778
|
throwOnInvalid;
|
|
47131
46779
|
/**
|
|
47132
46780
|
* Settings contains static getters and setters that control Luxon's overall behavior. Luxon is a simple library with few options, but the ones it does have live here.
|
|
@@ -47227,6 +46875,28 @@ class Settings {
|
|
|
47227
46875
|
static set defaultOutputCalendar(outputCalendar) {
|
|
47228
46876
|
defaultOutputCalendar = outputCalendar;
|
|
47229
46877
|
}
|
|
46878
|
+
/**
|
|
46879
|
+
* Get the cutoff year after which a string encoding a year as two digits is interpreted to occur in the current century.
|
|
46880
|
+
* @type {number}
|
|
46881
|
+
*/
|
|
46882
|
+
|
|
46883
|
+
|
|
46884
|
+
static get twoDigitCutoffYear() {
|
|
46885
|
+
return twoDigitCutoffYear;
|
|
46886
|
+
}
|
|
46887
|
+
/**
|
|
46888
|
+
* Set the cutoff year after which a string encoding a year as two digits is interpreted to occur in the current century.
|
|
46889
|
+
* @type {number}
|
|
46890
|
+
* @example Settings.twoDigitCutoffYear = 0 // cut-off year is 0, so all 'yy' are interpretted as current century
|
|
46891
|
+
* @example Settings.twoDigitCutoffYear = 50 // '49' -> 1949; '50' -> 2050
|
|
46892
|
+
* @example Settings.twoDigitCutoffYear = 1950 // interpretted as 50
|
|
46893
|
+
* @example Settings.twoDigitCutoffYear = 2050 // ALSO interpretted as 50
|
|
46894
|
+
*/
|
|
46895
|
+
|
|
46896
|
+
|
|
46897
|
+
static set twoDigitCutoffYear(cutoffYear) {
|
|
46898
|
+
twoDigitCutoffYear = cutoffYear % 100;
|
|
46899
|
+
}
|
|
47230
46900
|
/**
|
|
47231
46901
|
* Get whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals
|
|
47232
46902
|
* @type {boolean}
|
|
@@ -47258,495 +46928,870 @@ class Settings {
|
|
|
47258
46928
|
|
|
47259
46929
|
}
|
|
47260
46930
|
|
|
47261
|
-
|
|
46931
|
+
/*
|
|
46932
|
+
This is just a junk drawer, containing anything used across multiple classes.
|
|
46933
|
+
Because Luxon is small(ish), this should stay small and we won't worry about splitting
|
|
46934
|
+
it up into, say, parsingUtil.js and basicUtil.js and so on. But they are divided up by feature area.
|
|
46935
|
+
*/
|
|
46936
|
+
/**
|
|
46937
|
+
* @private
|
|
46938
|
+
*/
|
|
46939
|
+
// TYPES
|
|
47262
46940
|
|
|
47263
|
-
function
|
|
47264
|
-
|
|
47265
|
-
|
|
46941
|
+
function isUndefined(o) {
|
|
46942
|
+
return typeof o === "undefined";
|
|
46943
|
+
}
|
|
46944
|
+
function isNumber(o) {
|
|
46945
|
+
return typeof o === "number";
|
|
46946
|
+
}
|
|
46947
|
+
function isInteger(o) {
|
|
46948
|
+
return typeof o === "number" && o % 1 === 0;
|
|
46949
|
+
}
|
|
46950
|
+
function isString(o) {
|
|
46951
|
+
return typeof o === "string";
|
|
46952
|
+
}
|
|
46953
|
+
function isDate(o) {
|
|
46954
|
+
return Object.prototype.toString.call(o) === "[object Date]";
|
|
46955
|
+
} // CAPABILITIES
|
|
47266
46956
|
|
|
47267
|
-
|
|
47268
|
-
|
|
47269
|
-
|
|
46957
|
+
function hasRelative() {
|
|
46958
|
+
try {
|
|
46959
|
+
return typeof Intl !== "undefined" && !!Intl.RelativeTimeFormat;
|
|
46960
|
+
} catch (e) {
|
|
46961
|
+
return false;
|
|
47270
46962
|
}
|
|
46963
|
+
} // OBJECTS AND ARRAYS
|
|
47271
46964
|
|
|
47272
|
-
|
|
46965
|
+
function maybeArray(thing) {
|
|
46966
|
+
return Array.isArray(thing) ? thing : [thing];
|
|
47273
46967
|
}
|
|
46968
|
+
function bestBy(arr, by, compare) {
|
|
46969
|
+
if (arr.length === 0) {
|
|
46970
|
+
return undefined;
|
|
46971
|
+
}
|
|
47274
46972
|
|
|
47275
|
-
|
|
46973
|
+
return arr.reduce((best, next) => {
|
|
46974
|
+
const pair = [by(next), next];
|
|
47276
46975
|
|
|
47277
|
-
|
|
47278
|
-
|
|
47279
|
-
|
|
46976
|
+
if (!best) {
|
|
46977
|
+
return pair;
|
|
46978
|
+
} else if (compare(best[0], pair[0]) === best[0]) {
|
|
46979
|
+
return best;
|
|
46980
|
+
} else {
|
|
46981
|
+
return pair;
|
|
46982
|
+
}
|
|
46983
|
+
}, null)[1];
|
|
46984
|
+
}
|
|
46985
|
+
function pick(obj, keys) {
|
|
46986
|
+
return keys.reduce((a, k) => {
|
|
46987
|
+
a[k] = obj[k];
|
|
46988
|
+
return a;
|
|
46989
|
+
}, {});
|
|
46990
|
+
}
|
|
46991
|
+
function hasOwnProperty(obj, prop) {
|
|
46992
|
+
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
46993
|
+
} // NUMBERS AND STRINGS
|
|
47280
46994
|
|
|
47281
|
-
|
|
47282
|
-
|
|
47283
|
-
|
|
46995
|
+
function integerBetween(thing, bottom, top) {
|
|
46996
|
+
return isInteger(thing) && thing >= bottom && thing <= top;
|
|
46997
|
+
} // x % n but takes the sign of n instead of x
|
|
46998
|
+
|
|
46999
|
+
function floorMod(x, n) {
|
|
47000
|
+
return x - n * Math.floor(x / n);
|
|
47001
|
+
}
|
|
47002
|
+
function padStart(input, n = 2) {
|
|
47003
|
+
const isNeg = input < 0;
|
|
47004
|
+
let padded;
|
|
47005
|
+
|
|
47006
|
+
if (isNeg) {
|
|
47007
|
+
padded = "-" + ("" + -input).padStart(n, "0");
|
|
47008
|
+
} else {
|
|
47009
|
+
padded = ("" + input).padStart(n, "0");
|
|
47284
47010
|
}
|
|
47285
47011
|
|
|
47286
|
-
return
|
|
47012
|
+
return padded;
|
|
47287
47013
|
}
|
|
47014
|
+
function parseInteger(string) {
|
|
47015
|
+
if (isUndefined(string) || string === null || string === "") {
|
|
47016
|
+
return undefined;
|
|
47017
|
+
} else {
|
|
47018
|
+
return parseInt(string, 10);
|
|
47019
|
+
}
|
|
47020
|
+
}
|
|
47021
|
+
function parseFloating(string) {
|
|
47022
|
+
if (isUndefined(string) || string === null || string === "") {
|
|
47023
|
+
return undefined;
|
|
47024
|
+
} else {
|
|
47025
|
+
return parseFloat(string);
|
|
47026
|
+
}
|
|
47027
|
+
}
|
|
47028
|
+
function parseMillis(fraction) {
|
|
47029
|
+
// Return undefined (instead of 0) in these cases, where fraction is not set
|
|
47030
|
+
if (isUndefined(fraction) || fraction === null || fraction === "") {
|
|
47031
|
+
return undefined;
|
|
47032
|
+
} else {
|
|
47033
|
+
const f = parseFloat("0." + fraction) * 1000;
|
|
47034
|
+
return Math.floor(f);
|
|
47035
|
+
}
|
|
47036
|
+
}
|
|
47037
|
+
function roundTo(number, digits, towardZero = false) {
|
|
47038
|
+
const factor = 10 ** digits,
|
|
47039
|
+
rounder = towardZero ? Math.trunc : Math.round;
|
|
47040
|
+
return rounder(number * factor) / factor;
|
|
47041
|
+
} // DATE BASICS
|
|
47288
47042
|
|
|
47289
|
-
|
|
47043
|
+
function isLeapYear(year) {
|
|
47044
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
47045
|
+
}
|
|
47046
|
+
function daysInYear(year) {
|
|
47047
|
+
return isLeapYear(year) ? 366 : 365;
|
|
47048
|
+
}
|
|
47049
|
+
function daysInMonth(year, month) {
|
|
47050
|
+
const modMonth = floorMod(month - 1, 12) + 1,
|
|
47051
|
+
modYear = year + (month - modMonth) / 12;
|
|
47290
47052
|
|
|
47291
|
-
|
|
47292
|
-
|
|
47293
|
-
|
|
47053
|
+
if (modMonth === 2) {
|
|
47054
|
+
return isLeapYear(modYear) ? 29 : 28;
|
|
47055
|
+
} else {
|
|
47056
|
+
return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][modMonth - 1];
|
|
47057
|
+
}
|
|
47058
|
+
} // covert a calendar object to a local timestamp (epoch, but with the offset baked in)
|
|
47294
47059
|
|
|
47295
|
-
|
|
47296
|
-
|
|
47297
|
-
|
|
47060
|
+
function objToLocalTS(obj) {
|
|
47061
|
+
let d = Date.UTC(obj.year, obj.month - 1, obj.day, obj.hour, obj.minute, obj.second, obj.millisecond); // for legacy reasons, years between 0 and 99 are interpreted as 19XX; revert that
|
|
47062
|
+
|
|
47063
|
+
if (obj.year < 100 && obj.year >= 0) {
|
|
47064
|
+
d = new Date(d);
|
|
47065
|
+
d.setUTCFullYear(d.getUTCFullYear() - 1900);
|
|
47298
47066
|
}
|
|
47299
47067
|
|
|
47300
|
-
return
|
|
47068
|
+
return +d;
|
|
47069
|
+
}
|
|
47070
|
+
function weeksInWeekYear(weekYear) {
|
|
47071
|
+
const p1 = (weekYear + Math.floor(weekYear / 4) - Math.floor(weekYear / 100) + Math.floor(weekYear / 400)) % 7,
|
|
47072
|
+
last = weekYear - 1,
|
|
47073
|
+
p2 = (last + Math.floor(last / 4) - Math.floor(last / 100) + Math.floor(last / 400)) % 7;
|
|
47074
|
+
return p1 === 4 || p2 === 3 ? 53 : 52;
|
|
47301
47075
|
}
|
|
47076
|
+
function untruncateYear(year) {
|
|
47077
|
+
if (year > 99) {
|
|
47078
|
+
return year;
|
|
47079
|
+
} else return year > Settings.twoDigitCutoffYear ? 1900 + year : 2000 + year;
|
|
47080
|
+
} // PARSING
|
|
47302
47081
|
|
|
47303
|
-
|
|
47082
|
+
function parseZoneInfo(ts, offsetFormat, locale, timeZone = null) {
|
|
47083
|
+
const date = new Date(ts),
|
|
47084
|
+
intlOpts = {
|
|
47085
|
+
hourCycle: "h23",
|
|
47086
|
+
year: "numeric",
|
|
47087
|
+
month: "2-digit",
|
|
47088
|
+
day: "2-digit",
|
|
47089
|
+
hour: "2-digit",
|
|
47090
|
+
minute: "2-digit"
|
|
47091
|
+
};
|
|
47304
47092
|
|
|
47305
|
-
|
|
47306
|
-
|
|
47307
|
-
|
|
47308
|
-
...cacheKeyOpts
|
|
47309
|
-
} = opts; // exclude `base` from the options
|
|
47093
|
+
if (timeZone) {
|
|
47094
|
+
intlOpts.timeZone = timeZone;
|
|
47095
|
+
}
|
|
47310
47096
|
|
|
47311
|
-
const
|
|
47312
|
-
|
|
47097
|
+
const modified = {
|
|
47098
|
+
timeZoneName: offsetFormat,
|
|
47099
|
+
...intlOpts
|
|
47100
|
+
};
|
|
47101
|
+
const parsed = new Intl.DateTimeFormat(locale, modified).formatToParts(date).find(m => m.type.toLowerCase() === "timezonename");
|
|
47102
|
+
return parsed ? parsed.value : null;
|
|
47103
|
+
} // signedOffset('-5', '30') -> -330
|
|
47313
47104
|
|
|
47314
|
-
|
|
47315
|
-
|
|
47316
|
-
|
|
47105
|
+
function signedOffset(offHourStr, offMinuteStr) {
|
|
47106
|
+
let offHour = parseInt(offHourStr, 10); // don't || this because we want to preserve -0
|
|
47107
|
+
|
|
47108
|
+
if (Number.isNaN(offHour)) {
|
|
47109
|
+
offHour = 0;
|
|
47317
47110
|
}
|
|
47318
47111
|
|
|
47319
|
-
|
|
47112
|
+
const offMin = parseInt(offMinuteStr, 10) || 0,
|
|
47113
|
+
offMinSigned = offHour < 0 || Object.is(offHour, -0) ? -offMin : offMin;
|
|
47114
|
+
return offHour * 60 + offMinSigned;
|
|
47115
|
+
} // COERCION
|
|
47116
|
+
|
|
47117
|
+
function asNumber(value) {
|
|
47118
|
+
const numericValue = Number(value);
|
|
47119
|
+
if (typeof value === "boolean" || value === "" || Number.isNaN(numericValue)) throw new InvalidArgumentError(`Invalid unit value ${value}`);
|
|
47120
|
+
return numericValue;
|
|
47320
47121
|
}
|
|
47122
|
+
function normalizeObject(obj, normalizer) {
|
|
47123
|
+
const normalized = {};
|
|
47321
47124
|
|
|
47322
|
-
|
|
47125
|
+
for (const u in obj) {
|
|
47126
|
+
if (hasOwnProperty(obj, u)) {
|
|
47127
|
+
const v = obj[u];
|
|
47128
|
+
if (v === undefined || v === null) continue;
|
|
47129
|
+
normalized[normalizer(u)] = asNumber(v);
|
|
47130
|
+
}
|
|
47131
|
+
}
|
|
47323
47132
|
|
|
47324
|
-
|
|
47325
|
-
|
|
47326
|
-
|
|
47327
|
-
|
|
47328
|
-
|
|
47329
|
-
|
|
47133
|
+
return normalized;
|
|
47134
|
+
}
|
|
47135
|
+
function formatOffset(offset, format) {
|
|
47136
|
+
const hours = Math.trunc(Math.abs(offset / 60)),
|
|
47137
|
+
minutes = Math.trunc(Math.abs(offset % 60)),
|
|
47138
|
+
sign = offset >= 0 ? "+" : "-";
|
|
47139
|
+
|
|
47140
|
+
switch (format) {
|
|
47141
|
+
case "short":
|
|
47142
|
+
return `${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}`;
|
|
47143
|
+
|
|
47144
|
+
case "narrow":
|
|
47145
|
+
return `${sign}${hours}${minutes > 0 ? `:${minutes}` : ""}`;
|
|
47146
|
+
|
|
47147
|
+
case "techie":
|
|
47148
|
+
return `${sign}${padStart(hours, 2)}${padStart(minutes, 2)}`;
|
|
47149
|
+
|
|
47150
|
+
default:
|
|
47151
|
+
throw new RangeError(`Value format ${format} is out of range for property format`);
|
|
47330
47152
|
}
|
|
47331
47153
|
}
|
|
47154
|
+
function timeObject(obj) {
|
|
47155
|
+
return pick(obj, ["hour", "minute", "second", "millisecond"]);
|
|
47156
|
+
}
|
|
47332
47157
|
|
|
47333
|
-
|
|
47334
|
-
|
|
47335
|
-
|
|
47336
|
-
// Instead, we'll do this:
|
|
47337
|
-
// a) if the string has no -u extensions, just leave it alone
|
|
47338
|
-
// b) if it does, use Intl to resolve everything
|
|
47339
|
-
// c) if Intl fails, try again without the -u
|
|
47340
|
-
const uIndex = localeStr.indexOf("-u-");
|
|
47158
|
+
/**
|
|
47159
|
+
* @private
|
|
47160
|
+
*/
|
|
47341
47161
|
|
|
47342
|
-
if (uIndex === -1) {
|
|
47343
|
-
return [localeStr];
|
|
47344
|
-
} else {
|
|
47345
|
-
let options;
|
|
47346
|
-
const smaller = localeStr.substring(0, uIndex);
|
|
47347
47162
|
|
|
47348
|
-
|
|
47349
|
-
|
|
47350
|
-
|
|
47351
|
-
|
|
47163
|
+
const monthsLong = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
47164
|
+
const monthsShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
47165
|
+
const monthsNarrow = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"];
|
|
47166
|
+
function months(length) {
|
|
47167
|
+
switch (length) {
|
|
47168
|
+
case "narrow":
|
|
47169
|
+
return [...monthsNarrow];
|
|
47170
|
+
|
|
47171
|
+
case "short":
|
|
47172
|
+
return [...monthsShort];
|
|
47173
|
+
|
|
47174
|
+
case "long":
|
|
47175
|
+
return [...monthsLong];
|
|
47176
|
+
|
|
47177
|
+
case "numeric":
|
|
47178
|
+
return ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
|
|
47179
|
+
|
|
47180
|
+
case "2-digit":
|
|
47181
|
+
return ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
|
|
47182
|
+
|
|
47183
|
+
default:
|
|
47184
|
+
return null;
|
|
47185
|
+
}
|
|
47186
|
+
}
|
|
47187
|
+
const weekdaysLong = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
|
47188
|
+
const weekdaysShort = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
47189
|
+
const weekdaysNarrow = ["M", "T", "W", "T", "F", "S", "S"];
|
|
47190
|
+
function weekdays(length) {
|
|
47191
|
+
switch (length) {
|
|
47192
|
+
case "narrow":
|
|
47193
|
+
return [...weekdaysNarrow];
|
|
47194
|
+
|
|
47195
|
+
case "short":
|
|
47196
|
+
return [...weekdaysShort];
|
|
47197
|
+
|
|
47198
|
+
case "long":
|
|
47199
|
+
return [...weekdaysLong];
|
|
47200
|
+
|
|
47201
|
+
case "numeric":
|
|
47202
|
+
return ["1", "2", "3", "4", "5", "6", "7"];
|
|
47203
|
+
|
|
47204
|
+
default:
|
|
47205
|
+
return null;
|
|
47206
|
+
}
|
|
47207
|
+
}
|
|
47208
|
+
const meridiems = ["AM", "PM"];
|
|
47209
|
+
const erasLong = ["Before Christ", "Anno Domini"];
|
|
47210
|
+
const erasShort = ["BC", "AD"];
|
|
47211
|
+
const erasNarrow = ["B", "A"];
|
|
47212
|
+
function eras(length) {
|
|
47213
|
+
switch (length) {
|
|
47214
|
+
case "narrow":
|
|
47215
|
+
return [...erasNarrow];
|
|
47216
|
+
|
|
47217
|
+
case "short":
|
|
47218
|
+
return [...erasShort];
|
|
47219
|
+
|
|
47220
|
+
case "long":
|
|
47221
|
+
return [...erasLong];
|
|
47222
|
+
|
|
47223
|
+
default:
|
|
47224
|
+
return null;
|
|
47225
|
+
}
|
|
47226
|
+
}
|
|
47227
|
+
function meridiemForDateTime(dt) {
|
|
47228
|
+
return meridiems[dt.hour < 12 ? 0 : 1];
|
|
47229
|
+
}
|
|
47230
|
+
function weekdayForDateTime(dt, length) {
|
|
47231
|
+
return weekdays(length)[dt.weekday - 1];
|
|
47232
|
+
}
|
|
47233
|
+
function monthForDateTime(dt, length) {
|
|
47234
|
+
return months(length)[dt.month - 1];
|
|
47235
|
+
}
|
|
47236
|
+
function eraForDateTime(dt, length) {
|
|
47237
|
+
return eras(length)[dt.year < 0 ? 0 : 1];
|
|
47238
|
+
}
|
|
47239
|
+
function formatRelativeTime(unit, count, numeric = "always", narrow = false) {
|
|
47240
|
+
const units = {
|
|
47241
|
+
years: ["year", "yr."],
|
|
47242
|
+
quarters: ["quarter", "qtr."],
|
|
47243
|
+
months: ["month", "mo."],
|
|
47244
|
+
weeks: ["week", "wk."],
|
|
47245
|
+
days: ["day", "day", "days"],
|
|
47246
|
+
hours: ["hour", "hr."],
|
|
47247
|
+
minutes: ["minute", "min."],
|
|
47248
|
+
seconds: ["second", "sec."]
|
|
47249
|
+
};
|
|
47250
|
+
const lastable = ["hours", "minutes", "seconds"].indexOf(unit) === -1;
|
|
47251
|
+
|
|
47252
|
+
if (numeric === "auto" && lastable) {
|
|
47253
|
+
const isDay = unit === "days";
|
|
47254
|
+
|
|
47255
|
+
switch (count) {
|
|
47256
|
+
case 1:
|
|
47257
|
+
return isDay ? "tomorrow" : `next ${units[unit][0]}`;
|
|
47258
|
+
|
|
47259
|
+
case -1:
|
|
47260
|
+
return isDay ? "yesterday" : `last ${units[unit][0]}`;
|
|
47261
|
+
|
|
47262
|
+
case 0:
|
|
47263
|
+
return isDay ? "today" : `this ${units[unit][0]}`;
|
|
47264
|
+
|
|
47352
47265
|
}
|
|
47266
|
+
}
|
|
47353
47267
|
|
|
47354
|
-
|
|
47355
|
-
|
|
47356
|
-
|
|
47357
|
-
|
|
47268
|
+
const isInPast = Object.is(count, -0) || count < 0,
|
|
47269
|
+
fmtValue = Math.abs(count),
|
|
47270
|
+
singular = fmtValue === 1,
|
|
47271
|
+
lilUnits = units[unit],
|
|
47272
|
+
fmtUnit = narrow ? singular ? lilUnits[1] : lilUnits[2] || lilUnits[1] : singular ? units[unit][0] : unit;
|
|
47273
|
+
return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}`;
|
|
47274
|
+
}
|
|
47358
47275
|
|
|
47359
|
-
|
|
47276
|
+
function stringifyTokens(splits, tokenToString) {
|
|
47277
|
+
let s = "";
|
|
47278
|
+
|
|
47279
|
+
for (const token of splits) {
|
|
47280
|
+
if (token.literal) {
|
|
47281
|
+
s += token.val;
|
|
47282
|
+
} else {
|
|
47283
|
+
s += tokenToString(token.val);
|
|
47284
|
+
}
|
|
47360
47285
|
}
|
|
47286
|
+
|
|
47287
|
+
return s;
|
|
47361
47288
|
}
|
|
47362
47289
|
|
|
47363
|
-
|
|
47364
|
-
|
|
47365
|
-
|
|
47290
|
+
const macroTokenToFormatOpts = {
|
|
47291
|
+
D: DATE_SHORT,
|
|
47292
|
+
DD: DATE_MED,
|
|
47293
|
+
DDD: DATE_FULL,
|
|
47294
|
+
DDDD: DATE_HUGE,
|
|
47295
|
+
t: TIME_SIMPLE,
|
|
47296
|
+
tt: TIME_WITH_SECONDS,
|
|
47297
|
+
ttt: TIME_WITH_SHORT_OFFSET,
|
|
47298
|
+
tttt: TIME_WITH_LONG_OFFSET,
|
|
47299
|
+
T: TIME_24_SIMPLE,
|
|
47300
|
+
TT: TIME_24_WITH_SECONDS,
|
|
47301
|
+
TTT: TIME_24_WITH_SHORT_OFFSET,
|
|
47302
|
+
TTTT: TIME_24_WITH_LONG_OFFSET,
|
|
47303
|
+
f: DATETIME_SHORT,
|
|
47304
|
+
ff: DATETIME_MED,
|
|
47305
|
+
fff: DATETIME_FULL,
|
|
47306
|
+
ffff: DATETIME_HUGE,
|
|
47307
|
+
F: DATETIME_SHORT_WITH_SECONDS,
|
|
47308
|
+
FF: DATETIME_MED_WITH_SECONDS,
|
|
47309
|
+
FFF: DATETIME_FULL_WITH_SECONDS,
|
|
47310
|
+
FFFF: DATETIME_HUGE_WITH_SECONDS
|
|
47311
|
+
};
|
|
47312
|
+
/**
|
|
47313
|
+
* @private
|
|
47314
|
+
*/
|
|
47366
47315
|
|
|
47367
|
-
|
|
47368
|
-
|
|
47316
|
+
class Formatter {
|
|
47317
|
+
static create(locale, opts = {}) {
|
|
47318
|
+
return new Formatter(locale, opts);
|
|
47319
|
+
}
|
|
47320
|
+
|
|
47321
|
+
static parseFormat(fmt) {
|
|
47322
|
+
let current = null,
|
|
47323
|
+
currentFull = "",
|
|
47324
|
+
bracketed = false;
|
|
47325
|
+
const splits = [];
|
|
47326
|
+
|
|
47327
|
+
for (let i = 0; i < fmt.length; i++) {
|
|
47328
|
+
const c = fmt.charAt(i);
|
|
47329
|
+
|
|
47330
|
+
if (c === "'") {
|
|
47331
|
+
if (currentFull.length > 0) {
|
|
47332
|
+
splits.push({
|
|
47333
|
+
literal: bracketed,
|
|
47334
|
+
val: currentFull
|
|
47335
|
+
});
|
|
47336
|
+
}
|
|
47337
|
+
|
|
47338
|
+
current = null;
|
|
47339
|
+
currentFull = "";
|
|
47340
|
+
bracketed = !bracketed;
|
|
47341
|
+
} else if (bracketed) {
|
|
47342
|
+
currentFull += c;
|
|
47343
|
+
} else if (c === current) {
|
|
47344
|
+
currentFull += c;
|
|
47345
|
+
} else {
|
|
47346
|
+
if (currentFull.length > 0) {
|
|
47347
|
+
splits.push({
|
|
47348
|
+
literal: false,
|
|
47349
|
+
val: currentFull
|
|
47350
|
+
});
|
|
47351
|
+
}
|
|
47352
|
+
|
|
47353
|
+
currentFull = c;
|
|
47354
|
+
current = c;
|
|
47355
|
+
}
|
|
47369
47356
|
}
|
|
47370
47357
|
|
|
47371
|
-
if (
|
|
47372
|
-
|
|
47358
|
+
if (currentFull.length > 0) {
|
|
47359
|
+
splits.push({
|
|
47360
|
+
literal: bracketed,
|
|
47361
|
+
val: currentFull
|
|
47362
|
+
});
|
|
47373
47363
|
}
|
|
47374
47364
|
|
|
47375
|
-
return
|
|
47376
|
-
} else {
|
|
47377
|
-
return localeStr;
|
|
47365
|
+
return splits;
|
|
47378
47366
|
}
|
|
47379
|
-
}
|
|
47380
47367
|
|
|
47381
|
-
|
|
47382
|
-
|
|
47368
|
+
static macroTokenToFormatOpts(token) {
|
|
47369
|
+
return macroTokenToFormatOpts[token];
|
|
47370
|
+
}
|
|
47383
47371
|
|
|
47384
|
-
|
|
47385
|
-
|
|
47386
|
-
|
|
47372
|
+
constructor(locale, formatOpts) {
|
|
47373
|
+
this.opts = formatOpts;
|
|
47374
|
+
this.loc = locale;
|
|
47375
|
+
this.systemLoc = null;
|
|
47387
47376
|
}
|
|
47388
47377
|
|
|
47389
|
-
|
|
47390
|
-
|
|
47378
|
+
formatWithSystemDefault(dt, opts) {
|
|
47379
|
+
if (this.systemLoc === null) {
|
|
47380
|
+
this.systemLoc = this.loc.redefaultToSystem();
|
|
47381
|
+
}
|
|
47382
|
+
|
|
47383
|
+
const df = this.systemLoc.dtFormatter(dt, { ...this.opts,
|
|
47384
|
+
...opts
|
|
47385
|
+
});
|
|
47386
|
+
return df.format();
|
|
47387
|
+
}
|
|
47388
|
+
|
|
47389
|
+
formatDateTime(dt, opts = {}) {
|
|
47390
|
+
const df = this.loc.dtFormatter(dt, { ...this.opts,
|
|
47391
|
+
...opts
|
|
47392
|
+
});
|
|
47393
|
+
return df.format();
|
|
47394
|
+
}
|
|
47395
|
+
|
|
47396
|
+
formatDateTimeParts(dt, opts = {}) {
|
|
47397
|
+
const df = this.loc.dtFormatter(dt, { ...this.opts,
|
|
47398
|
+
...opts
|
|
47399
|
+
});
|
|
47400
|
+
return df.formatToParts();
|
|
47401
|
+
}
|
|
47402
|
+
|
|
47403
|
+
resolvedOptions(dt, opts = {}) {
|
|
47404
|
+
const df = this.loc.dtFormatter(dt, { ...this.opts,
|
|
47405
|
+
...opts
|
|
47406
|
+
});
|
|
47407
|
+
return df.resolvedOptions();
|
|
47408
|
+
}
|
|
47409
|
+
|
|
47410
|
+
num(n, p = 0) {
|
|
47411
|
+
// we get some perf out of doing this here, annoyingly
|
|
47412
|
+
if (this.opts.forceSimple) {
|
|
47413
|
+
return padStart(n, p);
|
|
47414
|
+
}
|
|
47415
|
+
|
|
47416
|
+
const opts = { ...this.opts
|
|
47417
|
+
};
|
|
47418
|
+
|
|
47419
|
+
if (p > 0) {
|
|
47420
|
+
opts.padTo = p;
|
|
47421
|
+
}
|
|
47422
|
+
|
|
47423
|
+
return this.loc.numberFormatter(opts).format(n);
|
|
47424
|
+
}
|
|
47425
|
+
|
|
47426
|
+
formatDateTimeFromString(dt, fmt) {
|
|
47427
|
+
const knownEnglish = this.loc.listingMode() === "en",
|
|
47428
|
+
useDateTimeFormatter = this.loc.outputCalendar && this.loc.outputCalendar !== "gregory",
|
|
47429
|
+
string = (opts, extract) => this.loc.extract(dt, opts, extract),
|
|
47430
|
+
formatOffset = opts => {
|
|
47431
|
+
if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) {
|
|
47432
|
+
return "Z";
|
|
47433
|
+
}
|
|
47434
|
+
|
|
47435
|
+
return dt.isValid ? dt.zone.formatOffset(dt.ts, opts.format) : "";
|
|
47436
|
+
},
|
|
47437
|
+
meridiem = () => knownEnglish ? meridiemForDateTime(dt) : string({
|
|
47438
|
+
hour: "numeric",
|
|
47439
|
+
hourCycle: "h12"
|
|
47440
|
+
}, "dayperiod"),
|
|
47441
|
+
month = (length, standalone) => knownEnglish ? monthForDateTime(dt, length) : string(standalone ? {
|
|
47442
|
+
month: length
|
|
47443
|
+
} : {
|
|
47444
|
+
month: length,
|
|
47445
|
+
day: "numeric"
|
|
47446
|
+
}, "month"),
|
|
47447
|
+
weekday = (length, standalone) => knownEnglish ? weekdayForDateTime(dt, length) : string(standalone ? {
|
|
47448
|
+
weekday: length
|
|
47449
|
+
} : {
|
|
47450
|
+
weekday: length,
|
|
47451
|
+
month: "long",
|
|
47452
|
+
day: "numeric"
|
|
47453
|
+
}, "weekday"),
|
|
47454
|
+
maybeMacro = token => {
|
|
47455
|
+
const formatOpts = Formatter.macroTokenToFormatOpts(token);
|
|
47456
|
+
|
|
47457
|
+
if (formatOpts) {
|
|
47458
|
+
return this.formatWithSystemDefault(dt, formatOpts);
|
|
47459
|
+
} else {
|
|
47460
|
+
return token;
|
|
47461
|
+
}
|
|
47462
|
+
},
|
|
47463
|
+
era = length => knownEnglish ? eraForDateTime(dt, length) : string({
|
|
47464
|
+
era: length
|
|
47465
|
+
}, "era"),
|
|
47466
|
+
tokenToString = token => {
|
|
47467
|
+
// Where possible: http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles
|
|
47468
|
+
switch (token) {
|
|
47469
|
+
// ms
|
|
47470
|
+
case "S":
|
|
47471
|
+
return this.num(dt.millisecond);
|
|
47472
|
+
|
|
47473
|
+
case "u": // falls through
|
|
47474
|
+
|
|
47475
|
+
case "SSS":
|
|
47476
|
+
return this.num(dt.millisecond, 3);
|
|
47477
|
+
// seconds
|
|
47478
|
+
|
|
47479
|
+
case "s":
|
|
47480
|
+
return this.num(dt.second);
|
|
47481
|
+
|
|
47482
|
+
case "ss":
|
|
47483
|
+
return this.num(dt.second, 2);
|
|
47484
|
+
// fractional seconds
|
|
47485
|
+
|
|
47486
|
+
case "uu":
|
|
47487
|
+
return this.num(Math.floor(dt.millisecond / 10), 2);
|
|
47488
|
+
|
|
47489
|
+
case "uuu":
|
|
47490
|
+
return this.num(Math.floor(dt.millisecond / 100));
|
|
47491
|
+
// minutes
|
|
47492
|
+
|
|
47493
|
+
case "m":
|
|
47494
|
+
return this.num(dt.minute);
|
|
47495
|
+
|
|
47496
|
+
case "mm":
|
|
47497
|
+
return this.num(dt.minute, 2);
|
|
47498
|
+
// hours
|
|
47499
|
+
|
|
47500
|
+
case "h":
|
|
47501
|
+
return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12);
|
|
47502
|
+
|
|
47503
|
+
case "hh":
|
|
47504
|
+
return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12, 2);
|
|
47505
|
+
|
|
47506
|
+
case "H":
|
|
47507
|
+
return this.num(dt.hour);
|
|
47508
|
+
|
|
47509
|
+
case "HH":
|
|
47510
|
+
return this.num(dt.hour, 2);
|
|
47511
|
+
// offset
|
|
47512
|
+
|
|
47513
|
+
case "Z":
|
|
47514
|
+
// like +6
|
|
47515
|
+
return formatOffset({
|
|
47516
|
+
format: "narrow",
|
|
47517
|
+
allowZ: this.opts.allowZ
|
|
47518
|
+
});
|
|
47391
47519
|
|
|
47392
|
-
|
|
47393
|
-
|
|
47520
|
+
case "ZZ":
|
|
47521
|
+
// like +06:00
|
|
47522
|
+
return formatOffset({
|
|
47523
|
+
format: "short",
|
|
47524
|
+
allowZ: this.opts.allowZ
|
|
47525
|
+
});
|
|
47394
47526
|
|
|
47395
|
-
|
|
47396
|
-
|
|
47397
|
-
|
|
47398
|
-
|
|
47527
|
+
case "ZZZ":
|
|
47528
|
+
// like +0600
|
|
47529
|
+
return formatOffset({
|
|
47530
|
+
format: "techie",
|
|
47531
|
+
allowZ: this.opts.allowZ
|
|
47532
|
+
});
|
|
47399
47533
|
|
|
47400
|
-
|
|
47401
|
-
|
|
47534
|
+
case "ZZZZ":
|
|
47535
|
+
// like EST
|
|
47536
|
+
return dt.zone.offsetName(dt.ts, {
|
|
47537
|
+
format: "short",
|
|
47538
|
+
locale: this.loc.locale
|
|
47539
|
+
});
|
|
47402
47540
|
|
|
47403
|
-
|
|
47404
|
-
|
|
47541
|
+
case "ZZZZZ":
|
|
47542
|
+
// like Eastern Standard Time
|
|
47543
|
+
return dt.zone.offsetName(dt.ts, {
|
|
47544
|
+
format: "long",
|
|
47545
|
+
locale: this.loc.locale
|
|
47546
|
+
});
|
|
47547
|
+
// zone
|
|
47405
47548
|
|
|
47406
|
-
|
|
47407
|
-
|
|
47408
|
-
|
|
47409
|
-
|
|
47410
|
-
} else {
|
|
47411
|
-
return intlFn(length);
|
|
47412
|
-
}
|
|
47413
|
-
}
|
|
47549
|
+
case "z":
|
|
47550
|
+
// like America/New_York
|
|
47551
|
+
return dt.zoneName;
|
|
47552
|
+
// meridiems
|
|
47414
47553
|
|
|
47415
|
-
|
|
47416
|
-
|
|
47417
|
-
|
|
47418
|
-
} else {
|
|
47419
|
-
return loc.numberingSystem === "latn" || !loc.locale || loc.locale.startsWith("en") || new Intl.DateTimeFormat(loc.intl).resolvedOptions().numberingSystem === "latn";
|
|
47420
|
-
}
|
|
47421
|
-
}
|
|
47422
|
-
/**
|
|
47423
|
-
* @private
|
|
47424
|
-
*/
|
|
47554
|
+
case "a":
|
|
47555
|
+
return meridiem();
|
|
47556
|
+
// dates
|
|
47425
47557
|
|
|
47558
|
+
case "d":
|
|
47559
|
+
return useDateTimeFormatter ? string({
|
|
47560
|
+
day: "numeric"
|
|
47561
|
+
}, "day") : this.num(dt.day);
|
|
47426
47562
|
|
|
47427
|
-
|
|
47428
|
-
|
|
47429
|
-
|
|
47430
|
-
|
|
47431
|
-
|
|
47432
|
-
padTo,
|
|
47433
|
-
floor,
|
|
47434
|
-
...otherOpts
|
|
47435
|
-
} = opts;
|
|
47563
|
+
case "dd":
|
|
47564
|
+
return useDateTimeFormatter ? string({
|
|
47565
|
+
day: "2-digit"
|
|
47566
|
+
}, "day") : this.num(dt.day, 2);
|
|
47567
|
+
// weekdays - standalone
|
|
47436
47568
|
|
|
47437
|
-
|
|
47438
|
-
|
|
47439
|
-
|
|
47440
|
-
...opts
|
|
47441
|
-
};
|
|
47442
|
-
if (opts.padTo > 0) intlOpts.minimumIntegerDigits = opts.padTo;
|
|
47443
|
-
this.inf = getCachedINF(intl, intlOpts);
|
|
47444
|
-
}
|
|
47445
|
-
}
|
|
47569
|
+
case "c":
|
|
47570
|
+
// like 1
|
|
47571
|
+
return this.num(dt.weekday);
|
|
47446
47572
|
|
|
47447
|
-
|
|
47448
|
-
|
|
47449
|
-
|
|
47450
|
-
return this.inf.format(fixed);
|
|
47451
|
-
} else {
|
|
47452
|
-
// to match the browser's numberformatter defaults
|
|
47453
|
-
const fixed = this.floor ? Math.floor(i) : roundTo(i, 3);
|
|
47454
|
-
return padStart(fixed, this.padTo);
|
|
47455
|
-
}
|
|
47456
|
-
}
|
|
47573
|
+
case "ccc":
|
|
47574
|
+
// like 'Tues'
|
|
47575
|
+
return weekday("short", true);
|
|
47457
47576
|
|
|
47458
|
-
|
|
47459
|
-
|
|
47460
|
-
|
|
47461
|
-
*/
|
|
47577
|
+
case "cccc":
|
|
47578
|
+
// like 'Tuesday'
|
|
47579
|
+
return weekday("long", true);
|
|
47462
47580
|
|
|
47581
|
+
case "ccccc":
|
|
47582
|
+
// like 'T'
|
|
47583
|
+
return weekday("narrow", true);
|
|
47584
|
+
// weekdays - format
|
|
47463
47585
|
|
|
47464
|
-
|
|
47465
|
-
|
|
47466
|
-
|
|
47467
|
-
let z;
|
|
47586
|
+
case "E":
|
|
47587
|
+
// like 1
|
|
47588
|
+
return this.num(dt.weekday);
|
|
47468
47589
|
|
|
47469
|
-
|
|
47470
|
-
|
|
47471
|
-
|
|
47472
|
-
// 1. Representing offset 0 when UTC is used to maintain previous behavior and does not become GMT.
|
|
47473
|
-
// 2. Unsupported by the browser:
|
|
47474
|
-
// - some do not support Etc/
|
|
47475
|
-
// - < Etc/GMT-14, > Etc/GMT+12, and 30-minute or 45-minute offsets are not part of tzdata
|
|
47476
|
-
const gmtOffset = -1 * (dt.offset / 60);
|
|
47477
|
-
const offsetZ = gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}`;
|
|
47590
|
+
case "EEE":
|
|
47591
|
+
// like 'Tues'
|
|
47592
|
+
return weekday("short", false);
|
|
47478
47593
|
|
|
47479
|
-
|
|
47480
|
-
|
|
47481
|
-
|
|
47482
|
-
} else {
|
|
47483
|
-
// Not all fixed-offset zones like Etc/+4:30 are present in tzdata.
|
|
47484
|
-
// So we have to make do. Two cases:
|
|
47485
|
-
// 1. The format options tell us to show the zone. We can't do that, so the best
|
|
47486
|
-
// we can do is format the date in UTC.
|
|
47487
|
-
// 2. The format options don't tell us to show the zone. Then we can adjust them
|
|
47488
|
-
// the time and tell the formatter to show it to us in UTC, so that the time is right
|
|
47489
|
-
// and the bad zone doesn't show up.
|
|
47490
|
-
z = "UTC";
|
|
47594
|
+
case "EEEE":
|
|
47595
|
+
// like 'Tuesday'
|
|
47596
|
+
return weekday("long", false);
|
|
47491
47597
|
|
|
47492
|
-
|
|
47493
|
-
|
|
47494
|
-
|
|
47495
|
-
|
|
47496
|
-
}
|
|
47497
|
-
}
|
|
47498
|
-
} else if (dt.zone.type === "system") {
|
|
47499
|
-
this.dt = dt;
|
|
47500
|
-
} else {
|
|
47501
|
-
this.dt = dt;
|
|
47502
|
-
z = dt.zone.name;
|
|
47503
|
-
}
|
|
47598
|
+
case "EEEEE":
|
|
47599
|
+
// like 'T'
|
|
47600
|
+
return weekday("narrow", false);
|
|
47601
|
+
// months - standalone
|
|
47504
47602
|
|
|
47505
|
-
|
|
47506
|
-
|
|
47603
|
+
case "L":
|
|
47604
|
+
// like 1
|
|
47605
|
+
return useDateTimeFormatter ? string({
|
|
47606
|
+
month: "numeric",
|
|
47607
|
+
day: "numeric"
|
|
47608
|
+
}, "month") : this.num(dt.month);
|
|
47507
47609
|
|
|
47508
|
-
|
|
47509
|
-
|
|
47510
|
-
|
|
47610
|
+
case "LL":
|
|
47611
|
+
// like 01, doesn't seem to work
|
|
47612
|
+
return useDateTimeFormatter ? string({
|
|
47613
|
+
month: "2-digit",
|
|
47614
|
+
day: "numeric"
|
|
47615
|
+
}, "month") : this.num(dt.month, 2);
|
|
47511
47616
|
|
|
47512
|
-
|
|
47513
|
-
|
|
47617
|
+
case "LLL":
|
|
47618
|
+
// like Jan
|
|
47619
|
+
return month("short", true);
|
|
47514
47620
|
|
|
47515
|
-
|
|
47516
|
-
|
|
47517
|
-
|
|
47621
|
+
case "LLLL":
|
|
47622
|
+
// like January
|
|
47623
|
+
return month("long", true);
|
|
47518
47624
|
|
|
47519
|
-
|
|
47520
|
-
|
|
47521
|
-
|
|
47625
|
+
case "LLLLL":
|
|
47626
|
+
// like J
|
|
47627
|
+
return month("narrow", true);
|
|
47628
|
+
// months - format
|
|
47522
47629
|
|
|
47523
|
-
|
|
47524
|
-
|
|
47525
|
-
|
|
47630
|
+
case "M":
|
|
47631
|
+
// like 1
|
|
47632
|
+
return useDateTimeFormatter ? string({
|
|
47633
|
+
month: "numeric"
|
|
47634
|
+
}, "month") : this.num(dt.month);
|
|
47526
47635
|
|
|
47527
|
-
|
|
47528
|
-
|
|
47529
|
-
|
|
47530
|
-
|
|
47636
|
+
case "MM":
|
|
47637
|
+
// like 01
|
|
47638
|
+
return useDateTimeFormatter ? string({
|
|
47639
|
+
month: "2-digit"
|
|
47640
|
+
}, "month") : this.num(dt.month, 2);
|
|
47531
47641
|
|
|
47642
|
+
case "MMM":
|
|
47643
|
+
// like Jan
|
|
47644
|
+
return month("short", false);
|
|
47532
47645
|
|
|
47533
|
-
|
|
47534
|
-
|
|
47535
|
-
|
|
47536
|
-
style: "long",
|
|
47537
|
-
...opts
|
|
47538
|
-
};
|
|
47646
|
+
case "MMMM":
|
|
47647
|
+
// like January
|
|
47648
|
+
return month("long", false);
|
|
47539
47649
|
|
|
47540
|
-
|
|
47541
|
-
|
|
47542
|
-
|
|
47543
|
-
|
|
47650
|
+
case "MMMMM":
|
|
47651
|
+
// like J
|
|
47652
|
+
return month("narrow", false);
|
|
47653
|
+
// years
|
|
47544
47654
|
|
|
47545
|
-
|
|
47546
|
-
|
|
47547
|
-
|
|
47548
|
-
|
|
47549
|
-
|
|
47550
|
-
}
|
|
47551
|
-
}
|
|
47655
|
+
case "y":
|
|
47656
|
+
// like 2014
|
|
47657
|
+
return useDateTimeFormatter ? string({
|
|
47658
|
+
year: "numeric"
|
|
47659
|
+
}, "year") : this.num(dt.year);
|
|
47552
47660
|
|
|
47553
|
-
|
|
47554
|
-
|
|
47555
|
-
|
|
47556
|
-
|
|
47557
|
-
|
|
47558
|
-
}
|
|
47559
|
-
}
|
|
47661
|
+
case "yy":
|
|
47662
|
+
// like 14
|
|
47663
|
+
return useDateTimeFormatter ? string({
|
|
47664
|
+
year: "2-digit"
|
|
47665
|
+
}, "year") : this.num(dt.year.toString().slice(-2), 2);
|
|
47560
47666
|
|
|
47561
|
-
|
|
47562
|
-
|
|
47563
|
-
|
|
47564
|
-
|
|
47667
|
+
case "yyyy":
|
|
47668
|
+
// like 0012
|
|
47669
|
+
return useDateTimeFormatter ? string({
|
|
47670
|
+
year: "numeric"
|
|
47671
|
+
}, "year") : this.num(dt.year, 4);
|
|
47565
47672
|
|
|
47673
|
+
case "yyyyyy":
|
|
47674
|
+
// like 000012
|
|
47675
|
+
return useDateTimeFormatter ? string({
|
|
47676
|
+
year: "numeric"
|
|
47677
|
+
}, "year") : this.num(dt.year, 6);
|
|
47678
|
+
// eras
|
|
47566
47679
|
|
|
47567
|
-
|
|
47568
|
-
|
|
47569
|
-
|
|
47570
|
-
}
|
|
47680
|
+
case "G":
|
|
47681
|
+
// like AD
|
|
47682
|
+
return era("short");
|
|
47571
47683
|
|
|
47572
|
-
|
|
47573
|
-
|
|
47684
|
+
case "GG":
|
|
47685
|
+
// like Anno Domini
|
|
47686
|
+
return era("long");
|
|
47574
47687
|
|
|
47575
|
-
|
|
47576
|
-
|
|
47577
|
-
const outputCalendarR = outputCalendar || Settings.defaultOutputCalendar;
|
|
47578
|
-
return new Locale(localeR, numberingSystemR, outputCalendarR, specifiedLocale);
|
|
47579
|
-
}
|
|
47688
|
+
case "GGGGG":
|
|
47689
|
+
return era("narrow");
|
|
47580
47690
|
|
|
47581
|
-
|
|
47582
|
-
|
|
47583
|
-
intlDTCache = {};
|
|
47584
|
-
intlNumCache = {};
|
|
47585
|
-
intlRelCache = {};
|
|
47586
|
-
}
|
|
47691
|
+
case "kk":
|
|
47692
|
+
return this.num(dt.weekYear.toString().slice(-2), 2);
|
|
47587
47693
|
|
|
47588
|
-
|
|
47589
|
-
|
|
47590
|
-
numberingSystem,
|
|
47591
|
-
outputCalendar
|
|
47592
|
-
} = {}) {
|
|
47593
|
-
return Locale.create(locale, numberingSystem, outputCalendar);
|
|
47594
|
-
}
|
|
47694
|
+
case "kkkk":
|
|
47695
|
+
return this.num(dt.weekYear, 4);
|
|
47595
47696
|
|
|
47596
|
-
|
|
47597
|
-
|
|
47598
|
-
this.locale = parsedLocale;
|
|
47599
|
-
this.numberingSystem = numbering || parsedNumberingSystem || null;
|
|
47600
|
-
this.outputCalendar = outputCalendar || parsedOutputCalendar || null;
|
|
47601
|
-
this.intl = intlConfigString(this.locale, this.numberingSystem, this.outputCalendar);
|
|
47602
|
-
this.weekdaysCache = {
|
|
47603
|
-
format: {},
|
|
47604
|
-
standalone: {}
|
|
47605
|
-
};
|
|
47606
|
-
this.monthsCache = {
|
|
47607
|
-
format: {},
|
|
47608
|
-
standalone: {}
|
|
47609
|
-
};
|
|
47610
|
-
this.meridiemCache = null;
|
|
47611
|
-
this.eraCache = {};
|
|
47612
|
-
this.specifiedLocale = specifiedLocale;
|
|
47613
|
-
this.fastNumbersCached = null;
|
|
47614
|
-
}
|
|
47697
|
+
case "W":
|
|
47698
|
+
return this.num(dt.weekNumber);
|
|
47615
47699
|
|
|
47616
|
-
|
|
47617
|
-
|
|
47618
|
-
this.fastNumbersCached = supportsFastNumbers(this);
|
|
47619
|
-
}
|
|
47700
|
+
case "WW":
|
|
47701
|
+
return this.num(dt.weekNumber, 2);
|
|
47620
47702
|
|
|
47621
|
-
|
|
47622
|
-
|
|
47703
|
+
case "o":
|
|
47704
|
+
return this.num(dt.ordinal);
|
|
47623
47705
|
|
|
47624
|
-
|
|
47625
|
-
|
|
47626
|
-
const hasNoWeirdness = (this.numberingSystem === null || this.numberingSystem === "latn") && (this.outputCalendar === null || this.outputCalendar === "gregory");
|
|
47627
|
-
return isActuallyEn && hasNoWeirdness ? "en" : "intl";
|
|
47628
|
-
}
|
|
47706
|
+
case "ooo":
|
|
47707
|
+
return this.num(dt.ordinal, 3);
|
|
47629
47708
|
|
|
47630
|
-
|
|
47631
|
-
|
|
47632
|
-
|
|
47633
|
-
} else {
|
|
47634
|
-
return Locale.create(alts.locale || this.specifiedLocale, alts.numberingSystem || this.numberingSystem, alts.outputCalendar || this.outputCalendar, alts.defaultToEN || false);
|
|
47635
|
-
}
|
|
47636
|
-
}
|
|
47709
|
+
case "q":
|
|
47710
|
+
// like 1
|
|
47711
|
+
return this.num(dt.quarter);
|
|
47637
47712
|
|
|
47638
|
-
|
|
47639
|
-
|
|
47640
|
-
|
|
47641
|
-
});
|
|
47642
|
-
}
|
|
47713
|
+
case "qq":
|
|
47714
|
+
// like 01
|
|
47715
|
+
return this.num(dt.quarter, 2);
|
|
47643
47716
|
|
|
47644
|
-
|
|
47645
|
-
|
|
47646
|
-
defaultToEN: false
|
|
47647
|
-
});
|
|
47648
|
-
}
|
|
47717
|
+
case "X":
|
|
47718
|
+
return this.num(Math.floor(dt.ts / 1000));
|
|
47649
47719
|
|
|
47650
|
-
|
|
47651
|
-
|
|
47652
|
-
const intl = format ? {
|
|
47653
|
-
month: length,
|
|
47654
|
-
day: "numeric"
|
|
47655
|
-
} : {
|
|
47656
|
-
month: length
|
|
47657
|
-
},
|
|
47658
|
-
formatStr = format ? "format" : "standalone";
|
|
47720
|
+
case "x":
|
|
47721
|
+
return this.num(dt.ts);
|
|
47659
47722
|
|
|
47660
|
-
|
|
47661
|
-
|
|
47723
|
+
default:
|
|
47724
|
+
return maybeMacro(token);
|
|
47662
47725
|
}
|
|
47726
|
+
};
|
|
47663
47727
|
|
|
47664
|
-
|
|
47665
|
-
});
|
|
47728
|
+
return stringifyTokens(Formatter.parseFormat(fmt), tokenToString);
|
|
47666
47729
|
}
|
|
47667
47730
|
|
|
47668
|
-
|
|
47669
|
-
|
|
47670
|
-
|
|
47671
|
-
|
|
47672
|
-
|
|
47673
|
-
month: "long",
|
|
47674
|
-
day: "numeric"
|
|
47675
|
-
} : {
|
|
47676
|
-
weekday: length
|
|
47677
|
-
},
|
|
47678
|
-
formatStr = format ? "format" : "standalone";
|
|
47679
|
-
|
|
47680
|
-
if (!this.weekdaysCache[formatStr][length]) {
|
|
47681
|
-
this.weekdaysCache[formatStr][length] = mapWeekdays(dt => this.extract(dt, intl, "weekday"));
|
|
47682
|
-
}
|
|
47731
|
+
formatDurationFromString(dur, fmt) {
|
|
47732
|
+
const tokenToField = token => {
|
|
47733
|
+
switch (token[0]) {
|
|
47734
|
+
case "S":
|
|
47735
|
+
return "millisecond";
|
|
47683
47736
|
|
|
47684
|
-
|
|
47685
|
-
|
|
47686
|
-
}
|
|
47737
|
+
case "s":
|
|
47738
|
+
return "second";
|
|
47687
47739
|
|
|
47688
|
-
|
|
47689
|
-
|
|
47690
|
-
// In theory there could be aribitrary day periods. We're gonna assume there are exactly two
|
|
47691
|
-
// for AM and PM. This is probably wrong, but it's makes parsing way easier.
|
|
47692
|
-
if (!this.meridiemCache) {
|
|
47693
|
-
const intl = {
|
|
47694
|
-
hour: "numeric",
|
|
47695
|
-
hourCycle: "h12"
|
|
47696
|
-
};
|
|
47697
|
-
this.meridiemCache = [DateTime.utc(2016, 11, 13, 9), DateTime.utc(2016, 11, 13, 19)].map(dt => this.extract(dt, intl, "dayperiod"));
|
|
47698
|
-
}
|
|
47740
|
+
case "m":
|
|
47741
|
+
return "minute";
|
|
47699
47742
|
|
|
47700
|
-
|
|
47701
|
-
|
|
47702
|
-
}
|
|
47743
|
+
case "h":
|
|
47744
|
+
return "hour";
|
|
47703
47745
|
|
|
47704
|
-
|
|
47705
|
-
|
|
47706
|
-
const intl = {
|
|
47707
|
-
era: length
|
|
47708
|
-
}; // This is problematic. Different calendars are going to define eras totally differently. What I need is the minimum set of dates
|
|
47709
|
-
// to definitely enumerate them.
|
|
47746
|
+
case "d":
|
|
47747
|
+
return "day";
|
|
47710
47748
|
|
|
47711
|
-
|
|
47712
|
-
|
|
47713
|
-
}
|
|
47749
|
+
case "w":
|
|
47750
|
+
return "week";
|
|
47714
47751
|
|
|
47715
|
-
|
|
47716
|
-
|
|
47717
|
-
}
|
|
47752
|
+
case "M":
|
|
47753
|
+
return "month";
|
|
47718
47754
|
|
|
47719
|
-
|
|
47720
|
-
|
|
47721
|
-
results = df.formatToParts(),
|
|
47722
|
-
matching = results.find(m => m.type.toLowerCase() === field);
|
|
47723
|
-
return matching ? matching.value : null;
|
|
47724
|
-
}
|
|
47755
|
+
case "y":
|
|
47756
|
+
return "year";
|
|
47725
47757
|
|
|
47726
|
-
|
|
47727
|
-
|
|
47728
|
-
|
|
47729
|
-
|
|
47730
|
-
|
|
47758
|
+
default:
|
|
47759
|
+
return null;
|
|
47760
|
+
}
|
|
47761
|
+
},
|
|
47762
|
+
tokenToString = lildur => token => {
|
|
47763
|
+
const mapped = tokenToField(token);
|
|
47731
47764
|
|
|
47732
|
-
|
|
47733
|
-
|
|
47734
|
-
|
|
47765
|
+
if (mapped) {
|
|
47766
|
+
return this.num(lildur.get(mapped), token.length);
|
|
47767
|
+
} else {
|
|
47768
|
+
return token;
|
|
47769
|
+
}
|
|
47770
|
+
},
|
|
47771
|
+
tokens = Formatter.parseFormat(fmt),
|
|
47772
|
+
realTokens = tokens.reduce((found, {
|
|
47773
|
+
literal,
|
|
47774
|
+
val
|
|
47775
|
+
}) => literal ? found : found.concat(val), []),
|
|
47776
|
+
collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter(t => t));
|
|
47735
47777
|
|
|
47736
|
-
|
|
47737
|
-
return new PolyRelFormatter(this.intl, this.isEnglish(), opts);
|
|
47778
|
+
return stringifyTokens(tokens, tokenToString(collapsed));
|
|
47738
47779
|
}
|
|
47739
47780
|
|
|
47740
|
-
|
|
47741
|
-
return getCachedLF(this.intl, opts);
|
|
47742
|
-
}
|
|
47781
|
+
}
|
|
47743
47782
|
|
|
47744
|
-
|
|
47745
|
-
|
|
47783
|
+
class Invalid {
|
|
47784
|
+
constructor(reason, explanation) {
|
|
47785
|
+
this.reason = reason;
|
|
47786
|
+
this.explanation = explanation;
|
|
47746
47787
|
}
|
|
47747
47788
|
|
|
47748
|
-
|
|
47749
|
-
|
|
47789
|
+
toMessage() {
|
|
47790
|
+
if (this.explanation) {
|
|
47791
|
+
return `${this.reason}: ${this.explanation}`;
|
|
47792
|
+
} else {
|
|
47793
|
+
return this.reason;
|
|
47794
|
+
}
|
|
47750
47795
|
}
|
|
47751
47796
|
|
|
47752
47797
|
}
|
|
@@ -47761,6 +47806,8 @@ class Locale {
|
|
|
47761
47806
|
* Some extractions are super dumb and simpleParse and fromStrings help DRY them.
|
|
47762
47807
|
*/
|
|
47763
47808
|
|
|
47809
|
+
const ianaRegex = /[A-Za-z_+-]{1,256}(?::?\/[A-Za-z0-9_+-]{1,256}(?:\/[A-Za-z0-9_+-]{1,256})?)?/;
|
|
47810
|
+
|
|
47764
47811
|
function combineRegexes(...regexes) {
|
|
47765
47812
|
const full = regexes.reduce((f, r) => f + r.source, "");
|
|
47766
47813
|
return RegExp(`^${full}$`);
|
|
@@ -53026,7 +53073,7 @@ function friendlyDateTime(dateTimeish) {
|
|
|
53026
53073
|
}
|
|
53027
53074
|
}
|
|
53028
53075
|
|
|
53029
|
-
const VERSION = "3.1.
|
|
53076
|
+
const VERSION = "3.1.1";
|
|
53030
53077
|
|
|
53031
53078
|
exports.DateTime = DateTime;
|
|
53032
53079
|
exports.Duration = Duration;
|