Wraps freezegun (github.com/spulec/freezegun), the Python time-mocking library: @freeze_time decorator / context manager, freeze_time(...).start() + stop(), tick / move_to / tz_offset, and integration with datetime.now / time.time / time.localtime. Use when testing Python code that calls datetime / time.
80
100%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
freezegun patches datetime.datetime, datetime.date,
time.time, time.gmtime, time.localtime, time.strftime,
and asyncio time across the test scope. Per
github.com/spulec/freezegun.
dst-transition-reference.pip install freezegunfrom freezegun import freeze_time
from datetime import datetime
@freeze_time("2026-05-20T14:30:00")
def test_today_is_may_20():
assert datetime.now().strftime("%Y-%m-%d") == "2026-05-20"with freeze_time("2026-05-20T14:30:00"):
assert datetime.now().strftime("%Y-%m-%d") == "2026-05-20"freezer = freeze_time("2026-05-20T14:30:00")
freezer.start()
try:
# ...
finally:
freezer.stop()@freeze_time("2026-05-20T14:30:00", tick=True)
def test_clock_advances():
t1 = datetime.now()
# ... a few ops later
t2 = datetime.now()
assert t2 > t1tick=True lets real time pass from the frozen start point.
Useful for tests that need duration measurement.
@freeze_time("2026-05-20T14:30:00")
def test_advance_one_day(freezer):
assert datetime.now().day == 20
freezer.move_to("2026-05-21T14:30:00")
assert datetime.now().day == 21Or via freezer.tick(delta=timedelta(hours=24)).
@freeze_time("2026-05-20T14:30:00", tz_offset=-5)
def test_eastern_time():
# datetime.now() returns wall-clock; datetime.utcnow() returns UTC
assert datetime.utcnow().hour == 19 # 14:30 + 5
assert datetime.now().hour == 14DST + zone tests, async support, and CI integration are in references/advanced-scenarios.md.
pytest tests/| Anti-pattern | Why it fails | Fix |
|---|---|---|
freeze_time("2026-05-20") (date only) | freezegun interprets as midnight local; subtle | Use ISO datetime |
time.sleep(...) inside frozen-time block | Sleep is real-time; frozen clock doesn't advance | Use freezer.tick() |
Mock datetime.utcnow separately | Conflicts with freezegun | Let freezegun do both |
| Forget freezer cleanup in fixtures | Cross-test contamination | Use decorator or with |
Test DST without tz_offset or zoneinfo | Result is UTC; misses local behaviour | Combine with zoneinfo |
@freeze_time on a class without decorate_class=True | Methods not patched | Use class decorator explicitly |
| Test third-party C extensions calling system time | freezegun only patches Python-level APIs | Use libfaketime |
clock_gettime() from C sees the real clock. Use
libfaketime-c for those.leap-second-reference.tz_offset doesn't know about DST. For accurate local-zone
behaviour, use datetime.now(tz=zoneinfo.ZoneInfo("...")).datetime before freezing. If a module imports
datetime.now directly at module-load, the unfrozen value may
be cached.dst-transition-reference,
leap-second-reference,
iso-8601-vs-rfc-3339-reference.libfaketime-c,
sinon-fake-timers-js,
jest-fake-timers,
timecop-ruby,
mockclock-jvm.timezone-test-matrix-builder.