datetime.combine / date() / time() / timetz()
The glue between the three value types. combine takes the zone from the time unless you pass tzinfo; time() drops the zone, timetz() keeps it.
Common call
datetime.combine(d, time(9, 30), tzinfo=UTC)
Returns
datetime.datetime(…, 9, 30, tzinfo=datetime.timezone.utc)
Replaces
datetime(d.year, d.month, d.day, t.hour, t.minute, …)
Watch out
dt.time() loses tzinfo; use dt.timetz() to keep it
datetime.combine(datedate — Supplies year, month, day (a datetime works too; its time part is ignored).type: date · required, timetime — Supplies hour … microsecond and fold.type: time · required, tzinfotzinfo — Overrides the time's tzinfo (3.6+); pass None to force a naive result.type: tzinfo | None · default: time.tzinfo=time.tzinfo)
→ datetime
Demo
Live evaluation
A date and a time of day become one datetime.
Try:
Inputs
dstrYYYY-MM-DD
tstrHH:MM[+HH:MM]
Code
from datetime import date, datetime, time datetime.combine(date.fromisoformat('2026-09-29'), time.fromisoformat('09:30'))
Result
datetime.datetime(2026, 9, 29, 9, 30)
combine copies tzinfo from the time, so 09:30+05:30 gives an aware result. On the way back, time() returns the naive wall-clock time and timetz() the same time with its timezone; for a naive datetime the two are identical.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| date | date | yes | Supplies year, month, day (a datetime works too; its time part is ignored). |
| time | time | yes | Supplies hour … microsecond and fold. |
| tzinfo | tzinfo | None | no (time.tzinfo) | Overrides the time's tzinfo (3.6+); pass None to force a naive result. |
Return value
datetime — combine → datetime. dt.date() → date, dt.time() → naive time, dt.timetz() → time with tzinfo.
Common patterns
Start and end of a day
time() is midnight; time.max the last microsecond.
from datetime import datetime, time, UTC start = datetime.combine(d, time(), tzinfo=UTC) end = datetime.combine(d, time.max, tzinfo=UTC)
Date input + time input from a form
Two ISO fields, one aware datetime.
from datetime import date, datetime, time when = datetime.combine(date.fromisoformat(form['day']), time.fromisoformat(form['at']), tzinfo=user_tz)
Group events by calendar day
.date() is hashable.
from itertools import groupby for day, items in groupby(sorted(events, key=lambda e: e.at), key=lambda e: e.at.date()): ...
Examples
1. Join
from datetime import date, datetime, time
datetime.combine(date(2026, 9, 29), time(14, 30))
Returns
datetime.datetime(2026, 9, 29, 14, 30)2. Zone from the time
from datetime import date, datetime, time, UTC
datetime.combine(date(2026, 9, 29), time(14, 30, tzinfo=UTC))
Returns
datetime.datetime(2026, 9, 29, 14, 30, tzinfo=datetime.timezone.utc)3. Zone as an argument (3.6+)
from datetime import date, datetime, time, UTC
datetime.combine(date(2026, 9, 29), time(14, 30), tzinfo=UTC)
Returns
datetime.datetime(2026, 9, 29, 14, 30, tzinfo=datetime.timezone.utc)4. Midnight of a date
from datetime import date, datetime, time
datetime.combine(date(2026, 9, 29), time())
Returns
datetime.datetime(2026, 9, 29, 0, 0)5. Split: date(), time(), timetz()
from datetime import datetime, timedelta, timezone
dt = datetime(2026, 9, 29, 14, 30, tzinfo=timezone(timedelta(hours=2)))
(dt.date(), dt.time(), dt.timetz())
Returns
(datetime.date(2026, 9, 29), datetime.time(14, 30), datetime.time(14, 30, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200))))6. Strings are rejected
from datetime import datetime, time
datetime.combine('2026-09-29', time(14, 30))
Returns
TypeError: combine() argument 1 must be datetime.date, not strPitfalls
1. Losing the zone with time()
dt.time() is always naive. Comparing it with aware times, or combining it back, silently drops the offset.
.time()
from datetime import datetime datetime.fromisoformat('2026-09-29T14:30+02:00').time().tzinfo is None
True
.timetz()
from datetime import datetime datetime.fromisoformat('2026-09-29T14:30+02:00').timetz().tzinfo
datetime.timezone(datetime.timedelta(seconds=7200))
2. Calling date() on the class after from datetime import datetime
datetime.date is the METHOD here, not the date class, so it needs a datetime instance.
datetime.date(…)
from datetime import datetime datetime.date(2026, 9, 29)
TypeError: descriptor 'date' for 'datetime.datetime' objects doesn't apply to a 'int' object
import date
from datetime import date date(2026, 9, 29)
datetime.date(2026, 9, 29)
When to use
Use it
- Separate date and time inputs (forms, CSV columns)
- Day boundaries: combine(d, time()) and combine(d, time.max)
Reach for something else
- Changing only the time of an existing datetime → replace(hour=…)
Notes
CPython impl
combine copies fold from the time; date() / time() / timetz() build new objects from the packed fields
Naming
With from datetime import datetime, the name datetime.date refers to this method — a frequent source of TypeErrors
tzinfo
combine(d, t, tzinfo=None) gives a naive result even when t is aware
FAQ
dt.date() returns a date with the same year, month and day. For an aware value those are the local fields; call dt.astimezone(UTC).date() first if you want the UTC date.