pytest-dev/pytest · error · TypeError

pytest.approx() does not support relative tolerance for date

Error message

pytest.approx() does not support relative tolerance for datetime comparisons. Use abs=timedelta(...) instead.

What it means

ApproxTimedelta.__init__ rejects relative tolerance for datetime (not timedelta) comparisons because a relative fraction of an absolute timestamp is not meaningful (and is timezone/epoch dependent). Use an absolute timedelta tolerance instead.

Source

Thrown at src/_pytest/approx.py:647

class ApproxTimedelta(Approx[datetime | timedelta]):
    """Perform approximate comparisons where the expected value is a
    datetime or timedelta.

    Requires an explicit tolerance as a timedelta for abs, or a float for rel.
    Relative tolerance is not supported for datetime comparisons.
    """

    def __init__(
        self,
        expected: datetime | timedelta,
        rel: float | Decimal | timedelta | None,
        abs: float | Decimal | timedelta | None,
        nan_ok: bool,
    ) -> None:
        __tracebackhide__ = True
        if isinstance(expected, datetime) and rel is not None:
            raise TypeError(
                "pytest.approx() does not support relative tolerance for "
                "datetime comparisons. Use abs=timedelta(...) instead."
            )
        if nan_ok:
            raise TypeError(
                "pytest.approx() does not support nan_ok for "
                "datetime/timedelta comparisons."
            )
        if abs is None and rel is None:
            raise TypeError(
                "pytest.approx() requires an explicit tolerance for "
                "datetime/timedelta comparisons: "
                "e.g. approx(expected, abs=timedelta(seconds=1)) "
                "or approx(expected, rel=0.01)"
            )
        if abs is not None and not isinstance(abs, timedelta):
            raise TypeError(
                f"absolute tolerance for datetime/timedelta must be a "

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Switch to an absolute tolerance: approx(dt, abs=timedelta(seconds=1)).
  2. Pick the timedelta magnitude that matches the precision you actually need (microseconds, seconds, days).
  3. If you truly need a proportional tolerance, convert to timedelta first and compare timedeltas.

Example fix

// before
assert got == approx(datetime(2024,1,1,12,0,0), rel=0.01)
// after
from datetime import timedelta
assert got == approx(datetime(2024,1,1,12,0,0), abs=timedelta(seconds=1))
Defensive patterns

Strategy: type-guard

Validate before calling

from datetime import datetime, timedelta

def approx_dt(value, abs_seconds=None):
    if isinstance(value, datetime):
        if abs_seconds is None:
            raise ValueError('datetime approx requires abs_seconds')
        return pytest.approx(value, abs=timedelta(seconds=abs_seconds))
    return pytest.approx(value)

Type guard

from datetime import datetime, timedelta

def is_datetime(v) -> bool:
    return isinstance(v, datetime)

Prevention

When it happens

Trigger: Call pytest.approx(some_datetime, rel=0.01) — i.e. the expected value is a datetime instance and rel is not None.

Common situations: Reusing a numeric-style approx(expected, rel=0.05) call for datetime values; refactoring a timedelta test to use datetime without updating the tolerance; copy-pasting tolerance kwargs between tests.

Related errors


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/326a947ddbbead2b.json. Report an issue: GitHub.