Skip to content

Commit

Permalink
Fix support for Node.js 18.13+ (#1369)
Browse files Browse the repository at this point in the history
Macro tokens are now treat non-breaking white-space equally when parsing.

---------

Co-authored-by: Take Weiland <[email protected]>
  • Loading branch information
mohd-akram and diesieben07 authored Feb 28, 2023
1 parent c5a6b0a commit 0c50b70
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 60 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

strategy:
matrix:
node-version: [18.9]
node-version: [18.13]

steps:
- uses: actions/checkout@v2
Expand Down
9 changes: 6 additions & 3 deletions src/impl/formatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export default class Formatter {
}

static parseFormat(fmt) {
// white-space is always considered a literal in user-provided formats
// the " " token has a special meaning (see unitForToken)

let current = null,
currentFull = "",
bracketed = false;
Expand All @@ -55,7 +58,7 @@ export default class Formatter {
const c = fmt.charAt(i);
if (c === "'") {
if (currentFull.length > 0) {
splits.push({ literal: bracketed, val: currentFull });
splits.push({ literal: bracketed || /^\s+$/.test(currentFull), val: currentFull });
}
current = null;
currentFull = "";
Expand All @@ -66,15 +69,15 @@ export default class Formatter {
currentFull += c;
} else {
if (currentFull.length > 0) {
splits.push({ literal: false, val: currentFull });
splits.push({ literal: /^\s+$/.test(currentFull), val: currentFull });
}
currentFull = c;
current = c;
}
}

if (currentFull.length > 0) {
splits.push({ literal: bracketed, val: currentFull });
splits.push({ literal: bracketed || /^\s+$/.test(currentFull), val: currentFull });
}

return splits;
Expand Down
9 changes: 7 additions & 2 deletions src/impl/tokenParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ function unitForToken(token, loc) {
// because we don't have any way to figure out what they are
case "z":
return simple(/[a-z_+-/]{1,256}?/i);
// this special-case "token" represents a place where a macro-token expanded into a white-space literal
// in this case we accept any non-newline white-space
case " ":
return simple(/[^\S\n\r]/);
default:
return literal(t);
}
Expand Down Expand Up @@ -237,9 +241,10 @@ function tokenForPart(part, formatOpts) {
const { type, value } = part;

if (type === "literal") {
const isSpace = /^\s+$/.test(value);
return {
literal: true,
val: value,
literal: !isSpace,
val: isSpace ? " " : value,
};
}

Expand Down
14 changes: 7 additions & 7 deletions test/datetime/format.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -376,34 +376,34 @@ test("DateTime#toLocaleString() returns something different for invalid DateTime

test("DateTime#toLocaleString() shows things in the right IANA zone", () => {
expect(dt.setZone("America/New_York").toLocaleString(DateTime.DATETIME_SHORT)).toBe(
"5/25/1982, 5:23 AM"
"5/25/1982, 5:23AM"
);
});

test("DateTime#toLocaleString() shows things in the right fixed-offset zone", () => {
expect(dt.setZone("UTC-8").toLocaleString(DateTime.DATETIME_SHORT)).toBe("5/25/1982, 1:23 AM");
expect(dt.setZone("UTC-8").toLocaleString(DateTime.DATETIME_SHORT)).toBe("5/25/1982, 1:23AM");
});

test("DateTime#toLocaleString() shows things in the right fixed-offset zone when showing the zone", () => {
expect(dt.setZone("UTC-8").toLocaleString(DateTime.DATETIME_FULL)).toBe(
"May 25, 1982 at 1:23 AM GMT-8"
"May 25, 1982 at 1:23AM GMT-8"
);
});

test("DateTime#toLocaleString() shows things with UTC if fixed-offset zone with 0 offset is used", () => {
expect(dt.setZone("UTC").toLocaleString(DateTime.DATETIME_FULL)).toBe(
"May 25, 1982 at 9:23 AM UTC"
"May 25, 1982 at 9:23AM UTC"
);
});

test("DateTime#toLocaleString() does the best it can with unsupported fixed-offset zone when showing the zone", () => {
expect(dt.setZone("UTC+4:30").toLocaleString(DateTime.DATETIME_FULL)).toBe(
"May 25, 1982 at 9:23 AM UTC"
"May 25, 1982 at 9:23AM UTC"
);
});

test("DateTime#toLocaleString uses locale-appropriate time formats", () => {
expect(dt.reconfigure({ locale: "en-US" }).toLocaleString(DateTime.TIME_SIMPLE)).toBe("9:23 AM");
expect(dt.reconfigure({ locale: "en-US" }).toLocaleString(DateTime.TIME_SIMPLE)).toBe("9:23AM");
expect(dt.reconfigure({ locale: "en-US" }).toLocaleString(DateTime.TIME_24_SIMPLE)).toBe("09:23");

// France has 24-hour time by default
Expand All @@ -429,7 +429,7 @@ test("DateTime#toLocaleString() accepts a zone even when the zone is set", () =>
timeZoneName: "short",
timeZone: "America/Los_Angeles",
})
).toBe("2:23 AM PDT");
).toBe("2:23AM PDT");
});

//------
Expand Down
60 changes: 30 additions & 30 deletions test/datetime/toFormat.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,8 @@ test("DateTime#toFormat('DDDD') returns a long date representation", () => {
});

test("DateTime#toFormat('t') returns a short time representation", () => {
expect(dt.toFormat("t")).toBe("9:23 AM");
expect(dt.set({ hour: 13 }).toFormat("t")).toBe("1:23 PM");
expect(dt.toFormat("t")).toBe("9:23AM");
expect(dt.set({ hour: 13 }).toFormat("t")).toBe("1:23PM");
expect(dt.reconfigure({ locale: "fr" }).toFormat("t")).toBe("09:23");
expect(dt.set({ hour: 13 }).reconfigure({ locale: "fr" }).toFormat("t")).toBe("13:23");
});
Expand All @@ -384,8 +384,8 @@ test("DateTime#toFormat('T') returns a short 24-hour time representation", () =>
});

test("DateTime#toFormat('tt') returns a medium time representation", () => {
expect(dt.toFormat("tt")).toBe("9:23:54 AM");
expect(dt.set({ hour: 13 }).toFormat("tt")).toBe("1:23:54 PM");
expect(dt.toFormat("tt")).toBe("9:23:54AM");
expect(dt.set({ hour: 13 }).toFormat("tt")).toBe("1:23:54PM");
expect(dt.reconfigure({ locale: "fr" }).toFormat("tt")).toBe("09:23:54");
expect(dt.set({ hour: 13 }).reconfigure({ locale: "fr" }).toFormat("tt")).toBe("13:23:54");
});
Expand Down Expand Up @@ -414,16 +414,16 @@ test("DateTime#toFormat('TTT') returns a medium time representation", () => {
});

test("DateTime#toFormat('f') returns a short date/time representation without seconds", () => {
expect(dt.toFormat("f")).toBe("5/25/1982, 9:23 AM");
expect(dt.set({ hour: 13 }).toFormat("f")).toBe("5/25/1982, 1:23 PM");
expect(dt.toFormat("f")).toBe("5/25/1982, 9:23AM");
expect(dt.set({ hour: 13 }).toFormat("f")).toBe("5/25/1982, 1:23PM");
expect(dt.reconfigure({ locale: "fr" }).toFormat("f")).toBe("25/05/1982 09:23");
expect(dt.set({ hour: 13 }).reconfigure({ locale: "fr" }).toFormat("f")).toBe("25/05/1982 13:23");
});

test("DateTime#toFormat('ff') returns a medium date/time representation without seconds", () => {
expect(dt.toFormat("ff")).toBe("May 25, 1982, 9:23 AM");
expect(dt.set({ hour: 13 }).toFormat("ff")).toBe("May 25, 1982, 1:23 PM");
expect(dt.set({ month: 8 }).toFormat("ff")).toBe("Aug 25, 1982, 9:23 AM");
expect(dt.toFormat("ff")).toBe("May 25, 1982, 9:23AM");
expect(dt.set({ hour: 13 }).toFormat("ff")).toBe("May 25, 1982, 1:23PM");
expect(dt.set({ month: 8 }).toFormat("ff")).toBe("Aug 25, 1982, 9:23AM");
expect(dt.reconfigure({ locale: "fr" }).toFormat("ff")).toBe("25 mai 1982, 09:23");
expect(dt.set({ month: 2 }).reconfigure({ locale: "fr" }).toFormat("ff")).toBe(
"25 févr. 1982, 09:23"
Expand All @@ -434,9 +434,9 @@ test("DateTime#toFormat('ff') returns a medium date/time representation without
});

test("DateTime#toFormat('fff') returns a medium date/time representation without seconds", () => {
expect(ny.toFormat("fff")).toBe("May 25, 1982 at 9:23 AM EDT");
expect(ny.set({ hour: 13 }).toFormat("fff")).toBe("May 25, 1982 at 1:23 PM EDT");
expect(ny.set({ month: 8 }).toFormat("fff")).toBe("August 25, 1982 at 9:23 AM EDT");
expect(ny.toFormat("fff")).toBe("May 25, 1982 at 9:23AM EDT");
expect(ny.set({ hour: 13 }).toFormat("fff")).toBe("May 25, 1982 at 1:23PM EDT");
expect(ny.set({ month: 8 }).toFormat("fff")).toBe("August 25, 1982 at 9:23AM EDT");
expect(ny.reconfigure({ locale: "fr" }).toFormat("fff")).toBe("25 mai 1982 à 09:23 UTC−4");
expect(ny.set({ month: 2 }).reconfigure({ locale: "fr" }).toFormat("fff")).toBe(
"25 février 1982 à 09:23 UTC−5"
Expand All @@ -447,37 +447,37 @@ test("DateTime#toFormat('fff') returns a medium date/time representation without
});

test("DateTime#toFormat('ffff') returns a long date/time representation without seconds", () => {
expect(ny.toFormat("ffff")).toBe("Tuesday, May 25, 1982 at 9:23 AM Eastern Daylight Time");
expect(ny.toFormat("ffff")).toBe("Tuesday, May 25, 1982 at 9:23AM Eastern Daylight Time");
expect(ny.set({ hour: 13 }).toFormat("ffff")).toBe(
"Tuesday, May 25, 1982 at 1:23 PM Eastern Daylight Time"
"Tuesday, May 25, 1982 at 1:23PM Eastern Daylight Time"
);
expect(ny.set({ month: 2 }).toFormat("ffff")).toBe(
"Thursday, February 25, 1982 at 9:23 AM Eastern Standard Time"
"Thursday, February 25, 1982 at 9:23AM Eastern Standard Time"
);
expect(ny.reconfigure({ locale: "fr" }).toFormat("ffff")).toBe(
"mardi 25 mai 1982 à 09:23 heure d’été de l’Est"
"mardi 25 mai 1982 à 09:23 heure d’été de l’Est nord-américain"
);
expect(ny.set({ month: 2 }).reconfigure({ locale: "fr" }).toFormat("ffff")).toBe(
"jeudi 25 février 1982 à 09:23 heure normale de l’Est nord-américain"
);
expect(ny.set({ hour: 13 }).reconfigure({ locale: "fr" }).toFormat("ffff")).toBe(
"mardi 25 mai 1982 à 13:23 heure d’été de l’Est"
"mardi 25 mai 1982 à 13:23 heure d’été de l’Est nord-américain"
);
});

test("DateTime#toFormat('F') returns a short date/time representation with seconds", () => {
expect(dt.toFormat("F")).toBe("5/25/1982, 9:23:54 AM");
expect(dt.set({ hour: 13 }).toFormat("F")).toBe("5/25/1982, 1:23:54 PM");
expect(dt.toFormat("F")).toBe("5/25/1982, 9:23:54AM");
expect(dt.set({ hour: 13 }).toFormat("F")).toBe("5/25/1982, 1:23:54PM");
expect(dt.reconfigure({ locale: "fr" }).toFormat("F")).toBe("25/05/1982 09:23:54");
expect(dt.set({ hour: 13 }).reconfigure({ locale: "fr" }).toFormat("F")).toBe(
"25/05/1982 13:23:54"
);
});

test("DateTime#toFormat('FF') returns a medium date/time representation with seconds", () => {
expect(dt.toFormat("FF")).toBe("May 25, 1982, 9:23:54 AM");
expect(dt.set({ hour: 13 }).toFormat("FF")).toBe("May 25, 1982, 1:23:54 PM");
expect(dt.set({ month: 8 }).toFormat("FF")).toBe("Aug 25, 1982, 9:23:54 AM");
expect(dt.toFormat("FF")).toBe("May 25, 1982, 9:23:54AM");
expect(dt.set({ hour: 13 }).toFormat("FF")).toBe("May 25, 1982, 1:23:54PM");
expect(dt.set({ month: 8 }).toFormat("FF")).toBe("Aug 25, 1982, 9:23:54AM");
expect(dt.reconfigure({ locale: "fr" }).toFormat("FF")).toBe("25 mai 1982, 09:23:54");
expect(dt.set({ month: 2 }).reconfigure({ locale: "fr" }).toFormat("FF")).toBe(
"25 févr. 1982, 09:23:54"
Expand All @@ -488,9 +488,9 @@ test("DateTime#toFormat('FF') returns a medium date/time representation with sec
});

test("DateTime#toFormat('FFF') returns a medium date/time representation without seconds", () => {
expect(ny.toFormat("FFF")).toBe("May 25, 1982 at 9:23:54 AM EDT");
expect(ny.set({ hour: 13 }).toFormat("FFF")).toBe("May 25, 1982 at 1:23:54 PM EDT");
expect(ny.set({ month: 8 }).toFormat("FFF")).toBe("August 25, 1982 at 9:23:54 AM EDT");
expect(ny.toFormat("FFF")).toBe("May 25, 1982 at 9:23:54AM EDT");
expect(ny.set({ hour: 13 }).toFormat("FFF")).toBe("May 25, 1982 at 1:23:54PM EDT");
expect(ny.set({ month: 8 }).toFormat("FFF")).toBe("August 25, 1982 at 9:23:54AM EDT");
expect(ny.reconfigure({ locale: "fr" }).toFormat("FFF")).toBe("25 mai 1982 à 9:23:54 UTC−4");
expect(ny.set({ month: 2 }).reconfigure({ locale: "fr" }).toFormat("FFF")).toBe(
"25 février 1982 à 9:23:54 UTC−5"
Expand All @@ -501,21 +501,21 @@ test("DateTime#toFormat('FFF') returns a medium date/time representation without
});

test("DateTime#toFormat('FFFF') returns a long date/time representation without seconds", () => {
expect(ny.toFormat("FFFF")).toBe("Tuesday, May 25, 1982 at 9:23:54 AM Eastern Daylight Time");
expect(ny.toFormat("FFFF")).toBe("Tuesday, May 25, 1982 at 9:23:54AM Eastern Daylight Time");
expect(ny.set({ hour: 13 }).toFormat("FFFF")).toBe(
"Tuesday, May 25, 1982 at 1:23:54 PM Eastern Daylight Time"
"Tuesday, May 25, 1982 at 1:23:54PM Eastern Daylight Time"
);
expect(ny.set({ month: 2 }).toFormat("FFFF")).toBe(
"Thursday, February 25, 1982 at 9:23:54 AM Eastern Standard Time"
"Thursday, February 25, 1982 at 9:23:54AM Eastern Standard Time"
);
expect(ny.reconfigure({ locale: "fr" }).toFormat("FFFF")).toBe(
"mardi 25 mai 1982 à 9:23:54 heure d’été de l’Est"
"mardi 25 mai 1982 à 9:23:54 heure d’été de l’Est nord-américain"
);
expect(ny.set({ month: 2 }).reconfigure({ locale: "fr" }).toFormat("FFFF")).toBe(
"jeudi 25 février 1982 à 9:23:54 heure normale de l’Est nord-américain"
);
expect(ny.set({ hour: 13 }).reconfigure({ locale: "fr" }).toFormat("FFFF")).toBe(
"mardi 25 mai 1982 à 13:23:54 heure d’été de l’Est"
"mardi 25 mai 1982 à 13:23:54 heure d’été de l’Est nord-américain"
);
});

Expand Down
6 changes: 6 additions & 0 deletions test/datetime/tokenParse.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,12 @@ test("DateTime.fromFormat() parses localized macro tokens", () => {
}
});

test("DateTime.fromFormat() allows non-breaking white-space to be substituted inside macro-tokens", () => {
expect(DateTime.fromFormat("5:54 PM", "t", { locale: "en-US" }).isValid).toBe(true);
expect(DateTime.fromFormat("5:54 PM", "t", { locale: "en-US" }).isValid).toBe(true);
expect(DateTime.fromFormat("5:54\nPM", "t", { locale: "en-US" }).isValid).toBe(false);
});

test("DateTime.fromFormat() throws if you don't provide a format", () => {
expect(() => DateTime.fromFormat("yo")).toThrowError();
});
Expand Down
Loading

0 comments on commit 0c50b70

Please sign in to comment.