Describe the bug
date().cast() mis-parses ISO datetimes whose fractional-seconds part has fewer than 3 digits. .5 (= 500 ms) is read as 5 ms, .05 as 5 ms instead of 50, .12 as 12 instead of 120. Only exactly-3-digit fractions (.123) are correct. The result is silently wrong by up to 495 ms.
To Reproduce
import { date } from 'yup';
date().cast('2020-01-01T00:00:00.5Z').toISOString();
// actual: "2020-01-01T00:00:00.005Z"
// expected: "2020-01-01T00:00:00.500Z" (same as new Date('2020-01-01T00:00:00.5Z'))
Sweep on yup 1.7.1 vs native Date:
| input |
yup ms |
Date ms |
.1Z |
1 |
100 |
.05Z |
5 |
50 |
.12Z |
12 |
120 |
.5Z |
5 |
500 |
.123Z |
123 |
123 (ok) |
date().validate('2020-01-01T00:00:00.5Z') likewise resolves to 2020-01-01T00:00:00.005Z.
Expected behavior
Fractional seconds match the native ISO 8601 parser (new Date / Date.parse), which yup's parseIsoDate.ts header says it enhances: .5 -> 500 ms.
Cause
In src/util/parseIsoDate.ts, the milliseconds field is toNumber(regexResult[7].substring(0, 3)) -- it truncates to 3 fractional digits but never right-pads, so a fraction shorter than 3 digits is parsed as a literal integer. Fix: .substring(0, 3).padEnd(3, '0').
(Distinct from the merged #60, which fixed the 3-digit leading-zero case .012->.120; that case is now correct, but sub-3-digit fractions remain wrong.)
Platform
Describe the bug
date().cast()mis-parses ISO datetimes whose fractional-seconds part has fewer than 3 digits..5(= 500 ms) is read as 5 ms,.05as 5 ms instead of 50,.12as 12 instead of 120. Only exactly-3-digit fractions (.123) are correct. The result is silently wrong by up to 495 ms.To Reproduce
Sweep on yup 1.7.1 vs native
Date:.1Z.05Z.12Z.5Z.123Zdate().validate('2020-01-01T00:00:00.5Z')likewise resolves to2020-01-01T00:00:00.005Z.Expected behavior
Fractional seconds match the native ISO 8601 parser (
new Date/Date.parse), which yup'sparseIsoDate.tsheader says it enhances:.5-> 500 ms.Cause
In
src/util/parseIsoDate.ts, the milliseconds field istoNumber(regexResult[7].substring(0, 3))-- it truncates to 3 fractional digits but never right-pads, so a fraction shorter than 3 digits is parsed as a literal integer. Fix:.substring(0, 3).padEnd(3, '0').(Distinct from the merged #60, which fixed the 3-digit leading-zero case
.012->.120; that case is now correct, but sub-3-digit fractions remain wrong.)Platform