Skip to content

Time & scheduling

Vayu leans on Python's zoneinfo and adds timezone-aware helpers plus a TimeWindow type with interval algebra.

The TZ convention

At import time, vayu.time_utils resolves a module-level TZ:

  1. os.environ["TZ"] as an IANA zone (e.g. Asia/Kolkata), if set.
  2. Otherwise, the system's local timezone.

time_now(), local_datetime(), and from_timestamp() default to this zone. Set TZ=UTC for production services unless you need a specific reporting timezone.

Building datetimes

from vayu.time_utils import time_now, utc_datetime, local_datetime, from_timestamp, from_z_string

now = time_now()                        # tz-aware, seconds precision
now_ms = time_now(with_ms=True)         # keep microseconds
now_utc = time_now(local=False)         # force UTC

t1 = utc_datetime(2026, 4, 22, 12, 30)                 # always UTC
t2 = local_datetime(2026, 4, 22, 18, 0)                # defaults to TZ
t3 = from_timestamp(1_713_000_000)                     # seconds
t4 = from_timestamp(1_713_000_000_123)                 # detects ms (> 1e12)
t5 = from_z_string("2026-04-22T12:30:00Z")             # ISO-8601 with Z

TimeWindow

TimeWindow is a dataclass that extends Interval with datetime-aware constructors:

from vayu import TimeWindow
from datetime import timedelta

# Last 6 hours
w = TimeWindow.behind(hours=6)

# Next 30 minutes
w = TimeWindow.ahead(minutes=30)

# 5 minutes on each side of `t`
w = TimeWindow.around(t=some_event_time, minutes=5)

# From a calendar day (UTC unless you pass tz=)
w = TimeWindow.from_date(2026, 4, 22)

# From a pair of timestamps
w = TimeWindow.from_timestamp(1_713_000_000, 1_713_003_600)

print(w.duration)   # timedelta
print(w.start_ms)   # int (ms)
print(w.end_ms)     # int (ms)

Because TimeWindow inherits from Interval, you get:

a = TimeWindow.behind(hours=6)
b = TimeWindow.ahead(hours=2)

a.intersects(b)          # bool
overlap = a & b          # intersection
combined = a | b         # union (requires no gap; see Interval guide)
some_time in a           # containment

timeit

Quick-and-dirty print-style timer:

from vayu.time_utils import timeit

@timeit
def slow():
    ...
# prints: `slow` took: 1.234s

For library-level instrumentation (no prints), use your own logging.

to_human_readable_time

from vayu.time_utils import to_human_readable_time
from datetime import timedelta

to_human_readable_time(3661)                           # "1h1m1s"
to_human_readable_time(timedelta(hours=2, minutes=5))  # "2h5m"
to_human_readable_time(0)                              # "0s"
to_human_readable_time(-1)                             # "invalid-time"

See also