Path: blob/main/py-polars/tests/unit/functions/range/test_date_range.py
8406 views
from __future__ import annotations12import os3from datetime import date, datetime45import pytest67import polars as pl8from polars.exceptions import ComputeError, InvalidOperationError, ShapeError9from polars.testing import assert_frame_equal, assert_series_equal101112def test_date_range() -> None:13# if low/high are both date, range is also be date _iff_ the granularity is >= 1d14result = pl.date_range(date(2022, 1, 1), date(2022, 3, 1), "1mo", eager=True)15assert result.to_list() == [date(2022, 1, 1), date(2022, 2, 1), date(2022, 3, 1)]161718def test_date_range_invalid_time_unit() -> None:19with pytest.raises(InvalidOperationError, match="'x' not supported"):20pl.date_range(21start=date(2021, 12, 16),22end=date(2021, 12, 18),23interval="1X",24eager=True,25)262728def test_date_range_end_of_month_5441() -> None:29result = pl.date_range(30start=date(2020, 1, 31),31end=date(2020, 3, 31),32interval="1mo",33closed="both",34eager=True,35)36expected = pl.Series(37"literal", [date(2020, 1, 31), date(2020, 2, 29), date(2020, 3, 31)]38)39assert_series_equal(result, expected)404142def test_date_range_name() -> None:43result_eager = pl.date_range(44start=date(2020, 1, 1), end=date(2020, 1, 3), eager=True45)46assert result_eager.name == "literal"4748start = pl.Series("left", [date(2020, 1, 1)])49result_lazy = pl.select(50pl.date_range(pl.lit(start).first(), date(2020, 1, 3), eager=False)51).to_series()52assert result_lazy.name == "left"535455def test_date_range_eager() -> None:56result = pl.date_range(start=date(2022, 1, 1), end=date(2022, 1, 3), eager=True)57expected = pl.Series(58"literal", [date(2022, 1, 1), date(2022, 1, 2), date(2022, 1, 3)]59)60assert_series_equal(result, expected)616263def test_date_range_input_shape_empty() -> None:64empty = pl.Series(dtype=pl.Datetime)65single = pl.Series([datetime(2022, 1, 2)])6667with pytest.raises(ShapeError):68pl.date_range(start=empty, end=single, eager=True)69with pytest.raises(ShapeError):70pl.date_range(start=single, end=empty, eager=True)71with pytest.raises(ShapeError):72pl.date_range(start=empty, end=empty, eager=True)737475def test_date_range_input_shape_multiple_values() -> None:76single = pl.Series([datetime(2022, 1, 2)])77multiple = pl.Series([datetime(2022, 1, 3), datetime(2022, 1, 4)])7879with pytest.raises(ShapeError):80pl.date_range(start=multiple, end=single, eager=True)81with pytest.raises(ShapeError):82pl.date_range(start=single, end=multiple, eager=True)83with pytest.raises(ShapeError):84pl.date_range(start=multiple, end=multiple, eager=True)858687def test_date_range_start_later_than_end() -> None:88result = pl.date_range(start=date(2000, 3, 20), end=date(2000, 3, 5), eager=True)89expected = pl.Series("literal", dtype=pl.Date)90assert_series_equal(result, expected)919293def test_date_range_24h_interval_raises() -> None:94with pytest.raises(95ComputeError,96match="`interval` input for `date_range` must consist of full days",97):98pl.date_range(99start=date(2022, 1, 1), end=date(2022, 1, 3), interval="24h", eager=True100)101102103def test_long_date_range_12461() -> None:104morsel_size_env = os.environ.get("POLARS_IDEAL_MORSEL_SIZE")105if morsel_size_env is not None and int(morsel_size_env) < 1000:106pytest.skip("test is too slow for small morsel sizes")107result = pl.date_range(108start=date(1900, 1, 1), end=date(2300, 1, 1), interval="1d", eager=True109)110assert result[0] == date(1900, 1, 1)111assert result[-1] == date(2300, 1, 1)112assert (result.diff()[1:].dt.total_days() == 1).all()113114115def test_date_range_datetime_input() -> None:116result = pl.date_range(117start=datetime(2022, 1, 1, 12),118end=datetime(2022, 1, 3),119interval="1d",120eager=True,121)122expected = pl.Series(123"literal", [date(2022, 1, 1), date(2022, 1, 2), date(2022, 1, 3)]124)125assert_series_equal(result, expected)126127128def test_date_ranges_datetime_input() -> None:129result = pl.date_ranges(130start=datetime(2022, 1, 1, 12),131end=datetime(2022, 1, 3),132interval="1d",133eager=True,134)135expected = pl.Series(136"literal", [[date(2022, 1, 1), date(2022, 1, 2), date(2022, 1, 3)]]137)138assert_series_equal(result, expected)139140141def test_date_range_with_subclass_18470_18447() -> None:142class MyAmazingDate(date):143pass144145class MyAmazingDatetime(datetime):146pass147148result = pl.datetime_range(149start=MyAmazingDate(2020, 1, 1), end=MyAmazingDatetime(2020, 1, 2), eager=True150)151expected = pl.Series("literal", [datetime(2020, 1, 1), datetime(2020, 1, 2)])152assert_series_equal(result, expected)153154155# start/end/interval156def test_date_range_start_end_interval_forwards() -> None:157start = date(2025, 1, 1)158end = date(2025, 1, 10)159160assert_series_equal(161pl.date_range(start=start, end=end, interval="3d", closed="left", eager=True),162pl.Series("literal", [date(2025, 1, 1), date(2025, 1, 4), date(2025, 1, 7)]),163)164assert_series_equal(165pl.date_range(start=start, end=end, interval="3d", closed="right", eager=True),166pl.Series("literal", [date(2025, 1, 4), date(2025, 1, 7), date(2025, 1, 10)]),167)168assert_series_equal(169pl.date_range(start=start, end=end, interval="3d", closed="none", eager=True),170pl.Series("literal", [date(2025, 1, 4), date(2025, 1, 7)]),171)172assert_series_equal(173pl.date_range(start=start, end=end, interval="3d", closed="both", eager=True),174pl.Series(175"literal",176[date(2025, 1, 1), date(2025, 1, 4), date(2025, 1, 7), date(2025, 1, 10)],177),178)179# test wrong direction is empty180assert_series_equal(181pl.date_range(start=end, end=start, interval="3d", eager=True),182pl.Series("literal", [], dtype=pl.Date),183)184185186def test_date_range_expr_scalar() -> None:187df = pl.DataFrame(188{189"a": [date(2025, 1, 3), date(2025, 1, 1)],190"interval": ["1d", "2d"],191}192)193result = df.select(194forward_start_end_interval=pl.date_range(195start=pl.col("a").min(), end=pl.col("a").max(), interval="1d"196),197)198forward = [date(2025, 1, 1), date(2025, 1, 2), date(2025, 1, 3)]199expected = pl.DataFrame(200{201"forward_start_end_interval": forward,202}203)204assert_frame_equal(result, expected)205206207