Skip to content

Commit 2896e7b

Browse files
Add support for Temporal objects (#98)
* Add support for Temporal objects * conditionally import polyfill * prettier * changeset --------- Co-authored-by: Rich Harris <[email protected]> Co-authored-by: Rich Harris <[email protected]>
1 parent f9b33eb commit 2896e7b

File tree

7 files changed

+132
-0
lines changed

7 files changed

+132
-0
lines changed

.changeset/blue-groups-beam.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'devalue': minor
3+
---
4+
5+
feat: support Temporal

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"types": "./types/index.d.ts",
2020
"devDependencies": {
2121
"@changesets/cli": "^2.29.6",
22+
"@js-temporal/polyfill": "^0.5.1",
2223
"dts-buddy": "^0.6.2",
2324
"publint": "^0.3.12",
2425
"typescript": "^5.9.2",

pnpm-lock.yaml

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/parse.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,20 @@ export function unflatten(parsed, revivers) {
131131
break;
132132
}
133133

134+
case 'Temporal.Duration':
135+
case 'Temporal.Instant':
136+
case 'Temporal.PlainDate':
137+
case 'Temporal.PlainTime':
138+
case 'Temporal.PlainDateTime':
139+
case 'Temporal.PlainMonthDay':
140+
case 'Temporal.PlainYearMonth':
141+
case 'Temporal.ZonedDateTime': {
142+
const temporalName = type.slice(9);
143+
// @ts-expect-error TS doesn't know about Temporal yet
144+
hydrated[index] = Temporal[temporalName].from(value[1]);
145+
break;
146+
}
147+
134148
default:
135149
throw new Error(`Unknown type ${type}`);
136150
}

src/stringify.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,17 @@ export function stringify(value, reducers) {
177177
break;
178178
}
179179

180+
case 'Temporal.Duration':
181+
case 'Temporal.Instant':
182+
case 'Temporal.PlainDate':
183+
case 'Temporal.PlainTime':
184+
case 'Temporal.PlainDateTime':
185+
case 'Temporal.PlainMonthDay':
186+
case 'Temporal.PlainYearMonth':
187+
case 'Temporal.ZonedDateTime':
188+
str = `["${type}",${stringify_string(thing.toString())}]`;
189+
break;
190+
180191
default:
181192
if (!is_plain_object(thing)) {
182193
throw new DevalueError(

src/uneval.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,16 @@ export function uneval(value, replacer) {
100100
case 'ArrayBuffer':
101101
return;
102102

103+
case 'Temporal.Duration':
104+
case 'Temporal.Instant':
105+
case 'Temporal.PlainDate':
106+
case 'Temporal.PlainTime':
107+
case 'Temporal.PlainDateTime':
108+
case 'Temporal.PlainMonthDay':
109+
case 'Temporal.PlainYearMonth':
110+
case 'Temporal.ZonedDateTime':
111+
return;
112+
103113
default:
104114
if (!is_plain_object(thing)) {
105115
throw new DevalueError(
@@ -216,6 +226,16 @@ export function uneval(value, replacer) {
216226
return `new Uint8Array([${ui8.toString()}]).buffer`;
217227
}
218228

229+
case 'Temporal.Duration':
230+
case 'Temporal.Instant':
231+
case 'Temporal.PlainDate':
232+
case 'Temporal.PlainTime':
233+
case 'Temporal.PlainDateTime':
234+
case 'Temporal.PlainMonthDay':
235+
case 'Temporal.PlainYearMonth':
236+
case 'Temporal.ZonedDateTime':
237+
return `${type}.from(${stringify_string(thing.toString())})`;
238+
219239
default:
220240
const obj = `{${Object.keys(thing)
221241
.map((key) => `${safe_key(key)}:${stringify(thing[key])}`)

test/test.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import * as assert from 'uvu/assert';
33
import * as uvu from 'uvu';
44
import { uneval, unflatten, parse, stringify } from '../index.js';
55

6+
globalThis.Temporal ??= (await import('@js-temporal/polyfill')).Temporal;
7+
68
class Custom {
79
constructor(value) {
810
this.value = value;
@@ -183,6 +185,69 @@ const fixtures = {
183185
value: new Uint16Array([10, 20, 30, 40]).subarray(1, 3),
184186
js: 'new Uint16Array([10,20,30,40]).subarray(1,3)',
185187
json: '[["Uint16Array",1,1,3],["ArrayBuffer","CgAUAB4AKAA="]]'
188+
},
189+
{
190+
name: 'Temporal.Duration',
191+
value: Temporal.Duration.from({ years: 1, months: 2, days: 3 }),
192+
js: 'Temporal.Duration.from("P1Y2M3D")',
193+
json: '[["Temporal.Duration","P1Y2M3D"]]'
194+
},
195+
{
196+
name: 'Temporal.Instant',
197+
value: Temporal.Instant.from('1999-09-29T05:30:00Z'),
198+
js: 'Temporal.Instant.from("1999-09-29T05:30:00Z")',
199+
json: '[["Temporal.Instant","1999-09-29T05:30:00Z"]]'
200+
},
201+
{
202+
name: 'Temporal.PlainDate',
203+
value: Temporal.PlainDate.from({ year: 1999, month: 9, day: 29 }),
204+
js: 'Temporal.PlainDate.from("1999-09-29")',
205+
json: '[["Temporal.PlainDate","1999-09-29"]]'
206+
},
207+
{
208+
name: 'Temporal.PlainTime',
209+
value: Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56 }),
210+
js: 'Temporal.PlainTime.from("12:34:56")',
211+
json: '[["Temporal.PlainTime","12:34:56"]]'
212+
},
213+
{
214+
name: 'Temporal.PlainDateTime',
215+
value: Temporal.PlainDateTime.from({
216+
year: 1999,
217+
month: 9,
218+
day: 29,
219+
hour: 12,
220+
minute: 34,
221+
second: 56
222+
}),
223+
js: 'Temporal.PlainDateTime.from("1999-09-29T12:34:56")',
224+
json: '[["Temporal.PlainDateTime","1999-09-29T12:34:56"]]'
225+
},
226+
{
227+
name: 'Temporal.PlainMonthDay',
228+
value: Temporal.PlainMonthDay.from({ month: 9, day: 29 }),
229+
js: 'Temporal.PlainMonthDay.from("09-29")',
230+
json: '[["Temporal.PlainMonthDay","09-29"]]'
231+
},
232+
{
233+
name: 'Temporal.PlainYearMonth',
234+
value: Temporal.PlainYearMonth.from({ year: 1999, month: 9 }),
235+
js: 'Temporal.PlainYearMonth.from("1999-09")',
236+
json: '[["Temporal.PlainYearMonth","1999-09"]]'
237+
},
238+
{
239+
name: 'Temporal.ZonedDateTime',
240+
value: Temporal.ZonedDateTime.from({
241+
year: 1999,
242+
month: 9,
243+
day: 29,
244+
hour: 12,
245+
minute: 34,
246+
second: 56,
247+
timeZone: 'Europe/Rome'
248+
}),
249+
js: 'Temporal.ZonedDateTime.from("1999-09-29T12:34:56+02:00[Europe/Rome]")',
250+
json: '[["Temporal.ZonedDateTime","1999-09-29T12:34:56+02:00[Europe/Rome]"]]'
186251
}
187252
],
188253

0 commit comments

Comments
 (0)