Quick start#

A five-minute tour of isoperiod. Each section links to the user guide page that covers it properly.

Build a period#

Either from an ISO 8601 duration string, or from a named unit:

pt15m = Period.of("PT15M")
p1d = Period.of_days(1)
p1m = Period.of_months(1)

Periods that describe the same grid are equal, however you spell them:

assert Period.of_hours(24) == Period.of_days(1)  # True
assert Period.of_months(12) == Period.of_years(1)  # True

See Creating periods for every factory, all three string formats, and error handling.

Find the interval a timestamp falls in#

ordinal() gives the number of the interval containing a datetime; datetime() turns that ordinal number back into the interval’s first instant.

Together they floor a timestamp onto the grid:

pt15m = Period.of("PT15M")
reading = datetime(2024, 3, 15, 9, 47, 30)

n = pt15m.ordinal(reading)
print(pt15m.datetime(n))  # this interval
print(pt15m.datetime(n + 1))  # the next one
2024-03-15 09:45:00
2024-03-15 10:00:00

When only the start boundary is wanted, floor() performs that in one call:

print(pt15m.floor(reading))
2024-03-15 09:45:00

Additionally, interval() provides a way to get both the start and end boundary of a period in one call:

start, end = pt15m.interval(reading)
print(start, "->", end)
2024-03-15 09:45:00 -> 2024-03-15 10:00:00

See Intervals and ordinals for stepping along the timeline, grouping by interval, and generating boundaries.

Check that data sits on the grid#

is_aligned() answers “is this timestamp exactly on a boundary?”:

Period.of_hours(1).is_aligned(datetime(2024, 3, 15, 9, 0))  # True
Period.of_hours(1).is_aligned(datetime(2024, 3, 15, 9, 47))  # False

Use an offset for a non-standard boundary#

An offset moves every boundary of the period by a fixed amount. For example, we can express a hydrological day, which runs from 09:00 to 09:00, using an offset:

water_day = Period.of_days(1).with_hour_offset(9)

# 07:30 belongs to the water day that began at 09:00 the previous day.
print(water_day.floor(datetime(2024, 3, 15, 7, 30)))
2024-03-14 09:00:00

See Offsets and origins for the full set of offset builders, the water year, and pinning a grid to an origin.

Compare two periods#

The count() method gives a way to explore how one period nests inside another:

pt15m = Period.of("PT15M")
pt1h = Period.of_hours(1)
p1d = Period.of_days(1)

# How many of one period fits inside another
print(pt15m.count(pt1h))
print(pt15m.count(p1d))
4
96

See Comparing periods for more detail, include special cases, how offsets work with comparisons, and epoch agnosticism.

Where next#

Page

Covers

Concepts

The ideas behind the API: intervals, ordinals, offsets, origins, alignment

Creating periods

Every way to build a period, and what each string format means

Intervals and ordinals

Flooring, stepping, grouping, alignment, the ends of the timeline

Offsets and origins

Offsets and origins, worked hydrological examples, stripping them off again

Comparing periods

Equality, ordering, counting, containment, epoch agnosticism

Time zones

What a period’s tzinfo does, and what it deliberately does not

Interoperability

String forms, timedelta conversion, Polars duration strings

Period

The full Period reference