Datetime in pyfake
Simple usage
pyfake generates Python datetime.date, datetime.datetime and datetime.time objects
for fields annotated with those types. By default it inspects the model and emits
appropriate values using the package RNG.
from pyfake import fake
from pydantic import BaseModel
from datetime import datetime
class Event(BaseModel):
when: datetime
result = fake(Event)
print(result)
Values will vary on each run; the important detail is the type returned is a
datetime.datetime object (the registry maps datetime → date-time generator).
Date / Time variants
The registry dispatches based on the Python annotation:
datetime.datetime→pyfake.generators.datetime.generate_datetime(returnsdatetime.datetime)datetime.date→pyfake.generators.datetime.generate_date(returnsdatetime.date)datetime.time→pyfake.generators.datetime.generate_time(returnsdatetime.time)
Example:
from datetime import date, time, datetime
from pydantic import BaseModel
class Mixed(BaseModel):
d: date
t: time
dt: datetime
result = fake(Mixed)
print(result)
'd': datetime.date(2026, 10, 4),
't': datetime.time(14, 23, 5),
'dt': datetime.datetime(2026, 10, 4, 14, 23, 5)
}
Returning multiple values
Use num to generate multiple instances:
results = fake(Event, num=3)
print(results)
{'when': datetime.datetime(2026, 4, 7, 12, 34, 56)},
{'when': datetime.datetime(2025, 9, 1, 8, 0, 12)},
{'when': datetime.datetime(1970, 7, 3, 3, 14, 15)}
]
Receiving Pydantic model instances
By default fake(...) returns dictionaries. Request model instances with as_dict=False:
results = fake(Event, num=2, as_dict=False)
print(results)
Event(when=datetime.datetime(2026, 4, 7, 12, 34, 56)),
Event(when=datetime.datetime(2025, 1, 1, 0, 0, 1)),
]
Nullable / Optional fields
If a field is a union that includes None (e.g. Optional[datetime] or datetime | None),
the registry marks the union as nullable. In the current implementation the resolver
returns None roughly 20% of the time for nullable variants; otherwise it generates a
datetime/date/time as usual.
from typing import Optional
from pydantic import BaseModel
from datetime import datetime
class Maybe(BaseModel):
when: Optional[datetime]
results = fake(Maybe, num=5)
print(results)
{'when': datetime.datetime(2026, 4, 7, 12, 34, 56)},
{'when': None},
{'when': datetime.datetime(2022, 1, 2, 3, 4, 5)},
{'when': datetime.datetime(2010, 6, 7, 8, 9, 10)},
{'when': None}
]
Default values
If a non-None default is provided on the field, the registry will return that value
instead of generating a random one.
from pydantic import Field
from datetime import datetime
class Meeting(BaseModel):
when: datetime = Field(default=datetime(2022, 1, 1, 9, 0))
result = fake(Meeting)
print(result)
Bounds, formats and generator args
The datetime generators accept the usual bound arguments: lt, gt, le, ge.
The Resolver collects generator arguments from field metadata and annotated types
and attaches them to the resolved schema; the GeneratorRegistry then forwards
those arguments into the generator functions.
- Bounds (
gt,ge,lt,le) are forwarded togenerate_date,generate_datetime, andgenerate_time. - You can request a specific generator format name (
date,date-time,time) via field JSON schema extras (the resolver readsField(..., json_schema_extra={"format": "date"})), or by using annotated metadata that the resolver understands (e.g.annotated_types.Ge).
Examples:
from datetime import datetime, date
from pydantic import Field
from annotated_types import Ge, Le
from typing import Annotated
class Bounded(BaseModel):
# annotated bounds (resolver recognizes annotated_types.Ge/Le)
when: Annotated[datetime, Ge(datetime(2020, 1, 1)), Le(datetime(2030, 1, 1))]
class DateOnly(BaseModel):
# request the date generator explicitly via json_schema_extra
day: date = Field(json_schema_extra={"format": "date"})
print(fake(Bounded))
print(fake(DateOnly))
{'day': datetime.date(2026, 10, 4)}
Implementation detail: when the resolved GeneratorArgs includes a format that matches
a generator key (for example date, date-time, time) the registry will choose that
generator and pass the other generator args (gt, lt, ge, le, etc.) into it.
JSON output
If you need JSON strings rather than Python objects use fake.json(...). That helper
serializes the generated output with json.dumps(..., default=str), so dates and
datetimes are turned into their str() representations (e.g. "2026-04-07 12:34:56").
Timezone-aware datetimes
Pass any datetime.tzinfo
subclass — including datetime.timezone constants and zoneinfo.ZoneInfo instances —
through json_schema_extra={"timezone": ...} on a datetime field.
from pyfake import fake
from pydantic import BaseModel, Field
from datetime import datetime, timezone
from typing import Annotated
from zoneinfo import ZoneInfo
class Event(BaseModel):
# stdlib UTC constant
utc_ts: Annotated[datetime, Field(..., json_schema_extra={"timezone": timezone.utc})]
# IANA timezone via zoneinfo
ny_ts: Annotated[datetime, Field(..., json_schema_extra={"timezone": ZoneInfo("America/New_York")})]
result = fake(Event)
print(result)
'utc_ts': datetime.datetime(2024, 3, 15, 9, 42, 17, tzinfo=datetime.timezone.utc),
'ny_ts': datetime.datetime(2019, 11, 7, 22, 5, 33, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
}
The timezone is stamped onto the generated datetime via replace(tzinfo=timezone) after
the random value is produced, so bounds (ge, gt, le, lt) are still expressed as
naive datetimes:
from datetime import datetime
from pydantic import Field
from typing import Annotated
from zoneinfo import ZoneInfo
class Bounded(BaseModel):
ts: Annotated[
datetime,
Field(
ge=datetime(2020, 1, 1),
le=datetime(2020, 12, 31, 23, 59, 59),
json_schema_extra={"timezone": ZoneInfo("UTC")},
),
]
result = fake(Bounded)
print(result)
Omitting timezone (or annotating a field without json_schema_extra) always returns
a naive datetime, preserving backward-compatible behaviour.
date and time fields
Timezone is only meaningful for datetime fields. If you accidentally pass
timezone on a date or time field the generator silently absorbs the argument
via **kwargs and continues to return a naive value — no error is raised.
JSON output
If you need JSON strings rather than Python objects use fake.json(...). That helper
serializes the generated output with json.dumps(..., default=str), so dates and
datetimes (including timezone-aware ones) are turned into their str() representations
(e.g. "2026-04-07 12:34:56+00:00").
Implementation notes
- Generator functions:
pyfake.generators.datetime.generate_date,generate_datetime,generate_time. - Registry type mapping:
datetime.datetime→date-time;datetime.date→date;datetime.time→time. - Nullable unions are handled by the resolver/registry:
Noneis selected roughly 20% of the time for nullable variants. - Generators return native Python objects (not ISO strings) — use
fake.json()to get a string-serialized form. generate_datetimeaccepts atimezonekeyword argument (anydatetime.tzinfosubclass). The resolver extracts it fromField(json_schema_extra={"timezone": ...})and the registry forwards it throughGeneratorArgs.timezone.
Unsupported / Partial support
- Locale-aware generation: there is no built-in locale or format-string based datetime generation.