Arrow date shifting and humanize with clocks frozen by time-machine: working versions (tested 2026-10-15)
Shift Arrow dates by calendar units, humanize relative times, and pin the clock with time-machine so the output is deterministic offline.
passed6 passed · 0 failed2026-10-15 15:56 UTC- Status
- passed
- Last passed
- 2026-10-15 15:56 UTC
- Tests
- 6 / 6
- Language
- Python
- Runtime
- Python 3.13.16
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt .venv/bin/python -m pytest -q
Python 3.13.16 linux 6.17.0-1022-azure x64 runner: github-actions 38764699834
The code
Exactly the files that passed. Your agent can pull them with get_recipe("arrow-time-machine-shift") (install), or see them on GitHub.
arrow==1.4.0 time-machine==3.5.1 pytest==9.1.1
import arrow
def monthly_renewal(start: arrow.Arrow, months: int = 1) -> arrow.Arrow:
"""Advance a renewal date by calendar months, clamping to month end."""
return start.shift(months=months)
def daily_checkpoint(start: arrow.Arrow, days: int = 1) -> arrow.Arrow:
"""Shift by calendar days; the wall clock is preserved across DST."""
return start.shift(days=days)
def last_seen(ts: arrow.Arrow, now: arrow.Arrow | None = None) -> str:
"""Humanize a timestamp, optionally against an explicit reference clock."""
return ts.humanize(now)
import time
import arrow
import pytest
import time_machine
from scheduling import daily_checkpoint, last_seen, monthly_renewal
@time_machine.travel("2024-05-01T12:00:00+00:00", tick=False)
def test_utcnow_tracks_the_frozen_clock():
assert arrow.utcnow() == arrow.get("2024-05-01T12:00:00+00:00")
assert arrow.utcnow() == arrow.utcnow()
assert arrow.utcnow().int_timestamp == 1714564800
def test_default_tick_advances_unless_disabled():
with time_machine.travel("2024-05-01T12:00:00+00:00"):
first = arrow.utcnow()
time.sleep(0.02)
assert arrow.utcnow() > first
with time_machine.travel("2024-05-01T12:00:00+00:00", tick=False):
first = arrow.utcnow()
time.sleep(0.02)
assert arrow.utcnow() == first
@time_machine.travel("2024-05-01T12:00:00+00:00", tick=False)
def test_humanize_is_deterministic_under_a_frozen_clock():
assert last_seen(arrow.get("2024-05-01T09:00:00+00:00")) == "3 hours ago"
assert last_seen(arrow.get("2024-05-01T15:00:00+00:00")) == "in 3 hours"
def test_humanize_truncates_toward_zero():
now = arrow.get("2024-05-01T12:00:00+00:00")
assert last_seen(now.shift(minutes=-119), now) == "an hour ago"
assert last_seen(now.shift(minutes=-120), now) == "2 hours ago"
assert last_seen(now.shift(hours=-47), now) == "a day ago"
assert last_seen(now.shift(hours=-48), now) == "2 days ago"
def test_shift_clamps_but_replace_raises():
jan31 = arrow.get("2024-01-31T00:00:00+00:00")
assert monthly_renewal(jan31).format("YYYY-MM-DD") == "2024-02-29"
leap = arrow.get("2024-02-29T00:00:00+00:00")
assert leap.shift(years=1).format("YYYY-MM-DD") == "2025-02-28"
with pytest.raises(ValueError):
leap.replace(year=2025)
def test_day_shift_preserves_wall_clock_across_dst():
with time_machine.travel("2024-03-09T17:00:00+00:00", tick=False):
start = arrow.now("US/Eastern")
assert start.format("YYYY-MM-DD HH:mm ZZ") == "2024-03-09 12:00 -05:00"
same_clock = daily_checkpoint(start)
assert same_clock.format("HH:mm ZZ") == "12:00 -04:00"
assert same_clock.timestamp() - start.timestamp() == 23 * 3600
assert start.shift(hours=24).timestamp() == same_clock.timestamp()
[pytest] pythonpath = .
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.
Related stacks
APScheduler job triggers tested deterministically with time-machine
Compute CronTrigger and IntervalTrigger fire times without a running scheduler, and test them offline by freezing the clock with time-machine.
Pendulum DateTime arithmetic and timezone shifts frozen with time-machine
Freeze the clock with time-machine to test Pendulum month-end clamping, DST-safe day additions and timezone shifts fully offline.
Recurring schedules with dateutil rrule and zoneinfo DST handling, frozen with time-machine
Build daily wall-clock schedules in a named timezone with dateutil rrule and zoneinfo, then test DST gaps, overlaps and naive datetimes offline with time-machine.