feat: implement Temporal Instant differences

This commit is contained in:
爱特每羊队
2026-08-11 18:22:21 +08:00
parent d443808d96
commit 6b00eaaf06
3 changed files with 199 additions and 0 deletions
@@ -89,8 +89,10 @@ pub fn bind_temporal(core: &Arc<KernelCore>, session: &KernelSession, global: &m
("add", oxide_builtins::temporal::instant_add::<crate::vm::Vm> as *const (), 1),
("equals", oxide_builtins::temporal::instant_equals::<crate::vm::Vm> as *const (), 1),
("round", oxide_builtins::temporal::instant_round::<crate::vm::Vm> as *const (), 1),
("since", oxide_builtins::temporal::instant_since::<crate::vm::Vm> as *const (), 1),
("subtract", oxide_builtins::temporal::instant_subtract::<crate::vm::Vm> as *const (), 1),
("toString", oxide_builtins::temporal::instant_to_string::<crate::vm::Vm> as *const (), 0),
("until", oxide_builtins::temporal::instant_until::<crate::vm::Vm> as *const (), 1),
("valueOf", oxide_builtins::temporal::instant_value_of::<crate::vm::Vm> as *const (), 0),
],
);
@@ -258,6 +258,43 @@ fn instant_round_handles_nested_destructured_callback_captures() {
assert!(r.as_bool());
}
#[test]
fn instant_until_and_since_balance_exact_differences() {
let mut vm = Vm::new();
let r = eval(
&mut vm,
"let earlier = new Temporal.Instant(1000000000000000000n);
let later = new Temporal.Instant(1000090061987654321n);
let exact = earlier.until(later);
let hours = later.since(earlier, { largestUnit: 'hours' });
exact.seconds === 90061 && exact.milliseconds === 987
&& exact.microseconds === 654 && exact.nanoseconds === 321
&& hours.hours === 25 && hours.minutes === 1 && hours.seconds === 1
&& hours.milliseconds === 987 && hours.microseconds === 654 && hours.nanoseconds === 321",
)
.unwrap();
assert!(r.as_bool());
}
#[test]
fn instant_difference_rounds_signed_values_and_validates_units() {
let mut vm = Vm::new();
let r = eval(
&mut vm,
"let zero = new Temporal.Instant(0n), value = new Temporal.Instant(7199000000000n);
let positive = zero.until(value, { largestUnit: 'hours', smallestUnit: 'minutes', roundingMode: 'expand' });
let negative = zero.since(value, { largestUnit: 'hours', smallestUnit: 'minutes', roundingMode: 'expand' });
positive.hours === 2 && positive.minutes === 0
&& negative.hours === -2 && negative.minutes === 0
&& (() => { try { zero.until(value, { largestUnit: 'seconds', smallestUnit: 'hours' }); return false }
catch (e) { return e instanceof RangeError } })()
&& (() => { try { zero.until(value, { smallestUnit: 'minutes', roundingIncrement: 60 }); return false }
catch (e) { return e instanceof RangeError } })()",
)
.unwrap();
assert!(r.as_bool());
}
#[test]
fn instant_epoch_factories_validate_input_and_range() {
let mut vm = Vm::new();