Skip to content

Commit

Permalink
formatMaximum/Minimum take timezone into account for time and date-ti…
Browse files Browse the repository at this point in the history
…me format (#43)

* formatMaximum/Minimum take timezone into account for time and date-time format

* additional tests for iso-time and iso-date-time formats
  • Loading branch information
epoberezkin authored Nov 7, 2021
1 parent 37d7538 commit 8b424f1
Show file tree
Hide file tree
Showing 3 changed files with 332 additions and 19 deletions.
26 changes: 21 additions & 5 deletions src/formats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export const fullFormats: DefinedFormats = {
// date-time: http://tools.ietf.org/html/rfc3339#section-5.6
time: fmtDef(getTime(true), compareTime),
"date-time": fmtDef(getDateTime(true), compareDateTime),
"iso-time": fmtDef(getTime(), compareTime),
"iso-date-time": fmtDef(getDateTime(), compareDateTime),
"iso-time": fmtDef(getTime(), compareIsoTime),
"iso-date-time": fmtDef(getDateTime(), compareIsoDateTime),
// duration: https://tools.ietf.org/html/rfc3339#appendix-A
duration: /^P(?!$)((\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?|(\d+W)?)$/,
uri,
Expand Down Expand Up @@ -107,11 +107,11 @@ export const fastFormats: DefinedFormats = {
),
"iso-time": fmtDef(
/^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i,
compareTime
compareIsoTime
),
"iso-date-time": fmtDef(
/^\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,
compareDateTime
compareIsoDateTime
),
// uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js
uri: /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/)?[^\s]*$/i,
Expand Down Expand Up @@ -177,7 +177,15 @@ function getTime(strictTimeZone?: boolean): (str: string) => boolean {
}
}

function compareTime(t1: string, t2: string): number | undefined {
function compareTime(s1: string, s2: string): number | undefined {
if (!(s1 && s2)) return undefined
const t1 = new Date("2020-01-01T" + s1).valueOf()
const t2 = new Date("2020-01-01T" + s2).valueOf()
if (!(t1 && t2)) return undefined
return t1 - t2
}

function compareIsoTime(t1: string, t2: string): number | undefined {
if (!(t1 && t2)) return undefined
const a1 = TIME.exec(t1)
const a2 = TIME.exec(t2)
Expand All @@ -201,6 +209,14 @@ function getDateTime(strictTimeZone?: boolean): (str: string) => boolean {
}

function compareDateTime(dt1: string, dt2: string): number | undefined {
if (!(dt1 && dt2)) return undefined
const d1 = new Date(dt1).valueOf()
const d2 = new Date(dt2).valueOf()
if (!(d1 && d2)) return undefined
return d1 - d2
}

function compareIsoDateTime(dt1: string, dt2: string): number | undefined {
if (!(dt1 && dt2)) return undefined
const [d1, t1] = dt1.split(DATE_TIME_SEPARATOR)
const [d2, t2] = dt2.split(DATE_TIME_SEPARATOR)
Expand Down
163 changes: 153 additions & 10 deletions tests/extras/formatMaximum.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
}
]
},

{
"description": "formatMaximum validation with time format",
"schema": {
Expand All @@ -69,10 +68,20 @@
"valid": true
},
{
"description": "boundary point is valid, timezone is ignored",
"description": "time before the maximum time is valid, timezone is taken into account",
"data": "13:15:17.000+01:00",
"valid": true
},
{
"description": "boundary point is valid, timezone is taken into account",
"data": "14:15:17.000+01:00",
"valid": true
},
{
"description": "time after the maximum time is invalid, timezone is taken into account",
"data": "14:20:17.000+01:00",
"valid": false
},
{
"description": "time before the maximum time is valid",
"data": "10:33:55.000Z",
Expand All @@ -99,13 +108,8 @@
"valid": false
},
{
"description": "boundary point is invalid, timezone is ignored",
"data": "13:15:17.000+01:00",
"valid": false
},
{
"description": "boundary point is invalid, no timezone is ok too",
"data": "13:15:17.000",
"description": "boundary point is invalid, timezone is taken into account",
"data": "14:15:17.000+01:00",
"valid": false
},
{
Expand All @@ -115,7 +119,6 @@
}
]
},

{
"description": "formatMaximum validation with date-time format",
"schema": {
Expand Down Expand Up @@ -186,6 +189,146 @@
}
]
},
{
"description": "formatMaximum validation with iso-time format",
"schema": {
"type": "string",
"format": "iso-time",
"formatMaximum": "13:15:17.000Z"
},
"tests": [
{
"description": "time after the maximum time is invalid",
"data": "15:11:09.000Z",
"valid": false
},
{
"description": "boundary point is valid",
"data": "13:15:17.000Z",
"valid": true
},
{
"description": "time before the maximum time is valid, timezone is ignored",
"data": "13:15:16.000+01:00",
"valid": true
},
{
"description": "boundary point is valid, timezone is ignored",
"data": "13:15:17.000+01:00",
"valid": true
},
{
"description": "time after the maximum time is invalid, timezone is ignored",
"data": "13:15:18.000+01:00",
"valid": false
},
{
"description": "time before the maximum time is valid",
"data": "10:33:55.000Z",
"valid": true
}
]
},
{
"description": "formatExclusiveMaximum validation with iso-time format",
"schema": {
"type": "string",
"format": "iso-time",
"formatExclusiveMaximum": "13:15:17.000Z"
},
"tests": [
{
"description": "time after the maximum time is still invalid",
"data": "15:11:09.000Z",
"valid": false
},
{
"description": "boundary point is invalid",
"data": "13:15:17.000Z",
"valid": false
},
{
"description": "boundary point is invalid, timezone is ignored",
"data": "13:15:17.000+01:00",
"valid": false
},
{
"description": "time before the maximum time is still valid",
"data": "10:33:55.000Z",
"valid": true
}
]
},
{
"description": "formatMaximum validation with iso-date-time format",
"schema": {
"type": "string",
"format": "iso-date-time",
"formatMaximum": "2015-08-17T13:15:17.000Z"
},
"tests": [
{
"description": "date after the maximum date is invalid",
"data": "2015-11-09T13:15:17.000Z",
"valid": false
},
{
"description": "same date, time after the maximum time is invalid",
"data": "2015-08-17T15:11:09.000Z",
"valid": false
},
{
"description": "boundary point is valid",
"data": "2015-08-17T13:15:17.000Z",
"valid": true
},
{
"description": "same date, time before the maximum time is valid",
"data": "2015-08-17T10:33:55.000Z",
"valid": true
},
{
"description": "date before the maximum date is valid",
"data": "2014-12-03T13:15:17.000Z",
"valid": true
}
]
},
{
"description": "formatExclusiveMaximum validation with iso-date-time format",
"schema": {
"type": "string",
"format": "iso-date-time",
"formatExclusiveMaximum": "2015-08-17T13:15:17.000Z"
},
"tests": [
{
"description": "date after the maximum date is still invalid",
"data": "2015-11-09T13:15:17.000Z",
"valid": false
},
{
"description": "same date, time after the maximum time is still invalid",
"data": "2015-08-17T15:11:09.000Z",
"valid": false
},
{
"description": "boundary point is invalid",
"data": "2015-08-17T13:15:17.000Z",
"valid": false
},
{
"description": "same date, time before the maximum time is still valid",
"data": "2015-08-17T10:33:55.000Z",
"valid": true
},
{
"description": "date before the maximum date is still valid",
"data": "2014-12-03T13:15:17.000Z",
"valid": true
}
]
},
{
"description": "formatMaximum is valid with whitelisted unknown format",
"schema": {
Expand Down
Loading

0 comments on commit 8b424f1

Please sign in to comment.