@@ -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