From f257940093dca8efa976e142e0f33ed3620425ed Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Mon, 22 Jan 2024 15:19:00 -0700 Subject: [PATCH] Validate time zone in quickDT prior to guessing offset (#1575) We validate the zone in the constructor anyway, but the tests missed a branch where we attempt to use an invalid zone to compute an offset, which will result in an exception. Zone#isValid is calculated at creation time (and checked in DateTime constructor already) so this will not degrade performance in the happy case. --- src/datetime.js | 8 ++++++-- test/datetime/invalid.test.js | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/datetime.js b/src/datetime.js index 9472cb53..85533dda 100644 --- a/src/datetime.js +++ b/src/datetime.js @@ -373,8 +373,12 @@ function normalizeUnitWithLocalWeeks(unit) { // but doesn't do any validation, makes a bunch of assumptions about what units // are present, and so on. function quickDT(obj, opts) { - const zone = normalizeZone(opts.zone, Settings.defaultZone), - loc = Locale.fromObject(opts), + const zone = normalizeZone(opts.zone, Settings.defaultZone); + if (!zone.isValid) { + return DateTime.invalid(unsupportedZone(zone)); + } + + const loc = Locale.fromObject(opts), tsNow = Settings.now(); let ts, o; diff --git a/test/datetime/invalid.test.js b/test/datetime/invalid.test.js index d13fb864..2fed5bbd 100644 --- a/test/datetime/invalid.test.js +++ b/test/datetime/invalid.test.js @@ -5,7 +5,11 @@ import { DateTime, Settings } from "../../src/luxon"; const organic1 = DateTime.utc(2014, 13, 33), // not an actual Wednesday organic2 = DateTime.fromObject({ weekday: 3, year: 1982, month: 5, day: 25 }, { zone: "UTC" }), - organic3 = DateTime.fromObject({ year: 1982, month: 5, day: 25, hour: 27 }); + organic3 = DateTime.fromObject({ year: 1982, month: 5, day: 25, hour: 27 }), + organic4 = DateTime.fromObject( + { year: 1982, month: 5, day: 25, hour: 2 }, + { zone: "America/Lasers" } + ); test("Explicitly invalid dates are invalid", () => { const dt = DateTime.invalid("just because", "seriously, just because"); @@ -22,14 +26,28 @@ test("Invalid creations are invalid", () => { test("invalid zones result in invalid dates", () => { expect(DateTime.now().setZone("America/Lasers").isValid).toBe(false); + expect(DateTime.now().setZone("America/Lasers").invalidReason).toBe("unsupported zone"); + expect(DateTime.local({ zone: "America/Lasers" }).isValid).toBe(false); + expect(DateTime.local({ zone: "America/Lasers" }).invalidReason).toBe("unsupported zone"); + + expect(DateTime.local(1982, { zone: "America/Lasers" }).isValid).toBe(false); + expect(DateTime.local(1982, { zone: "America/Lasers" }).invalidReason).toBe("unsupported zone"); + expect(DateTime.fromJSDate(new Date(), { zone: "America/Lasers" }).isValid).toBe(false); + expect(DateTime.fromJSDate(new Date(), { zone: "America/Lasers" }).invalidReason).toBe( + "unsupported zone" + ); + + expect(DateTime.fromMillis(0, { zone: "America/Lasers" }).isValid).toBe(false); + expect(DateTime.fromMillis(0, { zone: "America/Lasers" }).invalidReason).toBe("unsupported zone"); }); test("Invalid DateTimes tell you why", () => { expect(organic1.invalidReason).toBe("unit out of range"); expect(organic2.invalidReason).toBe("mismatched weekday"); expect(organic3.invalidReason).toBe("unit out of range"); + expect(organic4.invalidReason).toBe("unsupported zone"); }); test("Invalid DateTimes can provide an extended explanation", () => {