Skip to content

Commit a3900f6

Browse files
committed
fix: some floating point bits
1 parent 574a011 commit a3900f6

File tree

3 files changed

+42
-20
lines changed

3 files changed

+42
-20
lines changed

src/input/datetime.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,31 @@ impl<'a> EitherTimedelta<'a> {
134134
.extract(),
135135
}
136136
}
137+
138+
pub fn total_milliseconds(&self) -> PyResult<f64> {
139+
match self {
140+
Self::Raw(timedelta) => {
141+
let days: f64 = f64::from(timedelta.day);
142+
let seconds: f64 = f64::from(timedelta.second);
143+
let microseconds: f64 = f64::from(timedelta.microsecond);
144+
let total_seconds: f64 = if !timedelta.positive {
145+
-1.0 * (86_400_000.0 * days + seconds * 1_000.0 + microseconds / 1_000.0)
146+
} else {
147+
86_400_000.0 * days + seconds * 1_000.0 + microseconds / 1_000.0
148+
};
149+
Ok(total_seconds)
150+
}
151+
Self::PyExact(py_timedelta) => {
152+
let days: f64 = f64::from(py_timedelta.get_days()); // -999999999 to 999999999
153+
let seconds: f64 = f64::from(py_timedelta.get_seconds()); // 0 through 86399
154+
let microseconds: f64 = f64::from(py_timedelta.get_microseconds()); // 0 through 999999
155+
Ok(86_400_000.0 * days + seconds * 1_000.0 + microseconds / 1_000.0)
156+
}
157+
Self::PySubclass(py_timedelta) => py_timedelta
158+
.call_method0(intern!(py_timedelta.py(), "total_seconds"))?
159+
.extract(),
160+
}
161+
}
137162
}
138163

139164
impl<'a> TryFrom<&'_ Bound<'a, PyAny>> for EitherTimedelta<'a> {

src/serializers/config.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::str::{from_utf8, FromStr, Utf8Error};
44
use base64::Engine;
55
use pyo3::intern;
66
use pyo3::prelude::*;
7-
use pyo3::types::{PyDict, PyFloat, PyString};
7+
use pyo3::types::{PyDict, PyString};
88

99
use serde::ser::Error;
1010

@@ -120,9 +120,8 @@ impl TimedeltaMode {
120120
Ok(seconds.into_py(py))
121121
}
122122
Self::MillisecondsFloat => {
123-
let seconds: f64 = either_delta.total_seconds()?;
124-
let object: Bound<PyFloat> = PyFloat::new_bound(py, seconds * 1000.0);
125-
Ok(object.into_py(py))
123+
let milliseconds: f64 = either_delta.total_milliseconds()?;
124+
Ok(milliseconds.into_py(py))
126125
}
127126
}
128127
}
@@ -138,8 +137,7 @@ impl TimedeltaMode {
138137
Ok(seconds.to_string().into())
139138
}
140139
Self::MillisecondsFloat => {
141-
let seconds: f64 = either_delta.total_seconds()?;
142-
let milliseconds: f64 = seconds * 1000.0;
140+
let milliseconds: f64 = either_delta.total_milliseconds()?;
143141
Ok(milliseconds.to_string().into())
144142
}
145143
}
@@ -160,8 +158,7 @@ impl TimedeltaMode {
160158
serializer.serialize_f64(seconds)
161159
}
162160
Self::MillisecondsFloat => {
163-
let seconds: f64 = either_delta.total_seconds().map_err(py_err_se_err)?;
164-
let milliseconds: f64 = seconds * 1000.0;
161+
let milliseconds: f64 = either_delta.total_milliseconds().map_err(py_err_se_err)?;
165162
serializer.serialize_f64(milliseconds)
166163
}
167164
}

tests/serializers/test_any.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,10 @@ def test_any_with_timedelta_serializer():
194194
(timedelta(microseconds=1), 0.001, b'0.001', {'0.001': 'foo'}, b'{"0.001":"foo"}', 'milliseconds_float'),
195195
(
196196
timedelta(microseconds=-1),
197-
-0.0010000000000287557,
198-
b'-0.0010000000000287557',
199-
{'-0.0010000000000287557': 'foo'},
200-
b'{"-0.0010000000000287557":"foo"}',
197+
-0.0009999999999763531,
198+
b'-0.0009999999999763531',
199+
{'-0.0009999999999763531': 'foo'},
200+
b'{"-0.0009999999999763531":"foo"}',
201201
'milliseconds_float',
202202
),
203203
(
@@ -242,18 +242,18 @@ def test_any_with_timedelta_serializer():
242242
),
243243
(
244244
timedelta(days=1, seconds=1, microseconds=1),
245-
86401000.00099999,
246-
b'86401000.00099999',
247-
{'86401000.00099999': 'foo'},
248-
b'{"86401000.00099999":"foo"}',
245+
86401000.001,
246+
b'86401000.001',
247+
{'86401000.001': 'foo'},
248+
b'{"86401000.001":"foo"}',
249249
'milliseconds_float',
250250
),
251251
(
252252
timedelta(days=-1, seconds=-1, microseconds=-1),
253-
-86401000.00099999,
254-
b'-86401000.00099999',
255-
{'-86401000.00099999': 'foo'},
256-
b'{"-86401000.00099999":"foo"}',
253+
-86401000.001,
254+
b'-86401000.001',
255+
{'-86401000.001': 'foo'},
256+
b'{"-86401000.001":"foo"}',
257257
'milliseconds_float',
258258
),
259259
(timedelta(hours=2), 7200.0, b'7200.0', {'7200': 'foo'}, b'{"7200":"foo"}', 'seconds_float'),

0 commit comments

Comments
 (0)