diff --git a/package-lock.json b/package-lock.json index 41428ff9d..99cc8264f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,12 @@ { "name": "luxon", - "version": "2.0.1", + "version": "2.0.2", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "2.0.1", + "name": "luxon", + "version": "2.0.2", "license": "MIT", "devDependencies": { "@babel/core": "^7.14.6", @@ -29,7 +30,7 @@ "uglify-js": "^3.13.10" }, "engines": { - "node": "*" + "node": ">=12" } }, "node_modules/@babel/code-frame": { diff --git a/src/impl/util.js b/src/impl/util.js index f576c5e72..9f267211f 100644 --- a/src/impl/util.js +++ b/src/impl/util.js @@ -272,4 +272,4 @@ export function timeObject(obj) { return pick(obj, ["hour", "minute", "second", "millisecond"]); } -export const ianaRegex = /[A-Za-z_+-]{1,256}(:?\/[A-Za-z_+-]{1,256}(\/[A-Za-z_+-]{1,256})?)?/; +export const ianaRegex = /[A-Za-z_+-]{1,256}(:?\/[A-Za-z0-9_+-]{1,256}(\/[A-Za-z0-9_+-]{1,256})?)?/; diff --git a/src/impl/zoneUtil.js b/src/impl/zoneUtil.js index 1931439af..4b38ea949 100644 --- a/src/impl/zoneUtil.js +++ b/src/impl/zoneUtil.js @@ -19,10 +19,7 @@ export function normalizeZone(input, defaultZone) { const lowered = input.toLowerCase(); if (lowered === "local" || lowered === "system") return defaultZone; else if (lowered === "utc" || lowered === "gmt") return FixedOffsetZone.utcInstance; - else if ((offset = IANAZone.parseGMTOffset(input)) != null) { - // handle Etc/GMT-4, which V8 chokes on - return FixedOffsetZone.instance(offset); - } else if (IANAZone.isValidSpecifier(lowered)) return IANAZone.create(input); + else if (IANAZone.isValidSpecifier(lowered)) return IANAZone.create(input); else return FixedOffsetZone.parseSpecifier(lowered) || new InvalidZone(input); } else if (isNumber(input)) { return FixedOffsetZone.instance(input); diff --git a/src/zones/IANAZone.js b/src/zones/IANAZone.js index 5975598a5..b143dfb11 100644 --- a/src/zones/IANAZone.js +++ b/src/zones/IANAZone.js @@ -108,18 +108,6 @@ export default class IANAZone extends Zone { } } - // Etc/GMT+8 -> -480 - /** @ignore */ - static parseGMTOffset(specifier) { - if (specifier) { - const match = specifier.match(/^Etc\/GMT(0|[+-]\d{1,2})$/i); - if (match) { - return -60 * parseInt(match[1]); - } - } - return null; - } - constructor(name) { super(); /** @private **/ diff --git a/test/datetime/zone.test.js b/test/datetime/zone.test.js index 149a88354..4d5fb5480 100644 --- a/test/datetime/zone.test.js +++ b/test/datetime/zone.test.js @@ -236,13 +236,16 @@ test("DateTime#offsetNameShort returns null for invalid times", () => { //------ // Etc/GMT zones //------ -test("Etc/GMT zones work even though V8 does not support them", () => { - let zoned = DateTime.local().setZone("Etc/GMT+8"); - expect(zoned.zoneName).toBe("UTC-8"); - zoned = DateTime.local().setZone("Etc/GMT-5"); - expect(zoned.zoneName).toBe("UTC+5"); - zoned = DateTime.local().setZone("Etc/GMT-0"); - expect(zoned.zoneName).toBe("UTC"); +test.each([ + ["Etc/GMT+8", -8], + ["Etc/GMT-5", 5], + ["Etc/GMT", 0], + ["Etc/GMT-0", 0], + ["Etc/GMT", 0], +])("Etc/GMTx zones now work natively", (zone, expectedOffset) => { + let zoned = dt().setZone(zone); + expect(zoned.isValid).toBe(true); + expect(zoned.offset).toEqual(expectedOffset * 60); }); //------ diff --git a/test/info/zones.test.js b/test/info/zones.test.js index 039ced12b..de8341705 100644 --- a/test/info/zones.test.js +++ b/test/info/zones.test.js @@ -88,8 +88,8 @@ test.each([ ["System", SystemZone.instance], ["UTC", FixedOffsetZone.utcInstance], ["GMT", FixedOffsetZone.utcInstance], - ["Etc/GMT+5", FixedOffsetZone.instance(-5 * 60)], - ["Etc/GMT-10", FixedOffsetZone.instance(+10 * 60)], + ["Etc/GMT+5", new IANAZone("Etc/GMT+5")], + ["Etc/GMT-10", new IANAZone("Etc/GMT-10")], ["Europe/Paris", new IANAZone("Europe/Paris")], [0, FixedOffsetZone.utcInstance], [3, FixedOffsetZone.instance(3)], diff --git a/test/zones/IANA.test.js b/test/zones/IANA.test.js index 62b420ce2..a38789d1a 100644 --- a/test/zones/IANA.test.js +++ b/test/zones/IANA.test.js @@ -21,6 +21,10 @@ test("IANAZone.isValidSpecifier", () => { expect(IANAZone.isValidSpecifier("America/New_York")).toBe(true); expect(IANAZone.isValidSpecifier("Fantasia/Castle")).toBe(true); expect(IANAZone.isValidSpecifier("Sport~~blorp")).toBe(false); + expect(IANAZone.isValidSpecifier("Etc/GMT+8")).toBe(true); + expect(IANAZone.isValidSpecifier("Etc/GMT-8")).toBe(true); + expect(IANAZone.isValidSpecifier("Etc/GMT-0")).toBe(true); + expect(IANAZone.isValidSpecifier("Etc/GMT-1")).toBe(true); expect(IANAZone.isValidSpecifier(null)).toBe(false); }); @@ -34,21 +38,6 @@ test("IANAZone.isValidZone", () => { expect(IANAZone.isValidZone(4)).toBe(false); }); -test("IANAZone.parseGMTOffset returns a number for a valid input", () => { - expect(IANAZone.parseGMTOffset("Etc/GMT+8")).toBe(-480); - expect(IANAZone.parseGMTOffset("Etc/GMT+0")).toBe(-0); - expect(IANAZone.parseGMTOffset("Etc/GMT-0")).toBe(+0); - expect(IANAZone.parseGMTOffset("Etc/GMT0")).toBe(-0); -}); - -test("IANAZone.parseGMTOffset returns null for invalid input", () => { - expect(IANAZone.parseGMTOffset()).toBe(null); - expect(IANAZone.parseGMTOffset(null)).toBe(null); - expect(IANAZone.parseGMTOffset("")).toBe(null); - expect(IANAZone.parseGMTOffset("foo")).toBe(null); - expect(IANAZone.parseGMTOffset("Etc/GMT+blorp")).toBe(null); -}); - test("IANAZone.type returns a static string", () => { expect(new IANAZone("America/Santiago").type).toBe("iana"); expect(new IANAZone("America/Blorp").type).toBe("iana");