@@ -111,6 +111,12 @@ export const fastFormats: DefinedFormats = {
111
111
/ ^ [ a - z 0 - 9 . ! # $ % & ' * + / = ? ^ _ ` { | } ~ - ] + @ [ a - z 0 - 9 ] (?: [ a - z 0 - 9 - ] { 0 , 61 } [ a - z 0 - 9 ] ) ? (?: \. [ a - z 0 - 9 ] (?: [ a - z 0 - 9 - ] { 0 , 61 } [ a - z 0 - 9 ] ) ? ) * $ / i,
112
112
}
113
113
114
+ export const strictFormats : Partial < DefinedFormats > = {
115
+ // date-time: http://tools.ietf.org/html/rfc3339#section-5.6
116
+ time : fmtDef ( strict_time , compareTime ) ,
117
+ "date-time" : fmtDef ( strict_date_time , compareDateTime ) ,
118
+ }
119
+
114
120
export const formatNames = Object . keys ( fullFormats ) as FormatName [ ]
115
121
116
122
function isLeapYear ( year : number ) : boolean {
@@ -143,40 +149,50 @@ function compareDate(d1: string, d2: string): number | undefined {
143
149
return 0
144
150
}
145
151
146
- const TIME = / ^ ( \d \d ) : ( \d \d ) : ( \d \d ) ( \. \d + ) ? ( z | [ + - ] \d \d (?: : ? \d \d ) ? ) ? $ / i
152
+ const TIME = / ^ ( \d \d ) : ( \d \d ) : ( \d \d (?: \. \d + ) ? ) ( z | ( [ + - ] \d \d ) (?: : ? ( \d \d ) ) ? ) ? $ / i
147
153
148
- function time ( str : string , withTimeZone ?: boolean ) : boolean {
154
+ function time ( str : string , withTimeZone ?: boolean , strictTime ?: boolean ) : boolean {
149
155
const matches : string [ ] | null = TIME . exec ( str )
150
156
if ( ! matches ) return false
151
-
152
- const hour : number = + matches [ 1 ]
153
- const minute : number = + matches [ 2 ]
154
- const second : number = + matches [ 3 ]
155
- const timeZone : string = matches [ 5 ]
157
+ const hr : number = + matches [ 1 ]
158
+ const min : number = + matches [ 2 ]
159
+ const sec : number = + matches [ 3 ]
160
+ const tz : string | undefined = matches [ 4 ]
161
+ const tzH : number = + ( matches [ 5 ] || 0 )
162
+ const tzM : number = + ( matches [ 6 ] || 0 )
156
163
return (
157
- ( ( hour <= 23 && minute <= 59 && second <= 59 ) ||
158
- ( hour === 23 && minute === 59 && second === 60 ) ) &&
159
- ( ! withTimeZone || timeZone !== "" )
164
+ ( ( hr <= 23 && min <= 59 && sec < 60 && tzH <= 24 && tzM < 60 ) ||
165
+ // leap second
166
+ ( hr - tzH === 23 && min - tzM === 59 && sec < 61 && tzH <= 24 && tzM < 60 ) ) &&
167
+ ( ! withTimeZone || ( tz !== "" && ( ! strictTime || ! ! tz ) ) )
160
168
)
161
169
}
162
170
171
+ function strict_time ( str : string ) : boolean {
172
+ return time ( str , true , true )
173
+ }
174
+
163
175
function compareTime ( t1 : string , t2 : string ) : number | undefined {
164
176
if ( ! ( t1 && t2 ) ) return undefined
165
177
const a1 = TIME . exec ( t1 )
166
178
const a2 = TIME . exec ( t2 )
167
179
if ( ! ( a1 && a2 ) ) return undefined
168
- t1 = a1 [ 1 ] + a1 [ 2 ] + a1 [ 3 ] + ( a1 [ 4 ] || "" )
169
- t2 = a2 [ 1 ] + a2 [ 2 ] + a2 [ 3 ] + ( a2 [ 4 ] || "" )
180
+ t1 = a1 [ 1 ] + a1 [ 2 ] + a1 [ 3 ]
181
+ t2 = a2 [ 1 ] + a2 [ 2 ] + a2 [ 3 ]
170
182
if ( t1 > t2 ) return 1
171
183
if ( t1 < t2 ) return - 1
172
184
return 0
173
185
}
174
186
175
187
const DATE_TIME_SEPARATOR = / t | \s / i
176
- function date_time ( str : string ) : boolean {
188
+ function date_time ( str : string , strictTime ?: boolean ) : boolean {
177
189
// http://tools.ietf.org/html/rfc3339#section-5.6
178
190
const dateTime : string [ ] = str . split ( DATE_TIME_SEPARATOR )
179
- return dateTime . length === 2 && date ( dateTime [ 0 ] ) && time ( dateTime [ 1 ] , true )
191
+ return dateTime . length === 2 && date ( dateTime [ 0 ] ) && time ( dateTime [ 1 ] , true , strictTime )
192
+ }
193
+
194
+ function strict_date_time ( str : string ) : boolean {
195
+ return date_time ( str , true )
180
196
}
181
197
182
198
function compareDateTime ( dt1 : string , dt2 : string ) : number | undefined {
0 commit comments