Repository navigation
GH-47400: [C++] Support adding/subtracting intervals to/from timestamps - #53325
Open
DeviousCardi wants to merge 1 commit into
Open
DeviousCardi wants to merge 1 commit into
DeviousCardi wants to merge 1 commit into
Conversation
…mestamps
Add add, add_checked, subtract and subtract_checked kernels for
timestamp +/- {month_interval, day_time_interval, month_day_nano_interval},
with and without a timezone (add also accepts the interval first).
Months and days are calendar units applied to the local time of the
timestamp, while the sub-day part of the interval is a fixed duration,
following pandas.DateOffset. add applies months, days, then the sub-day
part; subtract applies the sub-day part first. Adding months clamps the
day of month. Ambiguous or nonexistent resulting local times return an
error, and the checked variants detect overflow.
Implicit temporal promotion is no longer applied in arithmetic dispatch
when an argument is an interval, so that e.g. date32 + interval is not
silently cast to a timestamp.
DeviousCardi
requested review from
AlenkaF,
pitrou,
raulcd and
rok
as code owners
October 12, 2026 15:41
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rationale for this change
There is currently no kernel for
timestamp + interval, so e.g. "add one day to a zoned timestamp, keeping the wall clock time" requires a round trip through pandas (see #47400).What changes are included in this PR?
New kernels for
add,add_checked,subtractandsubtract_checked:timestamp(unit, tz) ± month_interval / day_time_interval / month_day_nano_interval -> timestamp(unit, tz), for all four units, with or without a timezoneadd/add_checkedalso accept the interval as the first argumentSemantics follow the discussion in the issue (Pandas'
DateOffset):2025-03-08 09:30 EST + 1 day = 2025-03-09 09:30 EDT.day_time_interval, nanoseconds of amonth_day_nano_interval) is a fixed duration, so2025-03-08 09:30 EST + 24h = 2025-03-09 10:30 EDT.addapplies months, then days, then the sub-day part.subtractapplies the sub-day part first, so subtracting "1 day 24 hours" undoes adding it (the mixed-interval examples in the issue). Months are applied before days in both directions, as inDateOffsetand PostgreSQL.Invaliderror is returned, with the same messages as the existingZonedLocalizer::ConvertLocalToSys. This is also what pandas does for a tz-awareSeries/DatetimeIndex+DateOffset(a scalarTimestampsilently resolves instead). The issue doesn't settle this point. If wanted, a follow-up could add an option to chooseearliest/latest/shift-forward likeAssumeTimezoneOptions.timestamp[s]) returnsInvalid._checkedvariants returnInvalidon int64 overflow; the unchecked variants wrap around like the other arithmetic kernels.Calendar arithmetic uses 64-bit year arithmetic, so the full range of
timestamp[s]is supported. The timezone lookups use the existingLocateZone/time_zone::get_infomachinery fromtemporal_internal.h.ArithmeticFunction::DispatchBestno longer applies implicit temporal promotion when one of the arguments is an interval. Otherwisedate32 + intervalwould be silently cast totimestamp[s] + interval. Dates are not supported yet; I'd suggest doing them in a follow-up once we agree on whatdate + interval with a sub-day partshould return.Are these changes tested?
Yes:
scalar_temporal_test.cc): month-end clamping, leap years, negative intervals, nulls, all units and all three interval types, both argument orders. DST transitions are covered in America/New_York, Europe/London and Australia/Lord_Howe (30 min DST), including results that land just after a gap or overlap and results that fall inside one (errors), plus a fixed-offset timezone. Error tests cover sub-unit and overflow cases. The expected DST values were checked against pandas 3.0.6.test_compute.py): parity withpandas.DateOffset+Timedeltaacross timezones and units, and the same DST gap/overlap errors as pandas.Are there any user-facing changes?
Yes, new kernels for
add/subtract(documented incompute.rst). Existing kernels are unchanged.AI usage disclosure: I used an AI coding assistant (Claude) for this PR. It drafted most of the kernel code, the C++ and Python tests, and the docs paragraph. I reviewed all of it, and the expected DST values in the tests were checked against pandas independently of the kernel. The 64-bit calendar helpers (
DaysFromCivil/CivilFromDays) follow Howard Hinnant's public-domain date algorithms, which are linked in a comment.