Let your Python tests travel through time by mocking datetime and time functions
npx @tessl/cli install tessl/pypi-freezegun@1.5.0FreezeGun is a Python testing library that allows your tests to travel through time by mocking datetime and time functions. It freezes calls to datetime.datetime.now(), datetime.datetime.utcnow(), datetime.date.today(), time.time(), time.localtime(), time.gmtime(), time.strftime(), time.monotonic(), and time.perf_counter() to return consistent, predictable values during test execution.
pip install freezegunfrom freezegun import freeze_time, configureNote: Only freeze_time and configure are officially exported. Other components can be accessed from internal modules but are not part of the guaranteed public API:
# Internal API access (not guaranteed stable)
from freezegun.api import FakeDate, FakeDatetime, get_current_time
from freezegun.config import reset_configfrom freezegun import freeze_time
import datetime
# As a decorator
@freeze_time("2012-01-14")
def test_datetime():
assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)
# As a context manager
def test_context_manager():
with freeze_time("2012-01-14"):
assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)
# Time is unfrozen outside the context
# Manual start/stop
def test_manual():
freezer = freeze_time("2012-01-14 12:00:01")
freezer.start()
assert datetime.datetime.now() == datetime.datetime(2012, 1, 14, 12, 0, 1)
freezer.stop()FreezeGun works by monkey-patching Python's time and datetime modules at runtime. It replaces standard time functions with fake implementations that return frozen values, while preserving original functionality for restoration when freezing stops. The library uses three time factory patterns:
This approach ensures comprehensive time mocking across the entire Python environment while maintaining compatibility with existing codebases.
Main functionality for freezing time during test execution. Can be used as a decorator, context manager, or manually controlled.
def freeze_time(
time_to_freeze: Optional[_Freezable] = None,
tz_offset: Union[int, datetime.timedelta] = 0,
ignore: Optional[List[str]] = None,
tick: bool = False,
as_arg: bool = False,
as_kwarg: str = '',
auto_tick_seconds: float = 0,
real_asyncio: bool = False
) -> _freeze_time:
"""
Freezes time for testing purposes.
Args:
time_to_freeze: The datetime to freeze time at (see _Freezable type for supported formats)
tz_offset: Timezone offset in hours or timedelta
ignore: List of module names to ignore during freezing
tick: If True, time advances with real-world time
as_arg: Pass time factory as first argument to decorated function
as_kwarg: Pass time factory as named keyword argument
auto_tick_seconds: Automatically advance time by this interval
real_asyncio: Allow asyncio event loops to see real monotonic time
Returns:
_freeze_time: Time freezer instance that can be used as decorator or context manager
"""The class returned by freeze_time() that provides context manager and decorator functionality.
class _freeze_time:
"""
A class to freeze time for testing purposes.
This class can be used as a context manager or a decorator to freeze time
during the execution of a block of code or a function.
"""
def __init__(
self,
time_to_freeze_str: Optional[_Freezable],
tz_offset: Union[int, datetime.timedelta],
ignore: List[str],
tick: bool,
as_arg: bool,
as_kwarg: str,
auto_tick_seconds: float,
real_asyncio: Optional[bool],
): ...
def start(self) -> Union[StepTickTimeFactory, TickingDateTimeFactory, FrozenDateTimeFactory]:
"""
Starts freezing time and returns the time factory.
Returns:
Time factory instance for controlling frozen time
"""
def stop(self) -> None:
"""Stops freezing time and restores the original time functions."""
def __enter__(self) -> Union[StepTickTimeFactory, TickingDateTimeFactory, FrozenDateTimeFactory]:
"""Context manager entry point. Calls start()."""
def __exit__(self, *args: Any) -> None:
"""Context manager exit point. Calls stop()."""
def __call__(self, func: Union[Type[T], Callable]) -> Union[Type[T], Callable]:
"""
Decorator functionality for functions, methods, and classes.
Args:
func: Function, method, or class to decorate
Returns:
Decorated callable with frozen time behavior
"""
def decorate_class(self, klass: Type[T]) -> Type[T]:
"""Decorates a class to freeze time during its execution."""
def decorate_callable(self, func: Callable) -> Callable:
"""Decorates a callable to freeze time during its execution."""
def decorate_coroutine(self, coroutine: Callable) -> Callable:
"""Decorates a coroutine to freeze time during its execution."""Time factory classes control how frozen time behaves during test execution.
class FrozenDateTimeFactory:
"""Factory for static frozen time that doesn't advance."""
def __init__(self, time_to_freeze: datetime.datetime): ...
def __call__(self) -> datetime.datetime:
"""Returns the frozen datetime."""
def tick(self, delta: Union[datetime.timedelta, float] = datetime.timedelta(seconds=1)) -> datetime.datetime:
"""
Advances frozen time by the specified delta.
Args:
delta: Time delta to advance (timedelta or seconds as float/int)
Returns:
datetime.datetime: New frozen time after advancement
"""
def move_to(self, target_datetime: _Freezable) -> None:
"""
Moves frozen time to a specific target datetime.
Args:
target_datetime: Target time to move to (see _Freezable type for supported formats)
"""
class TickingDateTimeFactory:
"""Factory for time that advances with real-world time passage."""
def __init__(self, time_to_freeze: datetime.datetime, start: datetime.datetime): ...
def __call__(self) -> datetime.datetime:
"""Returns frozen time plus elapsed real time since start."""
def tick(self, delta: Union[datetime.timedelta, float] = datetime.timedelta(seconds=1)) -> datetime.datetime:
"""Advances the base frozen time by delta."""
def move_to(self, target_datetime: _Freezable) -> None:
"""Moves base frozen time to target, resets real time tracking."""
class StepTickTimeFactory:
"""Factory for time that automatically advances by fixed intervals."""
def __init__(self, time_to_freeze: datetime.datetime, step_width: float): ...
def __call__(self) -> datetime.datetime:
"""Returns current time and advances by step_width."""
def tick(self, delta: Optional[Union[datetime.timedelta, float]] = None) -> datetime.datetime:
"""
Advances time by delta or step_width if delta is None.
Args:
delta: Time to advance (defaults to step_width)
Returns:
datetime.datetime: New time after advancement
"""
def update_step_width(self, step_width: float) -> None:
"""
Updates the automatic advancement interval.
Args:
step_width: New step width in seconds
"""
def move_to(self, target_datetime: _Freezable) -> None:
"""Moves to target datetime."""Replacement classes for Python's built-in date and datetime that provide frozen behavior.
class FakeDate:
"""Replacement for datetime.date with frozen behavior."""
def __init__(self, year: int, month: int, day: int): ...
@classmethod
def today(cls) -> 'FakeDate':
"""Returns the current frozen date."""
def __add__(self, other: datetime.timedelta) -> 'FakeDate':
"""Add timedelta to date."""
def __sub__(self, other: Union['FakeDate', datetime.timedelta]) -> Union['FakeDate', datetime.timedelta]:
"""Subtract date or timedelta from date."""
# Class attributes
min: 'FakeDate' # Minimum representable date
max: 'FakeDate' # Maximum representable date
class FakeDatetime:
"""Replacement for datetime.datetime with frozen behavior."""
def __init__(self, year: int, month: int, day: int, hour: int = 0, minute: int = 0, second: int = 0, microsecond: int = 0, tzinfo: Optional[datetime.tzinfo] = None): ...
@classmethod
def now(cls, tz: Optional[datetime.tzinfo] = None) -> 'FakeDatetime':
"""Returns the current frozen datetime."""
@classmethod
def utcnow(cls) -> 'FakeDatetime':
"""Returns the current frozen UTC datetime."""
@classmethod
def today(cls) -> 'FakeDatetime':
"""Returns the current frozen date as datetime."""
@classmethod
def fromtimestamp(cls, t: float, tz: Optional[datetime.tzinfo] = None) -> 'FakeDatetime':
"""Creates datetime from timestamp using frozen timezone offset."""
def date(self) -> FakeDate:
"""Returns the date portion as FakeDate."""
def timestamp(self) -> float:
"""Returns POSIX timestamp respecting frozen time."""
def astimezone(self, tz: Optional[datetime.tzinfo] = None) -> 'FakeDatetime':
"""Returns timezone-aware datetime."""
def __add__(self, other: datetime.timedelta) -> 'FakeDatetime':
"""Add timedelta to datetime."""
def __sub__(self, other: Union['FakeDatetime', datetime.timedelta]) -> Union['FakeDatetime', datetime.timedelta]:
"""Subtract datetime or timedelta from datetime."""
@property
def nanosecond(self) -> int:
"""Nanosecond component (0 if not supported)."""
# Class attributes
min: 'FakeDatetime' # Minimum representable datetime
max: 'FakeDatetime' # Maximum representable datetimeGlobal configuration for FreezeGun behavior across all freeze operations.
def configure(
default_ignore_list: Optional[List[str]] = None,
extend_ignore_list: Optional[List[str]] = None
) -> None:
"""
Configure global FreezeGun settings.
Args:
default_ignore_list: Replace default ignore list with these modules
extend_ignore_list: Add these modules to default ignore list
Raises:
ConfigurationError: If both parameters are provided
"""
def reset_config() -> None:
"""Reset configuration to default settings."""
class Settings:
"""Global settings container."""
def __init__(self, default_ignore_list: Optional[List[str]] = None): ...
default_ignore_list: List[str] # Modules to ignore during freezing
class ConfigurationError(Exception):
"""Raised when configuration parameters conflict."""Helper functions for time manipulation and type conversion.
def get_current_time() -> datetime.datetime:
"""
Returns the current frozen time.
Returns:
datetime.datetime: Current frozen datetime
Raises:
IndexError: If no time is currently frozen
"""
def convert_to_timezone_naive(time_to_freeze: datetime.datetime) -> datetime.datetime:
"""
Converts timezone-aware datetime to naive UTC datetime.
Args:
time_to_freeze: Input datetime (may be timezone-aware)
Returns:
datetime.datetime: Naive UTC datetime
"""
def datetime_to_fakedatetime(datetime: datetime.datetime) -> FakeDatetime:
"""
Converts standard datetime to FakeDatetime.
Args:
datetime: Standard datetime object
Returns:
FakeDatetime: Equivalent FakeDatetime instance
"""
def date_to_fakedate(date: datetime.date) -> FakeDate:
"""
Converts standard date to FakeDate.
Args:
date: Standard date object
Returns:
FakeDate: Equivalent FakeDate instance
"""from typing import Union, Optional, List, Callable, Iterator, Type, Any
import types
import datetime
_Freezable = Union[
str, # "2020-01-01", "2020-01-01 12:30:45"
datetime.datetime, # Specific datetime object
datetime.date, # Date (time set to midnight)
datetime.timedelta, # Relative to current time
types.FunctionType, # Function returning datetime
Callable[[], Union[str, datetime.datetime, datetime.date, datetime.timedelta]], # Callable returning datetime
Iterator[datetime.datetime] # Generator yielding datetime values
]__version__: str = '1.5.5' # Package version
__title__: str = 'freezegun' # Package title
__author__: str = 'Steve Pulec' # Package author
__license__: str = 'Apache License 2.0' # Package license
__copyright__: str = 'Copyright 2012 Steve Pulec' # Copyright noticeDEFAULT_IGNORE_LIST: List[str] # Default modules ignored during freezing: [
'nose.plugins', 'six.moves', 'django.utils.six.moves', 'google.gax',
'threading', 'multiprocessing', 'queue', 'selenium', '_pytest.terminal.',
'_pytest.runner.', 'gi', 'prompt_toolkit'
]
settings: Settings # Global settings instancefrom freezegun import freeze_time
import datetime
# Ticking time - advances with real time
@freeze_time("2020-01-01", tick=True)
def test_ticking():
start = datetime.datetime.now()
time.sleep(1)
end = datetime.datetime.now()
assert end > start # Time has advanced
# Auto-tick time - advances automatically
@freeze_time("2020-01-01", auto_tick_seconds=1)
def test_auto_tick():
time1 = datetime.datetime.now()
time2 = datetime.datetime.now()
# time2 is 1 second after time1
# Manual time control
with freeze_time("2020-01-01") as frozen_time:
assert datetime.datetime.now() == datetime.datetime(2020, 1, 1)
# Advance time manually
frozen_time.tick(delta=datetime.timedelta(days=1))
assert datetime.datetime.now() == datetime.datetime(2020, 1, 2)
# Jump to specific time
frozen_time.move_to("2020-06-15 14:30:00")
assert datetime.datetime.now() == datetime.datetime(2020, 6, 15, 14, 30)from freezegun import freeze_time
import datetime
# Timezone offset
@freeze_time("2020-01-01 12:00:00", tz_offset=-5)
def test_timezone():
# UTC time is frozen at 12:00:00
assert datetime.datetime.utcnow() == datetime.datetime(2020, 1, 1, 12, 0, 0)
# Local time shows 07:00:00 (UTC-5)
assert datetime.datetime.now() == datetime.datetime(2020, 1, 1, 7, 0, 0)
# Using timedelta for offset
@freeze_time("2020-01-01", tz_offset=datetime.timedelta(hours=3))
def test_timedelta_offset():
# Local time is 3 hours ahead of UTC
passfrom freezegun import freeze_time
import unittest
import datetime
# Class decorator - freezes for all test methods
@freeze_time("2020-01-01")
class TestTimeTravel(unittest.TestCase):
def test_method_one(self):
assert datetime.datetime.now().year == 2020
def test_method_two(self):
assert datetime.datetime.now().month == 1
# Method decorator with time factory injection
class TestWithFactory(unittest.TestCase):
@freeze_time("2020-01-01", as_kwarg='frozen_time')
def test_with_factory_kwarg(self, frozen_time):
assert datetime.datetime.now() == datetime.datetime(2020, 1, 1)
# Use the factory to control time
frozen_time.tick(datetime.timedelta(days=5))
assert datetime.datetime.now() == datetime.datetime(2020, 1, 6)
@freeze_time("2020-01-01", as_arg=True)
def test_with_factory_arg(self, frozen_time):
# frozen_time is passed as first argument
frozen_time.move_to("2020-12-31")
assert datetime.datetime.now().month == 12from freezegun import freeze_time, configure
# Configure globally
configure(extend_ignore_list=['my_module', 'another_module'])
# Or per freeze operation
@freeze_time("2020-01-01", ignore=['requests', 'urllib3'])
def test_with_ignored_modules():
# Time is frozen except in requests and urllib3 modules
pass
# Reset configuration
from freezegun.config import reset_config
reset_config()from freezegun import freeze_time
import datetime
# Using a function
def get_test_time():
return datetime.datetime(2020, 6, 15, 10, 30, 0)
@freeze_time(get_test_time)
def test_function_time():
assert datetime.datetime.now() == datetime.datetime(2020, 6, 15, 10, 30, 0)
# Using a generator
def time_generator():
base = datetime.datetime(2020, 1, 1)
for i in range(10):
yield base + datetime.timedelta(days=i)
time_gen = time_generator()
@freeze_time(time_gen)
def test_generator_time():
# Uses next value from generator
pass