Working with deltas

This page gives a conceptual overview of the delta types in whenever. For the full API reference, see Delta types.

Three types for three use cases

whenever provides three delta types because durations have fundamentally different arithmetic rules depending on the units involved (see the FAQ for the reasoning):

Type

Units

When to use

TimeDelta

hours, minutes, seconds, …

Measuring exact elapsed time

ItemizedDateDelta

years, months, weeks, days

Calendar arithmetic (e.g. “3 months from now”)

ItemizedDelta

all of the above

Display, ISO 8601 round-tripping, mixed durations

Most of the time you won’t create delta objects directly—you’ll use add(), subtract(), since(), and until() on datetime and date objects. But deltas become useful when you need to reuse a duration, pass it around, or inspect its components.

Normalized vs. itemized

TimeDelta normalizes its components: 90 minutes automatically becomes 1 hour 30 minutes. This makes comparison and arithmetic straightforward.

ItemizedDateDelta and ItemizedDelta keep their components itemized: 1 month stays 1 month, not 30 days. This is essential because calendar units have variable lengths—a month can be 28, 29, 30, or 31 days depending on when you start.

>>> TimeDelta(hours=1, minutes=90)
TimeDelta("PT2h30m")          # normalized: 2 hours 30 minutes
>>> ItemizedDelta(hours=1, minutes=90)
ItemizedDelta("PT1h90m")      # itemized: components kept as-is

Calendar units need context

Because 1 month has a variable number of days, operations that convert between calendar and exact units require a reference date (the relative_to parameter).

>>> d = ItemizedDateDelta(months=1)
>>> d.total("days", relative_to=Date(2024, 1, 15))   # January → February
31
>>> d.total("days", relative_to=Date(2024, 2, 15))   # February → March
29   # 2024 is a leap year

The same applies to in_units(), add(), and subtract() when calendar units are involved.

Balancing into different units

“Balancing” means redistributing a delta’s value across a new set of units. Use in_units():

>>> td = TimeDelta(minutes=150)
>>> td.in_units(["hours", "minutes"]).values()
(2, 30)

For itemized deltas with calendar units, balancing requires a reference date:

>>> d = ItemizedDateDelta(days=400)
>>> d.in_units(["years", "months", "days"], relative_to=Date(2024, 1, 1)).values()
(1, 1, 3)

Sign

All deltas carry a single sign that applies to every component. There are no mixed-sign deltas:

>>> -ItemizedDateDelta(years=1, months=6)
ItemizedDateDelta("-P1y6m")

See Sign for more details.

Next steps

  • Arithmetic — adding and subtracting time from datetimes

  • Delta types — full API reference for all three delta types