isoduration

raw JSON →
20.11.0 verified Tue May 12 auth: no python install: verified quickstart: verified maintenance

isoduration is a Python library for working with ISO 8601 durations (e.g., 'P3Y6M4DT12H30M5S'). It provides functionality for parsing duration strings, formatting durations, and performing arithmetic operations with Python's `datetime` objects. The library is currently at version 20.11.0, released in 2020, and appears to be in maintenance mode with no recent major releases, though minor updates or repackaging may occur.

pip install isoduration
error ValueError: Invalid ISO 8601 duration string: 'P3X'
cause The input string provided to `parse_duration()` does not strictly conform to the ISO 8601 duration format, often due to typos, missing 'P' or 'T' designators, or incorrect units.
fix
Ensure the duration string adheres to the ISO 8601 format (e.g., 'P3Y6M4DT12H30M5S', 'PT1H30M', 'P1W'). For instance, 'P3X' should be 'P3D' for three days or 'PT3S' for three seconds.
error AttributeError: module 'isoduration' has no attribute 'DurationParsingException'
cause This error occurs when code attempts to reference `isoduration.DurationParsingException`, which is not an exposed exception in the `isoduration` library (bolsote/isoduration). It might be an internal exception type, or a class from a different, related library like `isodate` or `iso8601`.
fix
Identify where DurationParsingException is being referenced in your code or a dependent library. Replace it with a more general exception like ValueError, or specifically catch iso8601.iso8601.ParseError if that's the underlying exception being raised and you have iso8601 installed as a dependency. If it's a dependency causing the issue, check for compatibility or try reinstalling the packages.
error AttributeError: 'Duration' object has no attribute 'total_seconds'
cause The `isoduration` library returns its own `Duration` object, not a standard `datetime.timedelta`, especially when the duration includes years or months. The `total_seconds()` method is exclusive to `datetime.timedelta` objects.
fix
To get total seconds, you need to convert the Duration object to a timedelta first using duration.to_timedelta(). Note that to_timedelta() will raise a ValueError if the duration contains years or months, as these cannot be unambiguously converted to seconds without a specific context date. For durations with years/months, access the years, months, days, hours, minutes, seconds attributes from duration.date and duration.time directly.
gotcha ISO 8601 durations that include years or months represent variable-length periods (e.g., '1 month' can be 28, 29, 30, or 31 days). Python's `datetime.timedelta` is designed for fixed-length durations. `isoduration` addresses this by returning its own `Duration` object for such cases, which correctly handles arithmetic with `datetime` objects.
fix Be aware that `parse_duration` may return a `Duration` object, not always a `timedelta`. The `Duration` object correctly implements addition/subtraction with `datetime` objects.
gotcha The library had its initial and only PyPI release (20.11.0) in November 2020. While the GitHub repository shows some minor activity in 2021, there haven't been subsequent PyPI releases, suggesting limited active development or a stable, feature-complete state.
fix Consider its maintenance status when planning for long-term projects or needing new features/bug fixes. It appears stable for its current scope.
gotcha The `Duration` object's internal components (years, months, days, etc.) are stored as `Decimal` types for precision. Direct comparison or conversion to `datetime.timedelta` (especially for years/months) needs careful handling due to the inherent ambiguity of these units.
fix Access components via `duration.date.years`, `duration.time.hours`, etc. Perform arithmetic with `datetime` objects for correct temporal calculations. Avoid direct `timedelta` conversion if the `Duration` contains years or months, as `timedelta` cannot represent these precisely.
python os / libc status wheel install import disk
3.10 alpine (musl) wheel - 0.10s 22.2M
3.10 alpine (musl) - - 0.11s 22.2M
3.10 slim (glibc) wheel 1.8s 0.07s 23M
3.10 slim (glibc) - - 0.07s 23M
3.11 alpine (musl) wheel - 0.16s 24.2M
3.11 alpine (musl) - - 0.18s 24.2M
3.11 slim (glibc) wheel 2.0s 0.14s 25M
3.11 slim (glibc) - - 0.13s 25M
3.12 alpine (musl) wheel - 0.14s 16.1M
3.12 alpine (musl) - - 0.16s 16.1M
3.12 slim (glibc) wheel 1.8s 0.14s 17M
3.12 slim (glibc) - - 0.14s 17M
3.13 alpine (musl) wheel - 0.14s 15.8M
3.13 alpine (musl) - - 0.14s 15.7M
3.13 slim (glibc) wheel 1.8s 0.14s 16M
3.13 slim (glibc) - - 0.15s 16M
3.9 alpine (musl) wheel - 0.09s 21.7M
3.9 alpine (musl) - - 0.10s 21.7M
3.9 slim (glibc) wheel 2.1s 0.09s 22M
3.9 slim (glibc) - - 0.08s 22M

This quickstart demonstrates parsing an ISO 8601 duration string into a `Duration` object, accessing its components, and performing arithmetic by adding it to a `datetime` object.

from datetime import datetime
from isoduration import parse_duration

# Parse an ISO 8601 duration string
duration_str = "P3Y6M4DT12H30M5S"
duration = parse_duration(duration_str)

print(f"Parsed duration: {duration}")
print(f"Years: {duration.date.years}, Months: {duration.date.months}")
print(f"Hours: {duration.time.hours}, Seconds: {duration.time.seconds}")

# Add the duration to a datetime object
start_time = datetime(2023, 1, 1, 10, 0, 0)
end_time = start_time + duration
print(f"Start time: {start_time}")
print(f"End time after adding duration: {end_time}")

# Negate a duration
negative_duration = -duration
print(f"Negative duration: {negative_duration}")