From 1fb9ce5a9c2fa35af59487ea7595d20531b8f2ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Afonso=20Janu=C3=A1rio?= Date: Mon, 28 Sep 2026 20:57:44 +0100 Subject: [PATCH] fix: trailing decimal point drops the following unit A number like "5." (integer part followed by a bare decimal point with no fraction digits) failed the number regex's decimal branch, which requires at least one digit after the dot. The engine then matched just "5" with an empty unit capture, so the term fell back to the base format (ms) instead of picking up the unit that followed the dot. parse('5. seconds') returned 5 instead of 5000, silently disagreeing with parse('5 seconds'). The existing test for this shape used a zero value ('+0. secs' => 0), which passes either way and hid the bug. Made the fractional part of the digit-first branch accept zero digits after the dot, so "5." is consumed as part of the number and the trailing unit is captured correctly. Added regression tests covering a space and no space before the unit, and a negative value. --- index.js | 2 +- test.js | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 23270ca..a401fe4 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ import en from './locale/en.js' -const durationRE = /((?:\d+(?:\.\d+)?|\.\d+)(?:[eE][-+]?\d+)?)\s*([\p{L}]{0,14})/gu +const durationRE = /((?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?)\s*([\p{L}]{0,14})/gu parse.unit = en diff --git a/test.js b/test.js index 5a7cfa7..e1b8971 100644 --- a/test.js +++ b/test.js @@ -117,6 +117,16 @@ t('edge cases', t => { t.end() }) +t('trailing decimal point with no fraction digits', t => { + // a bare `.` right after the integer part must not swallow the unit + // that follows it, e.g. "5. seconds" should behave like "5 seconds" + t.equal(parse('5. seconds'), 5 * s) + t.equal(parse('5.seconds'), 5 * s) + t.equal(parse('5. secs'), parse('5 secs')) + t.equal(parse('-5. secs'), -5 * s) + t.end() +}) + t('invalid', t => { t.equal(parse('abc'), null) t.equal(parse(), null)