Skip to content

Commit

Permalink
simplify strictTime option
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Nov 6, 2021
1 parent bfa3304 commit d1a9e36
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 31 deletions.
45 changes: 19 additions & 26 deletions src/formats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,57 +149,50 @@ function compareDate(d1: string, d2: string): number | undefined {
return 0
}

const TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d(?::?\d\d)?)?$/i
const PLUS_MINUS = /^[+-]/
const TIMEZONE = /^[Zz]$/
const ISO_8601_TIME = /^[+-](?:[01][0-9]|2[0-4])(?::?[0-5][0-9])?$/
const TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-]\d\d)(?::?(\d\d))?)?$/i

function time(str: string, withTimeZone?: boolean, strict?: boolean): boolean {
function time(str: string, withTimeZone?: boolean, strictTime?: boolean): boolean {
const matches: string[] | null = TIME.exec(str)
if (!matches) return false

const hour: number = +matches[1]
const minute: number = +matches[2]
const second: number = +matches[3]
const timeZone: string = matches[5]
const hr: number = +matches[1]
const min: number = +matches[2]
const sec: number = +matches[3]
const tz: string | undefined = matches[4]
const tzH: number = +(matches[5] || 0)
const tzM: number = +(matches[6] || 0)
return (
((hour <= 23 && minute <= 59 && second <= 59) ||
(hour === 23 && minute === 59 && second === 60)) &&
(!withTimeZone ||
(strict
? TIMEZONE.test(timeZone) ||
(PLUS_MINUS.test(timeZone) && time(timeZone.slice(1) + ":00")) ||
ISO_8601_TIME.test(timeZone)
: timeZone !== ""))
((hr <= 23 && min <= 59 && sec < 60 && tzH <= 24 && tzM < 60) ||
// leap second
(hr - tzH === 23 && min - tzM === 59 && sec < 61 && tzH <= 24 && tzM < 60)) &&
(!withTimeZone || (tz !== "" && (!strictTime || !!tz)))
)
}

function strict_time(str: string, withTimeZone?: boolean): boolean {
return time(str, withTimeZone, true)
function strict_time(str: string): boolean {
return time(str, true, true)
}

function compareTime(t1: string, t2: string): number | undefined {
if (!(t1 && t2)) return undefined
const a1 = TIME.exec(t1)
const a2 = TIME.exec(t2)
if (!(a1 && a2)) return undefined
t1 = a1[1] + a1[2] + a1[3] + (a1[4] || "")
t2 = a2[1] + a2[2] + a2[3] + (a2[4] || "")
t1 = a1[1] + a1[2] + a1[3]
t2 = a2[1] + a2[2] + a2[3]
if (t1 > t2) return 1
if (t1 < t2) return -1
return 0
}

const DATE_TIME_SEPARATOR = /t|\s/i
function date_time(str: string): boolean {
function date_time(str: string, strictTime?: boolean): boolean {
// http://tools.ietf.org/html/rfc3339#section-5.6
const dateTime: string[] = str.split(DATE_TIME_SEPARATOR)
return dateTime.length === 2 && date(dateTime[0]) && time(dateTime[1], true)
return dateTime.length === 2 && date(dateTime[0]) && time(dateTime[1], true, strictTime)
}

function strict_date_time(str: string): boolean {
const dateTime: string[] = str.split(DATE_TIME_SEPARATOR)
return dateTime.length === 2 && date(dateTime[0]) && strict_time(dateTime[1], true)
return date_time(str, true)
}

function compareDateTime(dt1: string, dt2: string): number | undefined {
Expand Down
6 changes: 3 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface FormatOptions {
mode?: FormatMode
formats?: FormatName[]
keywords?: boolean
strictDate?: boolean
strictTime?: boolean
}

export type FormatsPluginOptions = FormatName[] | FormatOptions
Expand All @@ -32,7 +32,7 @@ const fastName = new Name("fastFormats")

const formatsPlugin: FormatsPlugin = (
ajv: Ajv,
opts: FormatsPluginOptions = {keywords: true, strictDate: false}
opts: FormatsPluginOptions = {keywords: true, strictTime: false}
): Ajv => {
if (Array.isArray(opts)) {
addFormats(ajv, opts, fullFormats, fullName)
Expand All @@ -41,7 +41,7 @@ const formatsPlugin: FormatsPlugin = (
const [formats, exportName] =
opts.mode === "fast" ? [fastFormats, fastName] : [fullFormats, fullName]
const list = opts.formats || formatNames
addFormats(ajv, list, opts.strictDate ? {...formats, ...strictFormats} : formats, exportName)
addFormats(ajv, list, opts.strictTime ? {...formats, ...strictFormats} : formats, exportName)
if (opts.keywords) formatLimit(ajv)
return ajv
}
Expand Down
4 changes: 2 additions & 2 deletions tests/strictDate.spec.ts → tests/strictTime.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import Ajv from "ajv"
import addFormats from "../dist"

const ajv = new Ajv({$data: true, strictTypes: false, formats: {allowedUnknown: true}})
addFormats(ajv, {strictDate: true})
addFormats(ajv, {mode: "full", strictTime: true})

describe("strictDate option", () => {
describe("strictTime option", () => {
it("a valid date-time string with time offset", () => {
expect(
ajv.validate(
Expand Down

0 comments on commit d1a9e36

Please sign in to comment.