Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/py-polars/tests/unit/functions/range/test_date_range.py
8406 views
1
from __future__ import annotations
2
3
import os
4
from datetime import date, datetime
5
6
import pytest
7
8
import polars as pl
9
from polars.exceptions import ComputeError, InvalidOperationError, ShapeError
10
from polars.testing import assert_frame_equal, assert_series_equal
11
12
13
def test_date_range() -> None:
14
# if low/high are both date, range is also be date _iff_ the granularity is >= 1d
15
result = pl.date_range(date(2022, 1, 1), date(2022, 3, 1), "1mo", eager=True)
16
assert result.to_list() == [date(2022, 1, 1), date(2022, 2, 1), date(2022, 3, 1)]
17
18
19
def test_date_range_invalid_time_unit() -> None:
20
with pytest.raises(InvalidOperationError, match="'x' not supported"):
21
pl.date_range(
22
start=date(2021, 12, 16),
23
end=date(2021, 12, 18),
24
interval="1X",
25
eager=True,
26
)
27
28
29
def test_date_range_end_of_month_5441() -> None:
30
result = pl.date_range(
31
start=date(2020, 1, 31),
32
end=date(2020, 3, 31),
33
interval="1mo",
34
closed="both",
35
eager=True,
36
)
37
expected = pl.Series(
38
"literal", [date(2020, 1, 31), date(2020, 2, 29), date(2020, 3, 31)]
39
)
40
assert_series_equal(result, expected)
41
42
43
def test_date_range_name() -> None:
44
result_eager = pl.date_range(
45
start=date(2020, 1, 1), end=date(2020, 1, 3), eager=True
46
)
47
assert result_eager.name == "literal"
48
49
start = pl.Series("left", [date(2020, 1, 1)])
50
result_lazy = pl.select(
51
pl.date_range(pl.lit(start).first(), date(2020, 1, 3), eager=False)
52
).to_series()
53
assert result_lazy.name == "left"
54
55
56
def test_date_range_eager() -> None:
57
result = pl.date_range(start=date(2022, 1, 1), end=date(2022, 1, 3), eager=True)
58
expected = pl.Series(
59
"literal", [date(2022, 1, 1), date(2022, 1, 2), date(2022, 1, 3)]
60
)
61
assert_series_equal(result, expected)
62
63
64
def test_date_range_input_shape_empty() -> None:
65
empty = pl.Series(dtype=pl.Datetime)
66
single = pl.Series([datetime(2022, 1, 2)])
67
68
with pytest.raises(ShapeError):
69
pl.date_range(start=empty, end=single, eager=True)
70
with pytest.raises(ShapeError):
71
pl.date_range(start=single, end=empty, eager=True)
72
with pytest.raises(ShapeError):
73
pl.date_range(start=empty, end=empty, eager=True)
74
75
76
def test_date_range_input_shape_multiple_values() -> None:
77
single = pl.Series([datetime(2022, 1, 2)])
78
multiple = pl.Series([datetime(2022, 1, 3), datetime(2022, 1, 4)])
79
80
with pytest.raises(ShapeError):
81
pl.date_range(start=multiple, end=single, eager=True)
82
with pytest.raises(ShapeError):
83
pl.date_range(start=single, end=multiple, eager=True)
84
with pytest.raises(ShapeError):
85
pl.date_range(start=multiple, end=multiple, eager=True)
86
87
88
def test_date_range_start_later_than_end() -> None:
89
result = pl.date_range(start=date(2000, 3, 20), end=date(2000, 3, 5), eager=True)
90
expected = pl.Series("literal", dtype=pl.Date)
91
assert_series_equal(result, expected)
92
93
94
def test_date_range_24h_interval_raises() -> None:
95
with pytest.raises(
96
ComputeError,
97
match="`interval` input for `date_range` must consist of full days",
98
):
99
pl.date_range(
100
start=date(2022, 1, 1), end=date(2022, 1, 3), interval="24h", eager=True
101
)
102
103
104
def test_long_date_range_12461() -> None:
105
morsel_size_env = os.environ.get("POLARS_IDEAL_MORSEL_SIZE")
106
if morsel_size_env is not None and int(morsel_size_env) < 1000:
107
pytest.skip("test is too slow for small morsel sizes")
108
result = pl.date_range(
109
start=date(1900, 1, 1), end=date(2300, 1, 1), interval="1d", eager=True
110
)
111
assert result[0] == date(1900, 1, 1)
112
assert result[-1] == date(2300, 1, 1)
113
assert (result.diff()[1:].dt.total_days() == 1).all()
114
115
116
def test_date_range_datetime_input() -> None:
117
result = pl.date_range(
118
start=datetime(2022, 1, 1, 12),
119
end=datetime(2022, 1, 3),
120
interval="1d",
121
eager=True,
122
)
123
expected = pl.Series(
124
"literal", [date(2022, 1, 1), date(2022, 1, 2), date(2022, 1, 3)]
125
)
126
assert_series_equal(result, expected)
127
128
129
def test_date_ranges_datetime_input() -> None:
130
result = pl.date_ranges(
131
start=datetime(2022, 1, 1, 12),
132
end=datetime(2022, 1, 3),
133
interval="1d",
134
eager=True,
135
)
136
expected = pl.Series(
137
"literal", [[date(2022, 1, 1), date(2022, 1, 2), date(2022, 1, 3)]]
138
)
139
assert_series_equal(result, expected)
140
141
142
def test_date_range_with_subclass_18470_18447() -> None:
143
class MyAmazingDate(date):
144
pass
145
146
class MyAmazingDatetime(datetime):
147
pass
148
149
result = pl.datetime_range(
150
start=MyAmazingDate(2020, 1, 1), end=MyAmazingDatetime(2020, 1, 2), eager=True
151
)
152
expected = pl.Series("literal", [datetime(2020, 1, 1), datetime(2020, 1, 2)])
153
assert_series_equal(result, expected)
154
155
156
# start/end/interval
157
def test_date_range_start_end_interval_forwards() -> None:
158
start = date(2025, 1, 1)
159
end = date(2025, 1, 10)
160
161
assert_series_equal(
162
pl.date_range(start=start, end=end, interval="3d", closed="left", eager=True),
163
pl.Series("literal", [date(2025, 1, 1), date(2025, 1, 4), date(2025, 1, 7)]),
164
)
165
assert_series_equal(
166
pl.date_range(start=start, end=end, interval="3d", closed="right", eager=True),
167
pl.Series("literal", [date(2025, 1, 4), date(2025, 1, 7), date(2025, 1, 10)]),
168
)
169
assert_series_equal(
170
pl.date_range(start=start, end=end, interval="3d", closed="none", eager=True),
171
pl.Series("literal", [date(2025, 1, 4), date(2025, 1, 7)]),
172
)
173
assert_series_equal(
174
pl.date_range(start=start, end=end, interval="3d", closed="both", eager=True),
175
pl.Series(
176
"literal",
177
[date(2025, 1, 1), date(2025, 1, 4), date(2025, 1, 7), date(2025, 1, 10)],
178
),
179
)
180
# test wrong direction is empty
181
assert_series_equal(
182
pl.date_range(start=end, end=start, interval="3d", eager=True),
183
pl.Series("literal", [], dtype=pl.Date),
184
)
185
186
187
def test_date_range_expr_scalar() -> None:
188
df = pl.DataFrame(
189
{
190
"a": [date(2025, 1, 3), date(2025, 1, 1)],
191
"interval": ["1d", "2d"],
192
}
193
)
194
result = df.select(
195
forward_start_end_interval=pl.date_range(
196
start=pl.col("a").min(), end=pl.col("a").max(), interval="1d"
197
),
198
)
199
forward = [date(2025, 1, 1), date(2025, 1, 2), date(2025, 1, 3)]
200
expected = pl.DataFrame(
201
{
202
"forward_start_end_interval": forward,
203
}
204
)
205
assert_frame_equal(result, expected)
206
207