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