time-machine: travel through time in Python tests
Travel through time in your tests.
At a glance
- What is it?
- time-machine is a Python library that lets tests run as if at a chosen date and time, using a decorator or context manager. It ships a C extension and requires Python 3.11 or newer.
- Who is it for?
- Adopt time-machine if you write Python 3.11+ tests that depend on the current time and want a simple decorator. Skip it if you need PyPy support or run on older Python versions.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What time-machine solves for Python tests
time-machine addresses the problem of testing code that depends on the current date or time. It lets a test run as if at a chosen instant, so assertions about today's date or a time-based calculation become deterministic. The project's tagline is travel through time in your tests.
The intended user is a Python developer writing tests that touch datetime or time. The library is licensed under MIT and is classified as production stable. It is typed and supports pytest through an entry point. The homepage is time-machine.readthedocs.io.
How time-machine moves time in a test
The README gives a quick example using a decorator. The time_machine.travel decorator takes a datetime and moves the clock for the duration of the decorated test.
import datetime as dt
from zoneinfo import ZoneInfo
import time_machine
hill_valley_tz = ZoneInfo("America/Los_Angeles")
@time_machine.travel(dt.datetime(1985, 10, 26, 1, 24, tzinfo=hill_valley_tz))
def test_delorean():
assert dt.date.today().isoformat() == "1985-10-26"The example shows that dt.date.today reflects the traveled time rather than the real clock. The README does not describe the implementation mechanism in detail, but the repository layout reveals that the library ships a C extension named _time_machine, built from src/_time_machine.c, with compile flags such as -fno-omit-frame-pointer. That C layer is how the library intercepts time calls, though the README itself does not explain the interception strategy.
Installing time-machine
The project is distributed on PyPI as time-machine, version 3.5.1 in pyproject.toml. The build system uses setuptools with a C extension, so installation compiles the extension unless a wheel is available. The README does not give install commands, but the package metadata and repository layout indicate standard Python packaging.
The project requires Python 3.11 or newer, with classifiers for 3.11 through 3.15. PyPy is explicitly not supported, and setup.py raises a RuntimeError when running under PyPy. Optional dependencies are tokenize-rt for the CLI extra and python-dateutil 2.8.2 or newer for the dateutil extra. Development dependencies include hypothesis, pytest 9 or newer, pytest-randomly, coverage, freezegun, and python-dateutil.
Entry points and optional features
The pyproject.toml declares a pytest11 entry point, so time_machine is automatically available as a pytest plugin when installed. Optional extras are cli, which pulls in tokenize-rt, and dateutil, which pulls in python-dateutil. The CLI extra suggests the package provides a command-line helper, but the README does not document it.
The project uses a uv lockfile and tox for testing, and cibuildwheel for building wheels. The documentation is built with Sphinx and the furo theme. Coverage is reported at 100 percent in the README badge.
Limitations and when time-machine is the wrong tool
time-machine is the wrong tool if you need PyPy support, because setup.py explicitly rejects PyPy. It is also the wrong tool if you are on Python older than 3.11, since requires-python is set to >=3.11. The C extension means installation depends on a working compiler when no wheel is available, which can be a hurdle on unusual platforms.
The README does not document the full API, rollback, or behavior for timezones beyond the example. The documentation lives at readthedocs.io, and the README points there rather than embedding reference material. The repository has no GitHub releases, so version tracking relies on PyPI and the changelog.
Alternatives and how the approach differs
The README does not name a competing library, but the test dependencies include freezegun.
The C extension adds a build dependency and excludes PyPy.
Documentation and project layout
The README points to the full documentation at time-machine.readthedocs.io rather than embedding the API reference. The repository includes a docs directory, a tests directory, a src directory, a tox.ini, a .readthedocs.yaml, and a MANIFEST.in. The CHANGELOG.rst and HISTORY.rst files track release history, which matters because the repository has no GitHub releases.
The project uses pre-commit, clang-format, editorconfig, and typos checks, as shown by the corresponding configuration files. The .github directory holds CI workflows. These signals suggest a maintained codebase with automated quality checks, though the README itself does not describe the contribution process.
Maintenance, licensing and upgrade cost
The repository is not archived and the last push was on 2026-10-05. The license is MIT. The version in pyproject.toml is 3.5.1. There are no GitHub releases, so version history is tracked through PyPI and the changelog.
Upgrade cost is shaped by the supported Python range and the C extension. Dropping older Python versions or changing the C build flags affects wheel availability. The project uses cibuildwheel for multi-platform wheels, so a maintainer must keep that configuration current. The MIT license allows use, modification, and redistribution, including in commercial products, but this is not legal advice and a team should have counsel review its obligations.
Editorial conclusion
Adopt time-machine if you write Python 3.11+ tests that depend on the current time and want a simple decorator. Skip it if you need PyPy support or run on older Python versions. Verify the Python version and the C extension build on your platform before adding it to CI.
Frequently asked questions
How do I use time-machine in a test?
Decorate the test with time_machine.travel and pass the datetime you want the test to run at.
Does time-machine support PyPy?
No, setup.py raises a RuntimeError when running under PyPy.
What Python versions does time-machine require?
It requires Python 3.11 or newer.
Is time-machine a pytest plugin?
Yes, it declares a pytest11 entry point so it is available automatically when installed.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/adamchainz-time-machine)Was this useful?