Skip to content

Commit 252f123

Browse files
authored
fix: Properly calculate duration units (#18869)
1 parent 66960ff commit 252f123

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

crates/polars-ops/src/series/ops/duration.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,24 @@ pub fn impl_duration(s: &[Column], time_unit: TimeUnit) -> PolarsResult<Column>
7272
TimeUnit::Milliseconds => MILLISECONDS,
7373
};
7474
if !is_zero_scalar(&seconds) {
75-
duration = ((duration + seconds)? * multiplier)?;
75+
let units = seconds * multiplier;
76+
duration = (duration + units?)?;
7677
}
7778
if !is_zero_scalar(&minutes) {
78-
duration = ((duration + minutes)? * (multiplier * 60))?;
79+
let units = minutes * (multiplier * 60);
80+
duration = (duration + units?)?;
7981
}
8082
if !is_zero_scalar(&hours) {
81-
duration = ((duration + hours)? * (multiplier * 60 * 60))?;
83+
let units = hours * (multiplier * 60 * 60);
84+
duration = (duration + units?)?;
8285
}
8386
if !is_zero_scalar(&days) {
84-
duration = ((duration + days)? * (multiplier * SECONDS_IN_DAY))?;
87+
let units = days * (multiplier * SECONDS_IN_DAY);
88+
duration = (duration + units?)?;
8589
}
8690
if !is_zero_scalar(&weeks) {
87-
duration = ((duration + weeks)? * (multiplier * SECONDS_IN_DAY * 7))?;
91+
let units = weeks * (multiplier * SECONDS_IN_DAY * 7);
92+
duration = (duration + units?)?;
8893
}
8994

9095
duration

py-polars/tests/unit/datatypes/test_duration.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,36 @@ def test_series_duration_var_overflow() -> None:
6060
s = pl.Series([timedelta(days=10), timedelta(days=20), timedelta(days=40)])
6161
with pytest.raises(PanicException, match="OverflowError"):
6262
s.var()
63+
64+
65+
def test_series_duration_units() -> None:
66+
td = timedelta
67+
68+
assert_frame_equal(
69+
pl.DataFrame({"x": [0, 1, 2, 3]}).select(x=pl.duration(weeks=pl.col("x"))),
70+
pl.DataFrame({"x": [td(weeks=i) for i in range(4)]}),
71+
)
72+
assert_frame_equal(
73+
pl.DataFrame({"x": [0, 1, 2, 3]}).select(x=pl.duration(days=pl.col("x"))),
74+
pl.DataFrame({"x": [td(days=i) for i in range(4)]}),
75+
)
76+
assert_frame_equal(
77+
pl.DataFrame({"x": [0, 1, 2, 3]}).select(x=pl.duration(hours=pl.col("x"))),
78+
pl.DataFrame({"x": [td(hours=i) for i in range(4)]}),
79+
)
80+
assert_frame_equal(
81+
pl.DataFrame({"x": [0, 1, 2, 3]}).select(x=pl.duration(minutes=pl.col("x"))),
82+
pl.DataFrame({"x": [td(minutes=i) for i in range(4)]}),
83+
)
84+
assert_frame_equal(
85+
pl.DataFrame({"x": [0, 1, 2, 3]}).select(
86+
x=pl.duration(milliseconds=pl.col("x"))
87+
),
88+
pl.DataFrame({"x": [td(milliseconds=i) for i in range(4)]}),
89+
)
90+
assert_frame_equal(
91+
pl.DataFrame({"x": [0, 1, 2, 3]}).select(
92+
x=pl.duration(microseconds=pl.col("x"))
93+
),
94+
pl.DataFrame({"x": [td(microseconds=i) for i in range(4)]}),
95+
)

0 commit comments

Comments
 (0)