Recent Updates to time-machine

This is my time machine.

time-machine is my library for mocking the current date and time in Python tests. It’s now over a year old, and I just released its version 2.2.0, so I thought it would be nice to summarize recent changes.

(If you’re unfamiliar with time-machine, see my how to guide and the introductory post.)

Major version API changes

The first release in January saw a major version bump to 2.0.0. This was because the API changed a little, including removal of an argument.

freezegun, the library that inspired time-machine, supports a tz_offset argument to specify the destination timezone. time-machine originally copied this, but with not quite the same semantics. Thinking a little about it, I realized that trying to specifying a timezone through a single offset is a flawed concept, since timezones change their offset, through daylight savings or governmental decrees.

Instead of supporting tz_offset, time-machine now supports destination timezones when passed a datetime with a zoneinfo.ZoneInfo instance attached. zoneinfo is the Python 3.9 standard library module for specifying timezones, for replacing third party libraries such as pytz (the fastest footgun in the west). On older Python versions we can install it from the backports.zoneinfo package.

The other API changes included moving all internal calculations to nanoseconds, to avoid any loss of precision from using floats, and improving the semantics of move_to().


time-machine releases now have more binary wheel formats: Windows, Linux aarch64 (ARM), and macOS universal2 (combined Intel/Apple Silicon). These wheels make it faster and easier to install time-machine on those platforms, as users no longer need to compile from source. Adding support for these formats was really straightforward - the credit all goes to cibuildwheel here, and its excellent documentation with many examples.

multi-phase initialization

The C module in time-machine now uses multi-phase initialization as per PEP 489. This change is probably not visible to any users, but it provides a level of future-proofing.

CPython is changing to support subinterpreters, which allows multiple Python interpreters to run in one process, allowing a new model of parallelization. Moving time-machine to multi-phase initialization means it will be able to work when using subinterpreters.

For more information on subinterpreters, see this summary of the recent Language Summit talk by Victor Stinner and Dong-hee Na, the developers working on it.

type hints

time-machine now has type hints! This makes it my first open source project to ship type hints, which is exciting.

I’ve written a number of type hints posts recently, so it was nice to apply this knowledge in open source. Working out time-machine’s type hints even inspired yesterday’s post on context managers.

Now that I’m familiar with the process and adding a py.typed file as per PEP 561, I hope to add type hints to more of my projects.


time-machine: it’s about time!


Make your development more pleasant with Boost Your Django DX.

Subscribe via RSS, Twitter, Mastodon, or email:

One summary email a week, no spam, I pinky promise.

Related posts: