ProvenPin Install

Pendulum DateTime arithmetic and timezone shifts frozen with time-machine: working versions (tested 2026-10-15)

Freeze the clock with time-machine to test Pendulum month-end clamping, DST-safe day additions and timezone shifts fully offline.

passed6 passed · 0 failed2026-10-15 16:03 UTC
Status
passed
Last passed
2026-10-15 16:03 UTC
Tests
6 / 6
Language
Python
Runtime
Python 3.13.16
pinned versions3
pendulum@3.3.0time-machine@3.5.1pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
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("pendulum-time-machine-freeze") (install), or see them on GitHub.

requirements.txt
pendulum==3.3.0
time-machine==3.5.1
pytest==9.1.1
clock.py
import pendulum
from pendulum import DateTime


def days_until(target: DateTime) -> int:
    """Whole days between now (in target's timezone) and target."""
    return (target - pendulum.now(target.tz)).days


def to_tz(dt: DateTime, tz: str) -> DateTime:
    """The same instant, expressed in another timezone."""
    return dt.in_timezone(tz)


def add_months(anchor: DateTime, months: int = 1) -> DateTime:
    """Add calendar months, clamping to the last valid day."""
    return anchor.add(months=months)
tests/test_clock.py
import datetime as dt
import time

import pendulum
import time_machine

from clock import add_months, days_until, to_tz


def test_freeze_pins_pendulum_now():
    frozen = pendulum.datetime(2024, 1, 15, 12, 0, tz="UTC")
    with time_machine.travel(frozen, tick=False):
        assert pendulum.now("UTC") == frozen
        assert days_until(frozen.add(days=10)) == 10
        assert days_until(frozen) == 0


def test_naive_input_kind_changes_meaning():
    naive = dt.datetime(2024, 1, 15, 12, 0)
    with time_machine.travel(naive, tick=False):
        assert dt.datetime.now(dt.timezone.utc).replace(tzinfo=None) == naive
    with time_machine.travel("2024-01-15 12:00:00", tick=False):
        assert pendulum.now().naive() == naive


def test_tick_flag_controls_flow():
    with time_machine.travel("2024-01-15 12:00:00", tick=False):
        assert pendulum.now("UTC") == pendulum.now("UTC")
    with time_machine.travel("2024-01-15 12:00:00", tick=True):
        first = pendulum.now("UTC")
        time.sleep(0.01)
        assert pendulum.now("UTC") > first


def test_add_days_keeps_wall_clock_across_dst():
    frozen = pendulum.datetime(2021, 3, 13, 12, 0, tz="America/New_York")
    with time_machine.travel(frozen, tick=False):
        now = pendulum.now("America/New_York")
        assert now.add(days=1).hour == 12
        assert now.add(days=1).offset_hours == -4.0
        assert now.add(hours=24).hour == 13


def test_add_months_clamps_to_month_end():
    with time_machine.travel(pendulum.datetime(2024, 1, 31, tz="UTC"), tick=False):
        assert add_months(pendulum.now("UTC")) == pendulum.datetime(2024, 2, 29, tz="UTC")
        assert add_months(pendulum.now("UTC"), -1) == pendulum.datetime(2023, 12, 31, tz="UTC")


def test_in_timezone_keeps_instant():
    frozen = pendulum.datetime(2021, 8, 1, 12, 0, tz="Europe/Paris")
    with time_machine.travel(frozen, tick=False):
        now = pendulum.now("Europe/Paris")
        ny = to_tz(now, "America/New_York")
        assert ny.hour == 6
        assert ny == now
        assert ny.timestamp() == now.timestamp()
pytest.ini
[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.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.