Describe the bug
isRFC3339 allows the seconds value 60 at any hour and minute:
const timeSecond = /([0-5][0-9]|60)/;
RFC 3339 §5.6
allows 60 only for a leap second, and a leap second occurs only at 23:59:60
UTC. After the offset is applied, any other instant is unrepresentable.
I want to flag up front that '2009-05-31 14:53:60Z' is currently in the valid
list in test/validators.test.js, and that #2841 mentions keeping it valid. So
this is a question about intended strictness rather than a straightforward bug,
and it may well be deliberate.
Examples
const validator = require('validator'); // 13.15.35
// A real leap second: correct
validator.isRFC3339('2016-12-31T23:59:60Z'); // true
// Not a possible instant for a leap second
validator.isRFC3339('2020-01-01T00:00:60Z'); // true
validator.isRFC3339('2009-05-31T14:53:60Z'); // true
Reproductions
The Examples block above runs as-is on Node after
npm install validator@13.15.35; no harness or scaffolding needed.
Additional context
If the leniency is intentional, it would help to say so in the docs, since
isRFC3339 is otherwise strict enough that callers may reasonably read a
true as "this is a representable instant". If it is not intentional, the
check is hour === 23 && minute === 59 guarding the 60 alternative, applied
after the offset.
Validator.js version: 13.15.35
Node.js version: v26.7.0
OS platform: Linux
Describe the bug
isRFC3339allows the seconds value60at any hour and minute:RFC 3339 §5.6
allows
60only for a leap second, and a leap second occurs only at 23:59:60UTC. After the offset is applied, any other instant is unrepresentable.
I want to flag up front that
'2009-05-31 14:53:60Z'is currently in the validlist in
test/validators.test.js, and that #2841 mentions keeping it valid. Sothis is a question about intended strictness rather than a straightforward bug,
and it may well be deliberate.
Examples
Reproductions
The Examples block above runs as-is on Node after
npm install validator@13.15.35; no harness or scaffolding needed.Additional context
If the leniency is intentional, it would help to say so in the docs, since
isRFC3339is otherwise strict enough that callers may reasonably read atrueas "this is a representable instant". If it is not intentional, thecheck is
hour === 23 && minute === 59guarding the60alternative, appliedafter the offset.
Validator.js version: 13.15.35
Node.js version: v26.7.0
OS platform: Linux