Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Nov 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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