{"record":{"id":"5e7b055f34604a5d","repo":"pytest-dev/pytest","slug":"pytest-approx-requires-an-explicit-tolerance-for","errorCode":null,"errorMessage":"pytest.approx() requires an explicit tolerance for datetime/timedelta comparisons: e.g. approx(expected, abs=timedelta(seconds=1)) or approx(expected, rel=0.01)","messagePattern":"pytest\\.approx\\(\\) requires an explicit tolerance for datetime/timedelta comparisons: e\\.g\\. approx\\(expected, abs=timedelta\\(seconds=1\\)\\) or approx\\(expected, rel=0\\.01\\)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/approx.py","lineNumber":657,"sourceCode":"        self,\n        expected: datetime | timedelta,\n        rel: float | Decimal | timedelta | None,\n        abs: float | Decimal | timedelta | None,\n        nan_ok: bool,\n    ) -> None:\n        __tracebackhide__ = True\n        if isinstance(expected, datetime) and rel is not None:\n            raise TypeError(\n                \"pytest.approx() does not support relative tolerance for \"\n                \"datetime comparisons. Use abs=timedelta(...) instead.\"\n            )\n        if nan_ok:\n            raise TypeError(\n                \"pytest.approx() does not support nan_ok for \"\n                \"datetime/timedelta comparisons.\"\n            )\n        if abs is None and rel is None:\n            raise TypeError(\n                \"pytest.approx() requires an explicit tolerance for \"\n                \"datetime/timedelta comparisons: \"\n                \"e.g. approx(expected, abs=timedelta(seconds=1)) \"\n                \"or approx(expected, rel=0.01)\"\n            )\n        if abs is not None and not isinstance(abs, timedelta):\n            raise TypeError(\n                f\"absolute tolerance for datetime/timedelta must be a \"\n                f\"timedelta, got {type(abs).__name__}\"\n            )\n        if abs is not None and abs < timedelta(0):\n            raise ValueError(f\"absolute tolerance can't be negative: {abs}\")\n        if rel is not None:\n            if not isinstance(rel, (int, float)):\n                raise TypeError(\n                    f\"relative tolerance for timedelta must be a \"\n                    f\"number, got {type(rel).__name__}\"\n                )","sourceCodeStart":639,"sourceCodeEnd":675,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/approx.py#L639-L675","documentation":"ApproxTimedelta.__init__ requires at least one explicit tolerance (abs or rel) for datetime/timedelta comparisons, unlike scalars which default to rel=1e-6/abs=1e-12. datetime/timedelta have no sensible default tolerance window (1e-6 of what unit?), so pytest refuses to guess. The error suggests both valid forms. The check fires when both abs and rel are None.","triggerScenarios":"Calling approx(datetime.now()); approx(timedelta(seconds=5)); approx(dt) with no keyword args. Triggered at ApproxTimedelta.__init__ (src/_pytest/approx.py:656-662).","commonSituations":"Migrating a numeric approx() call to datetime without adding tolerance; assuming a default tolerance exists; refactoring a test to use datetime while keeping the old bare approx() call.","solutions":["For datetime, pass an absolute timedelta: `approx(dt, abs=timedelta(seconds=1))`.","For timedelta, pass rel (a number, fraction of the duration) or abs: `approx(td, rel=0.01)` or `approx(td, abs=timedelta(milliseconds=10))`.","Centralize the chosen tolerance in a fixture/constant to keep datetime assertions consistent."],"exampleFix":"# before\nassert actual_dt == approx(expected_dt)\n# after\nassert actual_dt == approx(expected_dt, abs=timedelta(seconds=1))","handlingStrategy":"validation","validationCode":"from datetime import datetime, timedelta\ndef ensure_datetime_tolerance(expected, rel, abs):\n    if isinstance(expected, (datetime, timedelta)) and rel is None and abs is None:\n        if isinstance(expected, datetime):\n            return {'abs': timedelta(seconds=1)}\n        return {'rel': 0.01}\n    return {'rel': rel, 'abs': abs}\n# usage\nassert actual == approx(expected, **ensure_datetime_tolerance(expected, rel, abs))","typeGuard":"from datetime import datetime, timedelta\ndef needs_explicit_tolerance(expected) -> bool:\n    return isinstance(expected, (datetime, timedelta))","tryCatchPattern":null,"preventionTips":["Always pass abs=timedelta(...) (or rel for timedelta) for time comparisons.","Centralize datetime tolerance in a fixture/constant.","Add a helper that injects a default tolerance for datetime/timedelta."],"tags":["pytest","approx","datetime","tolerance","required-argument"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}