Skip to content

Commit f2729f7

Browse files
authored
Merge pull request #3145 from hapijs/backport/isodate-timeshift-v17
backport #3143 and #3144
2 parents 850be1e + c43fc96 commit f2729f7

2 files changed

Lines changed: 45 additions & 2 deletions

File tree

lib/types/string.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -829,8 +829,8 @@ internals.isoDate = function (value) {
829829
return null;
830830
}
831831

832-
if (/.*T.*[+-]\d\d$/.test(value)) { // Add missing trailing zeros to timeshift
833-
value += '00';
832+
if (/T.*[+-]\d\d$/.test(value)) { // Add missing separator and trailing zeros to timeshift
833+
value += ':00';
834834
}
835835

836836
const date = new Date(value);

test/types/string.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5585,6 +5585,49 @@ describe('string', () => {
55855585
const schema = Joi.string().isoDate().allow('x');
55865586
Helper.validate(schema, [['x', true]]);
55875587
});
5588+
5589+
it('pads a bare-hour timeshift with a colon, not just zeros', () => {
5590+
5591+
// A bare-hour offset like "+07" is padded to a full offset before being
5592+
// handed to Date(). Node's own parser tolerates "+0700" (basic format),
5593+
// but the ISO 8601 extended format used everywhere else in this string
5594+
// requires "+07:00" - mixing the two breaks stricter parsers (e.g. Safari).
5595+
// Node can't tell these apart itself, so this spies on what string
5596+
// actually reaches Date() rather than trusting Date() to reject it.
5597+
5598+
const NativeDate = global.Date;
5599+
const seen = [];
5600+
5601+
global.Date = class extends NativeDate {
5602+
5603+
constructor(...args) {
5604+
5605+
seen.push(args[0]);
5606+
super(...args);
5607+
}
5608+
};
5609+
5610+
try {
5611+
Joi.string().isoDate().validate('2013-06-07T14:21:46+07');
5612+
}
5613+
finally {
5614+
global.Date = NativeDate;
5615+
}
5616+
5617+
expect(seen).to.include('2013-06-07T14:21:46+07:00');
5618+
expect(seen).to.not.include('2013-06-07T14:21:46+0700');
5619+
});
5620+
5621+
it('validates a date with thousands of decimals in linear time', () => {
5622+
5623+
const value = '2020-01-01T00:00:00.' + '1'.repeat(64 * 1024);
5624+
5625+
const start = process.hrtime.bigint();
5626+
Joi.string().isoDate().validate(value);
5627+
const elapsed = Number(process.hrtime.bigint() - start) / 1e6;
5628+
5629+
expect(elapsed).to.be.below(200);
5630+
});
55885631
});
55895632

55905633
describe('isoDuration()', () => {

0 commit comments

Comments
 (0)