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.

datetime methodPython 2.3+ (tzinfo argument 3.6+)Live demo
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

NameTypeRequiredDescription
datedateyesSupplies year, month, day (a datetime works too; its time part is ignored).
timetimeyesSupplies hour … microsecond and fold.
tzinfotzinfo | Noneno (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 str

Pitfalls

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.