Skip to content

Commit b1883f2

Browse files
committed
feat(time): parse ISO 8601 Z timestamps
1 parent 84d683f commit b1883f2

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

src/Time.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,24 @@ export const time = (
7474
};
7575

7676
export const Time = createLanguageThis({
77+
ISODateTimeZ() {
78+
// Example: 2004-07-12T22:18:09Z
79+
// Keep it strict and UTC-only for now.
80+
return map(
81+
regex(
82+
/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/i,
83+
"iso-datetime-z",
84+
),
85+
(raw, b, a) => {
86+
const d = new Date(raw);
87+
if (Number.isNaN(d.getTime())) {
88+
// Should be unreachable given the regex, but keep it defensive.
89+
return time({ when: raw, grain: "second" }, b, a);
90+
}
91+
return time({ when: d.toISOString(), grain: "second" }, b, a);
92+
},
93+
);
94+
},
7795
Grain() {
7896
return any(
7997
regex(/sec(ond)?s?/i, "second"),
@@ -502,6 +520,7 @@ export const Time = createLanguageThis({
502520
parser() {
503521
return dot(
504522
any(
523+
this.ISODateTimeZ,
505524
this.FullDateEra,
506525
this.FullDate,
507526
this.Relative,

tests/Time.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,30 @@ Deno.test("Common", () => {
7676
}
7777
});
7878

79+
Deno.test("ISODateTimeZ", () => {
80+
const res = Duckling([Time.parser]).extract({
81+
text: `Timestamp: 2004-07-12T22:18:09Z.`,
82+
index: 0,
83+
});
84+
85+
assertEquals(res.success, true);
86+
if (res.success) {
87+
assertEquals(res.value, [
88+
{
89+
end: 31,
90+
kind: "time",
91+
start: 11,
92+
text: "2004-07-12T22:18:09Z",
93+
value: {
94+
era: "CE",
95+
grain: "second",
96+
when: "2004-07-12T22:18:09.000Z",
97+
},
98+
},
99+
]);
100+
}
101+
});
102+
79103
Deno.test("GrainQuantity", () => {
80104
const res = Duckling([Time.parser]).extract({
81105
text: `I'll get to it in 5 days, it only takes about 51615 seconds.`,

0 commit comments

Comments
 (0)