Travel through time in your tests.
npx @tessl/cli install tessl/pypi-time-machine@2.19.0A Python library for mocking time in tests, enabling developers to travel through time to create deterministic tests for time-sensitive code. Time Machine patches Python's time and datetime functions at the C level for high performance and comprehensive coverage.
pip install time-machineimport time_machineCommon usage pattern:
from time_machine import travelimport time_machine
from datetime import datetime, timezone
# Context manager usage
with time_machine.travel(datetime(2023, 1, 1, 12, 0, 0, tzinfo=timezone.utc)):
print(datetime.now()) # Prints 2023-01-01 12:00:00
# Decorator usage
@time_machine.travel("2023-01-01 12:00 UTC")
def test_something():
assert datetime.now().year == 2023
# Moving through time during travel
with time_machine.travel(0) as traveller:
print(datetime.now()) # 1970-01-01 00:00:00
traveller.shift(3600) # Add 1 hour
print(datetime.now()) # 1970-01-01 01:00:00
traveller.move_to("2023-01-01")
print(datetime.now()) # 2023-01-01 00:00:00Time Machine operates by patching Python's time-related functions at the C extension level:
_time_machine.c provides low-level patching of time functionsThe patching system ensures that all time-related functions (time.time(), datetime.now(), etc.) return consistent mocked values during time travel, with support for both static time (tick=False) and advancing time (tick=True).
Primary time travel functionality using the travel class as a context manager or decorator. Supports various destination formats including timestamps, datetime objects, ISO strings, and relative time deltas.
class travel:
def __init__(self, destination: DestinationType, *, tick: bool = True): ...
def start(self) -> Coordinates: ...
def stop(self) -> None: ...
def __enter__(self) -> Coordinates: ...
def __exit__(self, exc_type, exc_val, exc_tb) -> None: ...
async def __aenter__(self) -> Coordinates: ...
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None: ...class Coordinates:
def time(self) -> float: ...
def time_ns(self) -> int: ...
def shift(self, delta: dt.timedelta | int | float) -> None: ...
def move_to(self, destination: DestinationType, tick: bool | None = None) -> None: ...Seamless integration with pytest through fixtures, markers, and automatic test discovery. Provides both imperative and declarative approaches to time travel in tests.
class TimeMachineFixture:
def move_to(self, destination: DestinationType, tick: bool | None = None) -> None: ...
def shift(self, delta: dt.timedelta | int | float) -> None: ...
def stop(self) -> None: ...@pytest.fixture(name="time_machine")
def time_machine_fixture(request: pytest.FixtureRequest) -> Generator[TimeMachineFixture, None, None]: ...Access to real time functions during time travel for testing time-dependent operations that need actual system time, such as performance measurements or external API calls.
class _EscapeHatch:
def is_travelling(self) -> bool: ...
time: _EscapeHatchTime
datetime: _EscapeHatchDatetimeescape_hatch: _EscapeHatchCommand-line tool for migrating test code from freezegun to time-machine, automatically rewriting imports and function calls.
def main(argv: Sequence[str] | None = None) -> int: ...
def migrate_files(files: list[str]) -> int: ...
def migrate_file(filename: str) -> int: ...DestinationBaseType = Union[
int, # Unix timestamp
float, # Unix timestamp with fractional seconds
dt.datetime, # Datetime object (timezone-aware recommended)
dt.timedelta, # Relative time from current time
dt.date, # Date (converted to midnight UTC)
str, # ISO 8601 datetime string
]
DestinationType = Union[
DestinationBaseType,
Callable[[], DestinationBaseType], # Function returning destination
Generator[DestinationBaseType, None, None], # Generator yielding destinations
]
_TimeTuple = tuple[int, int, int, int, int, int, int, int, int] # Time tuple format used by time functionsNANOSECONDS_PER_SECOND: int = 1_000_000_000
SYSTEM_EPOCH_TIMESTAMP_NS: int # System epoch timestamp in nanoseconds (Windows compatibility)
escape_hatch: _EscapeHatch