From e4b3c1bbfaa78a55fc6cacf87f634d591e5e656f Mon Sep 17 00:00:00 2001 From: Dasa Paddock Date: Tue, 28 Sep 2021 09:07:13 -0700 Subject: [PATCH] Add support for formatting and parsing tokens `uu` and `uuu` (#976) --- CONTRIBUTING.md | 2 +- docs/formatting.md | 2 ++ docs/parsing.md | 2 ++ src/impl/formatter.js | 5 +++++ src/impl/tokenParser.js | 4 ++++ test/datetime/toFormat.test.js | 12 ++++++++++++ test/datetime/tokenParse.test.js | 8 ++++++++ 7 files changed, 34 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 96554b31b..b01cdc70f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,7 +65,7 @@ Once you're sure your bugfix or feature makes sense for Luxon, make sure you tak 1. Be sure you run `npm run format` before you commit. Note this will modify your source files to line up with the style guidelines. 1. Make sure you add or ESDoc annotations appropriately. You can run `npm run docs` to generate the HTML for them. They land in the `build/docs` directory. This also builds the markdown files in `/docs` into the guide on the Luxon website. 1. To test Luxon in your browser, run `npm run site` and then open `build/demo/global.html`. You can access Luxon classes in the console like `window.luxon.DateTime`. -1. To test in Node, run `npm run build` and then run something like `var DateTime = require('./build/cjs/luxon').DateTime`. +1. To test in Node, run `npm run build` and then run something like `var DateTime = require('./build/cjs-browser/luxon').DateTime`. Luxon uses [Husky](https://github.com/typicode/husky) to run the formatter on your code as a pre-commit hook. You should still run `npm run format` yourself to catch other issues, but this hook will help prevent you from failing the build with a trivial formatting error. diff --git a/docs/formatting.md b/docs/formatting.md index 3e05c81f6..7eb1dd611 100644 --- a/docs/formatting.md +++ b/docs/formatting.md @@ -180,6 +180,8 @@ The macro options available correspond one-to-one with the preset formats define | S | | millisecond, no padding | `54` | | SSS | | millisecond, padded to 3 | `054` | | u | | fractional seconds, functionally identical to SSS | `054` | +| uu | | fractional seconds, between 0 and 99, padded to 2 | `05` | +| uuu | | fractional seconds, between 0 and 9 | `0` | | s | | second, no padding | `4` | | ss | | second, padded to 2 padding | `04` | | m | | minute, no padding | `7` | diff --git a/docs/parsing.md b/docs/parsing.md index cf7f0e5e6..5540f63a5 100644 --- a/docs/parsing.md +++ b/docs/parsing.md @@ -184,6 +184,8 @@ Because Luxon was able to parse the string without difficulty, the output is a l | S | | millisecond, no padding | `54` | | SSS | | millisecond, padded to 3 | `054` | | u | | fractional seconds, (5 is a half second, 54 is slightly more) | `54` | +| uu | | fractional seconds, (one or two digits) | `05` | +| uuu | | fractional seconds, (only one digit) | `5` | | s | | second, no padding | `4` | | ss | | second, padded to 2 padding | `04` | | m | | minute, no padding | `7` | diff --git a/src/impl/formatter.js b/src/impl/formatter.js index 4463781af..38200c853 100644 --- a/src/impl/formatter.js +++ b/src/impl/formatter.js @@ -179,6 +179,11 @@ export default class Formatter { return this.num(dt.second); case "ss": return this.num(dt.second, 2); + // fractional seconds + case "uu": + return this.num(Math.floor(dt.millisecond / 10), 2); + case "uuu": + return this.num(Math.floor(dt.millisecond / 100)); // minutes case "m": return this.num(dt.minute); diff --git a/src/impl/tokenParser.js b/src/impl/tokenParser.js index 6b31541d4..e5a1270e6 100644 --- a/src/impl/tokenParser.js +++ b/src/impl/tokenParser.js @@ -141,6 +141,10 @@ function unitForToken(token, loc) { return intUnit(three); case "u": return simple(oneToNine); + case "uu": + return simple(oneOrTwo); + case "uuu": + return intUnit(one); // meridiem case "a": return oneOf(loc.meridiems(), 0); diff --git a/test/datetime/toFormat.test.js b/test/datetime/toFormat.test.js index 1d76e3845..116a71e53 100644 --- a/test/datetime/toFormat.test.js +++ b/test/datetime/toFormat.test.js @@ -35,6 +35,18 @@ test("DateTime#toFormat('u') returns fractional seconds", () => { expect(dt.set({ millisecond: 80 }).toFormat("u")).toBe("080"); // I think this is OK }); +test("DateTime#toFormat('uu') returns fractional seconds as two digits", () => { + expect(dt.toFormat("uu")).toBe("12"); + expect(dt.set({ millisecond: 82 }).toFormat("uu")).toBe("08"); + expect(dt.set({ millisecond: 789 }).toFormat("uu")).toBe("78"); +}); + +test("DateTime#toFormat('uuu') returns fractional seconds as one digit", () => { + expect(dt.toFormat("uuu")).toBe("1"); + expect(dt.set({ millisecond: 82 }).toFormat("uuu")).toBe("0"); + expect(dt.set({ millisecond: 789 }).toFormat("uuu")).toBe("7"); +}); + test("DateTime#toFormat('S') returns the millisecond", () => { expect(dt.toFormat("S")).toBe("123"); expect(dt.reconfigure({ locale: "bn" }).toFormat("S")).toBe("১২৩"); diff --git a/test/datetime/tokenParse.test.js b/test/datetime/tokenParse.test.js index 08708fc23..c2f3a15da 100644 --- a/test/datetime/tokenParse.test.js +++ b/test/datetime/tokenParse.test.js @@ -171,6 +171,14 @@ test("DateTime.fromFormat() parses fractional seconds", () => { expect(DateTime.fromFormat("003", "u").millisecond).toBe(3); expect(DateTime.fromFormat("1234", "u").millisecond).toBe(123); expect(DateTime.fromFormat("1235", "u").millisecond).toBe(123); + + expect(DateTime.fromFormat("1", "uu").millisecond).toBe(100); + expect(DateTime.fromFormat("12", "uu").millisecond).toBe(120); + expect(DateTime.fromFormat("02", "uu").millisecond).toBe(20); + expect(DateTime.fromFormat("-33", "uu").isValid).toBe(false); + + expect(DateTime.fromFormat("1", "uuu").millisecond).toBe(100); + expect(DateTime.fromFormat("-2", "uuu").isValid).toBe(false); }); test("DateTime.fromFormat() parses weekdays", () => {