Skip to content

Commit f939a06

Browse files
committed
fix durartion to round
1 parent 8d07c45 commit f939a06

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

crates/vm/src/convert/try_from.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,25 @@ impl TryFromObject for core::time::Duration {
126126
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
127127
if let Some(float) = obj.downcast_ref::<PyFloat>() {
128128
let f = float.to_f64();
129+
if f.is_nan() {
130+
return Err(
131+
vm.new_value_error("Invalid value NaN (not a number)".to_owned())
132+
);
133+
}
129134
if f < 0.0 {
130-
return Err(vm.new_value_error("negative duration"));
135+
return Err(vm.new_value_error("negative duration".to_owned()));
136+
}
137+
if !f.is_finite() || f > u64::MAX as f64 {
138+
return Err(vm.new_overflow_error(
139+
"timestamp too large to convert to C PyTime_t".to_owned(),
140+
));
131141
}
132-
Ok(Self::from_secs_f64(f))
142+
// Convert float to Duration using floor rounding (_PyTime_ROUND_FLOOR)
143+
let secs = f.trunc() as u64;
144+
let frac = f.fract();
145+
// Use floor to round down the nanoseconds
146+
let nanos = (frac * 1_000_000_000.0).floor() as u32;
147+
Ok(Self::new(secs, nanos))
133148
} else if let Some(int) = obj.try_index_opt(vm) {
134149
let int = int?;
135150
let bigint = int.as_bigint();

0 commit comments

Comments
 (0)