RustPython/RustPython · error · OverflowError

result out of range

Error message

result out of range

What it means

Raised by date.__add__ when adding a timedelta moves the result outside the representable date range (year 1-01-01 through year 9999-12-31, i.e. ordinals 1 to date.max.toordinal()). Dates are stored as proleptic Gregorian ordinals and cannot wrap around or go below day 1, so any addition whose target ordinal is <= 0 or > _MAXORDINAL is rejected with OverflowError instead of producing an invalid date.

Source

Thrown at Lib/_pydatetime.py:1218

        y, m, d = self._year, self._month, self._day
        y2, m2, d2 = other._year, other._month, other._day
        return _cmp((y, m, d), (y2, m2, d2))

    def __hash__(self):
        "Hash."
        if self._hashcode == -1:
            self._hashcode = hash(self._getstate())
        return self._hashcode

    # Computations

    def __add__(self, other):
        "Add a date to a timedelta."
        if isinstance(other, timedelta):
            o = self.toordinal() + other.days
            if 0 < o <= _MAXORDINAL:
                return type(self).fromordinal(o)
            raise OverflowError("result out of range")
        return NotImplemented

    __radd__ = __add__

    def __sub__(self, other):
        """Subtract two dates, or a date and a timedelta."""
        if isinstance(other, timedelta):
            return self + timedelta(-other.days)
        if isinstance(other, date):
            days1 = self.toordinal()
            days2 = other.toordinal()
            return timedelta(days1 - days2)
        return NotImplemented

    def weekday(self):
        "Return day of the week, where Monday == 0 ... Sunday == 6."
        return (self.toordinal() + 6) % 7

View on GitHub (pinned to aaeab4f754)

Solutions

  1. Validate the target ordinal before adding: 1 <= d.toordinal() + delta.days <= date.max.toordinal(); reject or clamp the input if outside.
  2. Catch OverflowError at the boundary and clamp to date.min/date.max or surface a user-facing 'date out of range' message.
  3. Bound the offset itself (cap timedelta.days) when it originates from user input or configuration.
  4. If dates outside year 1..9999 are genuinely needed, switch representation (integer year/month/day or a third-party date type) instead of fighting the limit.

Example fix

// before
d = start + timedelta(days=offset)  # OverflowError when start is near date.max

// after
from datetime import date, timedelta

def add_days(d: date, offset: int) -> date:
    ordinal = d.toordinal() + offset
    if not 1 <= ordinal <= date.max.toordinal():
        raise OverflowError(f'{offset} days from {d} leaves year 1..9999')
    return d + timedelta(days=offset)
Defensive patterns

Strategy: validation

Validate before calling

from datetime import date, timedelta

def safe_date_add(d: date, delta: timedelta) -> date:
    target = d.toordinal() + delta.days
    if not 1 <= target <= date.max.toordinal():
        raise OverflowError(f'{delta} moves {d} outside year 1..9999')
    return d + delta

Try / catch

try:
    result = d + delta
except OverflowError:
    result = date.max  # or reject the request with a user-facing error

Prevention

When it happens

Trigger: date.max + timedelta(days=1); date(1, 1, 1) + timedelta(days=-1); date(9999, 12, 31) + timedelta(weeks=2); day-stepping loops (d += timedelta(days=1)) that run past the horizon; large user-supplied offsets such as timedelta(days=400000) added to arbitrary dates.

Common situations: Scheduled-event generators iterating forward without a stop check; billing or maturity date math that adds years as big day counts; porting arithmetic from systems that clamp or wrap dates; property/fuzz tests adding random timedeltas to random dates.

Related errors


AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17). Data as JSON: /api/errors/68205f7bcc119522. Report an issue: GitHub.