I propose to add support for a subset of ISO 8601 durations to the datetime module, which already supports parsing/exporting this standard for datetime objects.
In a nutshell, using the standard: "P3Y6M4DT12H30M5S" represents a duration of “three years, six months, four days, twelve hours, thirty minutes, and five seconds”.
Previous discussions on the topic:
- Issue 42094: isoformat() / fromisoformat() for datetime.timedelta - Python tracker
- Issue 41254: Add to/from string methods to datetime.timedelta - Python tracker
As explained in those prior discussions, the main problem of ISO 8601 durations is that they do not all “map cleanly” on timedeltaobjects (which are essentially a fixed number of days/seconds):
"PT1S":timedelta(seconds=1)"PT1M":timedelta(minutes=1)"PT1H":timedelta(hours=1)"P1D":timedelta(days=1)"P1W":timedelta(weeks=1)"P1M": not possible to convert totimedelta, as it is a “relative” concept (*)"P1Y": not possible to convert totimedelta, as it is a “relative” concept (*)
(*) To expand on the “relative” nature of months/years: adding 1 month to different dates “adds” a different amount of time:
datetime(2026, 1, 1)+ 1 month:datetime(2026, 2, 1): 31 daysdatetime(2026, 2, 1)+ 1 month:datetime(2026, 3, 1): 28 days
(*) To manage such relative durations, dateutil relativedelta works well.
As mentioned in the last message of bpo-42094, I suggest to implement only the part of the standard that can be safely represented as timedelta, and defer potential inclusion of a class for relative durations to later/never.
Examples
Recently, pip added support for relative durations for --uploaded-prior-to and ships a simple regex-based parsing of PnD. uv did the same for --exclude-newer, and also only supports days.
I personally have used my own parse_iso_duration variations in multiple projects.
Proposed API
I suggest to mirror datetime.fromisoformat and add timedelta.fromisoformat:
>>> from datetime import timedelta
>>> timedelta.fromisoformat("P2DT10H")
datetime.timedelta(days=2, seconds=36000)
For non-supported durations, we just raise:
>>> timedelta.fromisoformat("P1M") # raises ValueError
We can also mirror datetime.isoformat and add timedelta.isoformat :
>>> td = timedelta(days=12, hours=4)
>>> td.isoformat()
"P12DT4H"
Process
My understanding of the dev guide is that such changes do not require a PEP, but a consensus here, and agreement from the datetime maintainers.
If there is interest in the proposal, I would be happy to work on an implementation.