feat: ZonedDateTime.compare 跨实例按 epoch 比较(复用 from 解析器,忽略时区/日历)

This commit is contained in:
2026-08-17 01:27:54 +08:00
parent 76edd0d1ea
commit 04bef9f9ac
3 changed files with 98 additions and 1 deletions
@@ -152,7 +152,14 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
world,
zoned_date_time_ctor,
core,
&[("from", oxide_builtins::temporal::zoned_date_time_from::<crate::vm::Vm> as *const (), 1)],
&[
("from", oxide_builtins::temporal::zoned_date_time_from::<crate::vm::Vm> as *const (), 1),
(
"compare",
oxide_builtins::temporal::zoned_date_time_compare::<crate::vm::Vm> as *const (),
2,
),
],
);
let zoned_date_time_proto_ptr = world.zoned_date_time_proto.as_ptr() as *mut JsObject;
@@ -1487,6 +1487,74 @@ fn zoned_date_time_from_options_validation() {
assert_eq!(str_val(&vm, r), "true|true|true");
}
#[test]
fn zoned_date_time_compare_orders_by_epoch() {
let mut vm = Vm::new();
// 按 epoch 大小比较而非墙钟:epoch 大者胜,返回 -1/0/1。
let r = eval(
&mut vm,
"const a = new Temporal.ZonedDateTime(217175010123456789n, 'UTC');
const b = new Temporal.ZonedDateTime(217175010223456789n, 'UTC');
Temporal.ZonedDateTime.compare(a, a) + '|' +
Temporal.ZonedDateTime.compare(a, b) + '|' +
Temporal.ZonedDateTime.compare(b, a)",
)
.unwrap();
assert_eq!(str_val(&vm, r), "0|-1|1");
}
#[test]
fn zoned_date_time_compare_ignores_time_zone_and_calendar() {
let mut vm = Vm::new();
// 同 epoch 不同时区/日历 → 0(只按 epoch 比较)。
let r = eval(
&mut vm,
"const a = new Temporal.ZonedDateTime(0n, '+01:00', 'hebrew');
const b = new Temporal.ZonedDateTime(0n, 'UTC');
const c = new Temporal.ZonedDateTime(1n, '-05:00');
Temporal.ZonedDateTime.compare(a, b) + '|' +
Temporal.ZonedDateTime.compare(b, c)",
)
.unwrap();
assert_eq!(str_val(&vm, r), "0|-1");
}
#[test]
fn zoned_date_time_compare_accepts_string_and_bag() {
let mut vm = Vm::new();
// 字符串 / property bag 参数走 from 解析器归一为 epoch 后比较。
let r = eval(
&mut vm,
"const zdt = new Temporal.ZonedDateTime(0n, 'UTC');
Temporal.ZonedDateTime.compare('1970-01-01T00:00Z[UTC]', zdt) + '|' +
Temporal.ZonedDateTime.compare(
{ year: 1969, month: 12, day: 31, hour: 19, minute: 0, timeZone: '-05:00' },
zdt) + '|' +
Temporal.ZonedDateTime.compare(zdt, '1970-01-01T00:00:01Z[UTC]')",
)
.unwrap();
assert_eq!(str_val(&vm, r), "0|0|-1");
}
#[test]
fn zoned_date_time_compare_error_paths() {
let mut vm = Vm::new();
// 非法字符串 / 缺 timeZone 的 bag / 非转换原始值均抛错(RangeError/TypeError)。
let r = eval(
&mut vm,
"( () => { try { Temporal.ZonedDateTime.compare('garbage', '1970-01-01T00:00Z[UTC]'); return 'no-throw'; }
catch (e) { return e instanceof RangeError; } })() + '|' +
(() => { try { Temporal.ZonedDateTime.compare(
{ year: 2000, month: 1, day: 1 },
'1970-01-01T00:00Z[UTC]'); return 'no-throw'; }
catch (e) { return e instanceof TypeError; } })() + '|' +
(() => { try { Temporal.ZonedDateTime.compare(123, 456); return 'no-throw'; }
catch (e) { return e instanceof TypeError; } })()",
)
.unwrap();
assert_eq!(str_val(&vm, r), "true|true|true");
}
#[test]
fn zoned_date_time_until_defaults_to_hours() {
let mut vm = Vm::new();