pytest-dev/pytest · error · TypeError

pytest.approx() requires an explicit tolerance for datetime/

Error message

pytest.approx() requires an explicit tolerance for datetime/timedelta comparisons: e.g. approx(expected, abs=timedelta(seconds=1)) or approx(expected, rel=0.01)

What it means

ApproxTimedelta.__init__ requires an explicit tolerance because there is no sensible default for datetime/timedelta comparisons (unlike the 1e-12 default for floats). You must pass either abs=timedelta(...) or rel=<float>.

Source

Thrown at src/_pytest/approx.py:657

        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 "
                f"timedelta, got {type(abs).__name__}"
            )
        if abs is not None and abs < timedelta(0):
            raise ValueError(f"absolute tolerance can't be negative: {abs}")
        if rel is not None:
            if not isinstance(rel, (int, float)):
                raise TypeError(
                    f"relative tolerance for timedelta must be a "
                    f"number, got {type(rel).__name__}"
                )

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Pass an absolute tolerance: approx(dt, abs=timedelta(seconds=1)).
  2. Or, for timedelta expected values, pass a relative tolerance: approx(td, rel=0.01).
  3. Choose a tolerance magnitude that reflects the precision you actually care about.

Example fix

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

Strategy: validation

Validate before calling

from datetime import datetime, timedelta

def approx_dt(value, *, abs_seconds=1.0):
    if isinstance(value, (datetime, timedelta)):
        return pytest.approx(value, abs=timedelta(seconds=abs_seconds))
    return pytest.approx(value)

Type guard

from datetime import datetime, timedelta

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

Prevention

When it happens

Trigger: Call pytest.approx(some_datetime) or pytest.approx(some_timedelta) with neither abs nor rel supplied.

Common situations: Assuming approx() has the same default-tolerance behavior for datetimes as for floats; quick one-liner tests written without reading the datetime docs.

Related errors


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