datetime.hour / minute / second / microsecond / tzinfo / fold
Six read-only attributes, identical on datetime and time. tzinfo is what makes a value aware; fold (0 or 1) picks between the two occurrences of a repeated wall time when clocks go back.
Common call
dt.hour, dt.minute
Returns
(14, 30)
Replaces
Slicing "HH:MM" strings
Watch out
No millisecond attribute: dt.microsecond // 1000
dt.hour · dt.minute · dt.second · dt.microsecond · dt.tzinfo · dt.fold
→ int | tzinfo | None
Demo
Live evaluation
Parse a timestamp and read every time-of-day attribute.
Try:
Inputs
whenstran ISO 8601 timestamp
Code
from datetime import datetime dt = datetime.fromisoformat('2026-09-29T14:30:05.25') (dt.hour, dt.minute, dt.second, dt.microsecond, dt.tzinfo, dt.fold)
Result
(14, 30, 5, 250000, None, 0)
A fractional ".25" is 250000 microseconds (the digits are padded on the right), i.e. 250 milliseconds. tzinfo holds the zone object itself — timezone(timedelta(days=-1, seconds=72000)) for -04:00 — while fold stays 0 for anything parsed from text.
Attributes
| Attribute | Type | Meaning |
|---|---|---|
| hour | int | 0..23. |
| minute | int | 0..59. |
| second | int | 0..59 (no leap second 60). |
| microsecond | int | 0..999999. Milliseconds are microsecond // 1000. |
| tzinfo | tzinfo | None | The object passed as tzinfo=, or None for naive values. It is the zone object, not an offset — call utcoffset() for the offset. |
| fold | int | 0 or 1 (3.6+). 1 = the second occurrence of an ambiguous local time. Ignored by comparisons and by fixed-offset zones. |
Common patterns
Minutes since midnight
A compact sortable key for times of day.
minutes = dt.hour * 60 + dt.minute
Truncate to the minute
replace() the smaller fields with zero.
minute_start = dt.replace(second=0, microsecond=0)
Aware or naive?
tzinfo alone is not quite enough; utcoffset() must also be non-None.
aware = dt.tzinfo is not None and dt.utcoffset() is not None
Examples
1. The clock fields
from datetime import datetime
dt = datetime(2026, 9, 29, 14, 30, 5, 250)
(dt.hour, dt.minute, dt.second, dt.microsecond)
Returns
(14, 30, 5, 250)2. tzinfo of naive and aware
from datetime import datetime, UTC
(datetime(2026, 9, 29).tzinfo, datetime(2026, 9, 29, tzinfo=UTC).tzinfo)
Returns
(None, datetime.timezone.utc)3. Same on time objects
from datetime import time
t = time(9, 5, 30)
(t.hour, t.minute, t.second)
Returns
(9, 5, 30)4. fold is kept but not compared
from datetime import datetime
a = datetime(2026, 11, 1, 1, 30, fold=1)
(a.fold, a == a.replace(fold=0))
Returns
(1, True)5. Read-only
from datetime import datetime
dt = datetime(2026, 9, 29, 14)
dt.hour = 15
Returns
AttributeError: attribute 'hour' of 'datetime.datetime' objects is not writable6. A date has no hour
from datetime import date
date(2026, 9, 29).hour
Returns
AttributeError: 'datetime.date' object has no attribute 'hour'Pitfalls
1. Using tzinfo as the offset
tzinfo is the zone object. The offset of this particular datetime comes from utcoffset().
dt.tzinfo
from datetime import datetime datetime.fromisoformat('2026-09-29T08:00-04:00').tzinfo
datetime.timezone(datetime.timedelta(days=-1, seconds=72000))
dt.utcoffset()
from datetime import datetime datetime.fromisoformat('2026-09-29T08:00-04:00').utcoffset().total_seconds() / 3600
-4.0
2. Looking for a millisecond attribute
Only microsecond exists. Divide by 1000 — or format with isoformat(timespec="milliseconds").
.millisecond
from datetime import datetime datetime(2026, 9, 29, 14, 30, 5, 250000).millisecond
AttributeError: 'datetime.datetime' object has no attribute 'millisecond'. Did you mean: 'microsecond'?
microsecond // 1000
from datetime import datetime datetime(2026, 9, 29, 14, 30, 5, 250000).microsecond // 1000
250
When to use
Use it
- Bucketing by hour, business-hours checks, custom labels
- tzinfo to find out whether and how a value is zoned
Reach for something else
- Changing a field → replace()
- Formatting → strftime / isoformat
Notes
CPython impl
Read-only getset descriptors; fold is stored separately from the packed time bytes and does not take part in comparisons or hashing
fold
Only a tzinfo with DST transitions (zoneinfo) gives fold meaning: 01:30 on a fall-back night happens twice, fold=0 is the first
Also on
hour/minute/second/microsecond/tzinfo/fold exist on both datetime and time; date has none of them
FAQ
dt.hour and dt.minute — int attributes without parentheses. For text use dt.strftime("%H:%M").