Skip to content

Commit 8b424f1

Browse files
authored
formatMaximum/Minimum take timezone into account for time and date-time format (#43)
* formatMaximum/Minimum take timezone into account for time and date-time format * additional tests for iso-time and iso-date-time formats
1 parent 37d7538 commit 8b424f1

File tree

3 files changed

+332
-19
lines changed

3 files changed

+332
-19
lines changed

src/formats.ts

+21-5
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ export const fullFormats: DefinedFormats = {
4848
// date-time: http://tools.ietf.org/html/rfc3339#section-5.6
4949
time: fmtDef(getTime(true), compareTime),
5050
"date-time": fmtDef(getDateTime(true), compareDateTime),
51-
"iso-time": fmtDef(getTime(), compareTime),
52-
"iso-date-time": fmtDef(getDateTime(), compareDateTime),
51+
"iso-time": fmtDef(getTime(), compareIsoTime),
52+
"iso-date-time": fmtDef(getDateTime(), compareIsoDateTime),
5353
// duration: https://tools.ietf.org/html/rfc3339#appendix-A
5454
duration: /^P(?!$)((\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?|(\d+W)?)$/,
5555
uri,
@@ -107,11 +107,11 @@ export const fastFormats: DefinedFormats = {
107107
),
108108
"iso-time": fmtDef(
109109
/^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i,
110-
compareTime
110+
compareIsoTime
111111
),
112112
"iso-date-time": fmtDef(
113113
/^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i,
114-
compareDateTime
114+
compareIsoDateTime
115115
),
116116
// uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js
117117
uri: /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/)?[^\s]*$/i,
@@ -177,7 +177,15 @@ function getTime(strictTimeZone?: boolean): (str: string) => boolean {
177177
}
178178
}
179179

180-
function compareTime(t1: string, t2: string): number | undefined {
180+
function compareTime(s1: string, s2: string): number | undefined {
181+
if (!(s1 && s2)) return undefined
182+
const t1 = new Date("2020-01-01T" + s1).valueOf()
183+
const t2 = new Date("2020-01-01T" + s2).valueOf()
184+
if (!(t1 && t2)) return undefined
185+
return t1 - t2
186+
}
187+
188+
function compareIsoTime(t1: string, t2: string): number | undefined {
181189
if (!(t1 && t2)) return undefined
182190
const a1 = TIME.exec(t1)
183191
const a2 = TIME.exec(t2)
@@ -201,6 +209,14 @@ function getDateTime(strictTimeZone?: boolean): (str: string) => boolean {
201209
}
202210

203211
function compareDateTime(dt1: string, dt2: string): number | undefined {
212+
if (!(dt1 && dt2)) return undefined
213+
const d1 = new Date(dt1).valueOf()
214+
const d2 = new Date(dt2).valueOf()
215+
if (!(d1 && d2)) return undefined
216+
return d1 - d2
217+
}
218+
219+
function compareIsoDateTime(dt1: string, dt2: string): number | undefined {
204220
if (!(dt1 && dt2)) return undefined
205221
const [d1, t1] = dt1.split(DATE_TIME_SEPARATOR)
206222
const [d2, t2] = dt2.split(DATE_TIME_SEPARATOR)

tests/extras/formatMaximum.json

+153-10
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
}
5050
]
5151
},
52-
5352
{
5453
"description": "formatMaximum validation with time format",
5554
"schema": {
@@ -69,10 +68,20 @@
6968
"valid": true
7069
},
7170
{
72-
"description": "boundary point is valid, timezone is ignored",
71+
"description": "time before the maximum time is valid, timezone is taken into account",
7372
"data": "13:15:17.000+01:00",
7473
"valid": true
7574
},
75+
{
76+
"description": "boundary point is valid, timezone is taken into account",
77+
"data": "14:15:17.000+01:00",
78+
"valid": true
79+
},
80+
{
81+
"description": "time after the maximum time is invalid, timezone is taken into account",
82+
"data": "14:20:17.000+01:00",
83+
"valid": false
84+
},
7685
{
7786
"description": "time before the maximum time is valid",
7887
"data": "10:33:55.000Z",
@@ -99,13 +108,8 @@
99108
"valid": false
100109
},
101110
{
102-
"description": "boundary point is invalid, timezone is ignored",
103-
"data": "13:15:17.000+01:00",
104-
"valid": false
105-
},
106-
{
107-
"description": "boundary point is invalid, no timezone is ok too",
108-
"data": "13:15:17.000",
111+
"description": "boundary point is invalid, timezone is taken into account",
112+
"data": "14:15:17.000+01:00",
109113
"valid": false
110114
},
111115
{
@@ -115,7 +119,6 @@
115119
}
116120
]
117121
},
118-
119122
{
120123
"description": "formatMaximum validation with date-time format",
121124
"schema": {
@@ -186,6 +189,146 @@
186189
}
187190
]
188191
},
192+
{
193+
"description": "formatMaximum validation with iso-time format",
194+
"schema": {
195+
"type": "string",
196+
"format": "iso-time",
197+
"formatMaximum": "13:15:17.000Z"
198+
},
199+
"tests": [
200+
{
201+
"description": "time after the maximum time is invalid",
202+
"data": "15:11:09.000Z",
203+
"valid": false
204+
},
205+
{
206+
"description": "boundary point is valid",
207+
"data": "13:15:17.000Z",
208+
"valid": true
209+
},
210+
{
211+
"description": "time before the maximum time is valid, timezone is ignored",
212+
"data": "13:15:16.000+01:00",
213+
"valid": true
214+
},
215+
{
216+
"description": "boundary point is valid, timezone is ignored",
217+
"data": "13:15:17.000+01:00",
218+
"valid": true
219+
},
220+
{
221+
"description": "time after the maximum time is invalid, timezone is ignored",
222+
"data": "13:15:18.000+01:00",
223+
"valid": false
224+
},
225+
{
226+
"description": "time before the maximum time is valid",
227+
"data": "10:33:55.000Z",
228+
"valid": true
229+
}
230+
]
231+
},
232+
{
233+
"description": "formatExclusiveMaximum validation with iso-time format",
234+
"schema": {
235+
"type": "string",
236+
"format": "iso-time",
237+
"formatExclusiveMaximum": "13:15:17.000Z"
238+
},
239+
"tests": [
240+
{
241+
"description": "time after the maximum time is still invalid",
242+
"data": "15:11:09.000Z",
243+
"valid": false
244+
},
245+
{
246+
"description": "boundary point is invalid",
247+
"data": "13:15:17.000Z",
248+
"valid": false
249+
},
250+
{
251+
"description": "boundary point is invalid, timezone is ignored",
252+
"data": "13:15:17.000+01:00",
253+
"valid": false
254+
},
255+
{
256+
"description": "time before the maximum time is still valid",
257+
"data": "10:33:55.000Z",
258+
"valid": true
259+
}
260+
]
261+
},
262+
{
263+
"description": "formatMaximum validation with iso-date-time format",
264+
"schema": {
265+
"type": "string",
266+
"format": "iso-date-time",
267+
"formatMaximum": "2015-08-17T13:15:17.000Z"
268+
},
269+
"tests": [
270+
{
271+
"description": "date after the maximum date is invalid",
272+
"data": "2015-11-09T13:15:17.000Z",
273+
"valid": false
274+
},
275+
{
276+
"description": "same date, time after the maximum time is invalid",
277+
"data": "2015-08-17T15:11:09.000Z",
278+
"valid": false
279+
},
280+
{
281+
"description": "boundary point is valid",
282+
"data": "2015-08-17T13:15:17.000Z",
283+
"valid": true
284+
},
285+
{
286+
"description": "same date, time before the maximum time is valid",
287+
"data": "2015-08-17T10:33:55.000Z",
288+
"valid": true
289+
},
290+
{
291+
"description": "date before the maximum date is valid",
292+
"data": "2014-12-03T13:15:17.000Z",
293+
"valid": true
294+
}
295+
]
296+
},
297+
{
298+
"description": "formatExclusiveMaximum validation with iso-date-time format",
299+
"schema": {
300+
"type": "string",
301+
"format": "iso-date-time",
302+
"formatExclusiveMaximum": "2015-08-17T13:15:17.000Z"
303+
},
304+
"tests": [
305+
{
306+
"description": "date after the maximum date is still invalid",
307+
"data": "2015-11-09T13:15:17.000Z",
308+
"valid": false
309+
},
310+
{
311+
"description": "same date, time after the maximum time is still invalid",
312+
"data": "2015-08-17T15:11:09.000Z",
313+
"valid": false
314+
},
315+
{
316+
"description": "boundary point is invalid",
317+
"data": "2015-08-17T13:15:17.000Z",
318+
"valid": false
319+
},
320+
{
321+
"description": "same date, time before the maximum time is still valid",
322+
"data": "2015-08-17T10:33:55.000Z",
323+
"valid": true
324+
},
325+
{
326+
"description": "date before the maximum date is still valid",
327+
"data": "2014-12-03T13:15:17.000Z",
328+
"valid": true
329+
}
330+
]
331+
},
189332
{
190333
"description": "formatMaximum is valid with whitelisted unknown format",
191334
"schema": {

0 commit comments

Comments
 (0)