Skip to content

Commit 1579e54

Browse files
author
Sascha Goldhofer
committed
fix: time validation to support RFC 3339
1 parent 82de5e6 commit 1579e54

File tree

2 files changed

+79
-16
lines changed

2 files changed

+79
-16
lines changed

lib/validation/format.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ const isValidIPV6 =
1717
const isValidHostname =
1818
/^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$/;
1919
const matchDate = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
20-
const matchTime = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d(?::?\d\d)?)?$/i;
20+
// const matchTime = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d(?::?\d\d)?)?$/i;
21+
const matchTime = /^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i;
2122
const DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
2223

2324
const isValidJsonPointer = /^(?:\/(?:[^~/]|~0|~1)*)*$/;
@@ -175,27 +176,31 @@ const formatValidators: Record<
175176
return errors.formatRegExError({ value, pointer, schema });
176177
},
177178

179+
// hh:mm:ss.sTZD
180+
// https://opis.io/json-schema/2.x/formats.html
181+
// regex https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s07.html
178182
time: (draft, schema, value, pointer) => {
179183
if (typeof value !== "string" || value === "") {
180184
return undefined;
181185
}
182186
// https://github.com/cfworker/cfworker/blob/main/packages/json-schema/src/format.ts
183187
const matches = value.match(matchTime);
184-
if (!matches) {
185-
return errors.formatDateTimeError({ value, pointer, schema });
186-
}
187-
const hour = +matches[1];
188-
const minute = +matches[2];
189-
const second = +matches[3];
190-
const timeZone = !!matches[5];
191-
if (
192-
((hour <= 23 && minute <= 59 && second <= 59) ||
193-
(hour == 23 && minute == 59 && second == 60)) &&
194-
timeZone
195-
) {
196-
return undefined;
197-
}
198-
return errors.formatTimeError({ value, pointer, schema });
188+
return matches ? undefined : errors.formatDateTimeError({ value, pointer, schema });
189+
// if (!matches) {
190+
// return errors.formatDateTimeError({ value, pointer, schema });
191+
// }
192+
// const hour = +matches[1];
193+
// const minute = +matches[2];
194+
// const second = +matches[3];
195+
// const timeZone = !!matches[5];
196+
// if (
197+
// ((hour <= 23 && minute <= 59 && second <= 59) ||
198+
// (hour == 23 && minute == 59 && second == 60)) &&
199+
// timeZone
200+
// ) {
201+
// return undefined;
202+
// }
203+
// return errors.formatTimeError({ value, pointer, schema });
199204
},
200205

201206
uri: (draft, schema, value, pointer) => {

test/unit/validate.format.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,64 @@ describe("validate format", () => {
66
let draft: Draft04;
77
before(() => (draft = new Draft04()));
88

9+
describe("time", () => {
10+
it("should validate HH:mm:ss", () => {
11+
const errors = validate(draft, "15:31:12", {
12+
type: "string",
13+
format: "time"
14+
});
15+
assert.deepEqual(errors, []);
16+
});
17+
18+
it("should validate HH:mm:ss.s", () => {
19+
const errors = validate(draft, "15:31:12.99", {
20+
type: "string",
21+
format: "time"
22+
});
23+
assert.deepEqual(errors, []);
24+
});
25+
26+
it("should validate HH:mm:ss-HH:mm", () => {
27+
const errors = validate(draft, "15:31:12-02:30", {
28+
type: "string",
29+
format: "time"
30+
});
31+
assert.deepEqual(errors, []);
32+
});
33+
34+
it("should validate HH:mm:ssZ", () => {
35+
const errors = validate(draft, "15:31:12Z", {
36+
type: "string",
37+
format: "time"
38+
});
39+
assert.deepEqual(errors, []);
40+
});
41+
42+
it("should not validate minutes above 59", () => {
43+
const errors = validate(draft, "15:60:12", {
44+
type: "string",
45+
format: "time"
46+
});
47+
assert.equal(errors.length, 1);
48+
});
49+
50+
it("should not validate seconds above 59", () => {
51+
const errors = validate(draft, "15:31:60", {
52+
type: "string",
53+
format: "time"
54+
});
55+
assert.equal(errors.length, 1);
56+
});
57+
58+
it("should not validate HH:mm", () => {
59+
const errors = validate(draft, "15:31", {
60+
type: "string",
61+
format: "time"
62+
});
63+
assert.equal(errors.length, 1);
64+
});
65+
});
66+
967
describe("url", () => {
1068
it("should validate format url", () => {
1169
const errors = validate(draft, "https://developer.mozilla.org/en-US/", {

0 commit comments

Comments
 (0)