Skip to content

Implement more datetime polars.Expressions#23097

Closed
mroeschke wants to merge 8 commits into
rapidsai:mainfrom
mroeschke:cudf_polars/enh/5b_effort1_batch3
Closed

Implement more datetime polars.Expressions#23097
mroeschke wants to merge 8 commits into
rapidsai:mainfrom
mroeschke:cudf_polars/enh/5b_effort1_batch3

Conversation

@mroeschke

Copy link
Copy Markdown
Contributor

Description

Implements the following datetime expressions

Expr.dt.century
Expr.dt.millennium
Expr.dt.date
Expr.dt.days_in_month
Expr.dt.quarter
Expr.dt.total_days/hours/minutes/seconds/milliseconds/microseconds/nanoseconds

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@mroeschke mroeschke self-assigned this Jul 3, 2026
@mroeschke mroeschke requested a review from a team as a code owner July 3, 2026 00:22
@mroeschke mroeschke added the improvement Improvement / enhancement to an existing function label Jul 3, 2026
@mroeschke mroeschke requested a review from wence- July 3, 2026 00:22
@mroeschke mroeschke added non-breaking Non-breaking change cudf-polars Issues specific to cudf-polars labels Jul 3, 2026
@github-actions github-actions Bot added the Python Affects Python cuDF API. label Jul 3, 2026
@GPUtester GPUtester moved this to In Progress in cuDF Python Jul 3, 2026
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added support for additional datetime and date operations, including century, millennium, quarter, days-in-month, date-only conversion, and rounding.
    • Expanded handling for duration component extraction with broader validation coverage.
  • Bug Fixes

    • Improved bucket-size validation so unsupported round/truncate frequencies now fail consistently.
    • Added broader date and datetime coverage, including edge cases and extreme year ranges, to improve result accuracy.

Walkthrough

Adds new temporal operations (Century, Millennium, Round, DaysInMonth, Quarter, Date) to cudf_polars' TemporalFunction expression evaluator, extends validation of bucket sizes for Truncate/Round, and adds corresponding parametrized GPU-vs-CPU tests for these operations.

Changes

Temporal Function Extension

Layer / File(s) Summary
Century/Millennium divisor and valid ops
python/cudf_polars/cudf_polars/dsl/expressions/datetime.py
Adds _CENTURY_MILLENNIUM_DIVISOR constant and extends _valid_ops to include Round, Century, Millennium, Date, DaysInMonth, and Quarter.
Bucket validation for Truncate/Round
python/cudf_polars/cudf_polars/dsl/expressions/datetime.py
Updates constructor so bucket parsing/validation applies to both Truncate and Round, raising NotImplementedError for unsupported bucket sizes.
do_evaluate implementation for new ops
python/cudf_polars/cudf_polars/dsl/expressions/datetime.py
Adds evaluation branches for Century/Millennium via fused libcudf AST arithmetic, Round via round_datetimes, DaysInMonth, Quarter, and Date via casting.
Test coverage for new operations
python/cudf_polars/tests/expressions/test_datetime_basic.py
Adds parametrized tests for fractional duration extraction, century/millennium (including extreme years), date extraction, round validity, days_in_month, and quarter, validating GPU/CPU equivalence.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • rapidsai/cudf#18443: Both PRs modify the same TemporalFunction machinery in datetime.py, extending _valid_ops and adding do_evaluate branches for new datetime-related ops.

Suggested reviewers: vyasr

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding more Polars datetime expressions.
Description check ✅ Passed The description matches the implemented datetime expression additions and related tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
python/cudf_polars/tests/expressions/test_datetime_basic.py (2)

223-243: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated literal data list with test_duration_total_component_extract.

The 12-value duration list here is identical to the one in test_duration_total_component_extract a few lines above (Lines 191-209). Consider hoisting it into a shared module-level constant or fixture to avoid duplication and keep both tests in sync if values change.

♻️ Proposed refactor
+_DURATION_TEST_VALUES = [
+    0,
+    1,
+    15,
+    -1500,
+    1000,
+    1111,
+    1500,
+    11111,
+    -134234534,
+    134234534,
+    5857593848682946,
+    -5857593848682946,
+]
+
 def test_duration_total_component_extract(engine: pl.GPUEngine, field, dtype):
     ldf = pl.LazyFrame(
         {
-            "durations": pl.Series(
-                [
-                    0,
-                    1,
-                    ...
-                ],
-                dtype=dtype,
-            ),
+            "durations": pl.Series(_DURATION_TEST_VALUES, dtype=dtype),
         }
     )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/cudf_polars/tests/expressions/test_datetime_basic.py` around lines 223
- 243, The duration values used to build the LazyFrame in this test are
duplicated in test_duration_total_component_extract, so centralize the shared
list into a module-level constant or fixture and reuse it from both tests.
Update the test setup around pl.LazyFrame and pl.Series to reference that shared
source so the two duration component tests stay in sync if the data changes.

216-246: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing empty/single-element series coverage for new temporal ops.

The new tests for total_*(fractional=True), century/millennium, dt.date(), days_in_month(), and quarter() include None values (all-null-element coverage) but none test an empty series or a single-element series, which the test guidelines call out explicitly.

Consider adding at least one empty/single-element case per new operation (or a shared parametrized fixture) to close this gap.

Also applies to: 248-267, 287-305, 625-665

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/cudf_polars/tests/expressions/test_datetime_basic.py` around lines 216
- 246, The new temporal-op tests cover nulls but still miss empty and
single-element series cases. Update the affected test groups around
test_duration_total_component_extract_fractional and the related
century/millennium, dt.date(), days_in_month(), and quarter() tests to add at
least one empty-series and one single-value-series check, ideally via a shared
parametrized helper/fixture so each new op is exercised through those edge
cases.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@python/cudf_polars/tests/expressions/test_datetime_basic.py`:
- Around line 223-243: The duration values used to build the LazyFrame in this
test are duplicated in test_duration_total_component_extract, so centralize the
shared list into a module-level constant or fixture and reuse it from both
tests. Update the test setup around pl.LazyFrame and pl.Series to reference that
shared source so the two duration component tests stay in sync if the data
changes.
- Around line 216-246: The new temporal-op tests cover nulls but still miss
empty and single-element series cases. Update the affected test groups around
test_duration_total_component_extract_fractional and the related
century/millennium, dt.date(), days_in_month(), and quarter() tests to add at
least one empty-series and one single-value-series check, ideally via a shared
parametrized helper/fixture so each new op is exercised through those edge
cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ef08a635-8dcd-4261-884c-6295f475d3a7

📥 Commits

Reviewing files that changed from the base of the PR and between 08f48c2 and cc77c6f.

📒 Files selected for processing (2)
  • python/cudf_polars/cudf_polars/dsl/expressions/datetime.py
  • python/cudf_polars/tests/expressions/test_datetime_basic.py

@mroeschke

Copy link
Copy Markdown
Contributor Author

Closing in favor of individual PRs

@mroeschke mroeschke closed this Jul 7, 2026
@github-project-automation github-project-automation Bot moved this from In Progress to Done in cuDF Python Jul 7, 2026
@mroeschke mroeschke deleted the cudf_polars/enh/5b_effort1_batch3 branch July 7, 2026 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cudf-polars Issues specific to cudf-polars improvement Improvement / enhancement to an existing function non-breaking Non-breaking change Python Affects Python cuDF API.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants