Files
datastore/tests/performance/add_days_fixed_offset.xml
ManuelandClaude Fable 5 09de24495a Arithmetic fast path for addDays/addWeeks in fixed-offset time zones
addDays/subtractDays/addWeeks/subtractWeeks on DateTime/DateTime64 went
through the per-row DateLUT calendar step even in UTC and other
fixed-offset time zones, where a day/week is a constant 86400/604800
seconds. addSeconds/addMinutes/addHours already add n*k to the unix
timestamp directly and are several times faster on the same data.

Add an offset_is_fixed flag to DateLUTImpl, computed while filling the
LUT: it is true iff the UTC offset never changes within the LUT range
(no midnight jumps between consecutive days and no intra-day offset
changes). When the flag is set, AddDaysImpl/AddWeeksImpl (and therefore
subtractDays/subtractWeeks and the DateTime +/- INTERVAL DAY/WEEK
operators) add delta * 86400 or delta * 604800 to the timestamp
directly, skipping the LUT lookup and, for DateTime64/Time64, the
std::div decomposition. Time zones with DST or any historical offset
change keep the calendar path, as do MONTH/QUARTER/YEAR intervals.

A parameterized unit test asserts for every known time zone that
reports a fixed offset that DateLUTImpl::addDays is bitwise-equal to
plain arithmetic across the LUT range.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-08 20:00:43 +02:00

22 lines
872 B
XML

<test>
<settings>
<max_threads>1</max_threads>
</settings>
<substitutions>
<substitution>
<name>func</name>
<values>
<value>addDays</value>
<value>addWeeks</value>
<value>subtractDays</value>
<value>subtractWeeks</value>
</values>
</substitution>
</substitutions>
<query>SELECT sum(toUInt32({func}(t, 7))) FROM (SELECT toDateTime(1600000000 + number % 50000000, 'UTC') AS t FROM numbers(100000000))</query>
<query>SELECT sum(toUInt32({func}(t, 7))) FROM (SELECT toDateTime64(1600000000.123 + number % 50000000, 3, 'UTC') AS t FROM numbers(50000000))</query>
<query>SELECT sum(toUInt32({func}(t, 7))) FROM (SELECT toDateTime(1600000000 + number % 50000000, 'Europe/Berlin') AS t FROM numbers(50000000))</query>
</test>