Skip to main content

Lib/datetime.py (part 2)

Source:

cpython 3.14 @ ab2d84fe1023/Lib/datetime.py

This annotation supplements lib_datetime_detail with arithmetic, timezone disambiguation (PEP 495 fold), ISO 8601 parsing, and the timedelta implementation.

Map

LinesSymbolRole
1-200timedeltaDuration: days, seconds, microseconds
201-400date arithmeticdate + timedelta, date - date
401-700datetime constructionnow(), utcnow(), fromtimestamp(), fromisoformat()
701-900datetime arithmeticdatetime + timedelta, datetime - datetime
901-1100fold and DST disambiguationPEP 495 wall clock fold
1101-1300strftime / strptimeFormat and parse
1301-1600timezoneFixed-offset tzinfo subclass
1601-1900astimezoneConvert between timezones
1901-2900time, date, datetime fromisoformatISO 8601 parsing (Python 3.11+)

Reading

timedelta normalization

timedelta stores duration in three fields: days, seconds (0-86399), microseconds (0-999999). The constructor normalizes any input to this canonical form.

# CPython: Lib/datetime.py:367 timedelta.__new__
def __new__(cls, days=0, seconds=0, microseconds=0,
milliseconds=0, minutes=0, hours=0, weeks=0):
...
d, s, us = _check_tzinfo_arg(days, seconds, microseconds,
milliseconds, minutes, hours, weeks)
...
self = object.__new__(cls)
self._days = d
self._seconds = s
self._microseconds = us
return self

Total duration in microseconds is (days * 86400 + seconds) * 1_000_000 + microseconds.

fold and DST transition disambiguation

PEP 495 added fold=0|1 to datetime and time. When a local clock repeats due to a DST fall-back, fold=0 means the first occurrence and fold=1 the second. Most tzinfo implementations ignore fold unless they implement fromutc.

fromisoformat (Python 3.11+)

Python 3.11 extended fromisoformat to accept any valid ISO 8601 format, including formats with Z for UTC, fractional seconds, and week-number dates.

# CPython: Lib/datetime.py:1580 datetime.fromisoformat
@classmethod
def fromisoformat(cls, date_string):
dstr = date_string.upper()
...
# Handles: 2023-01-15, 2023-01-15T10:30:00, 2023-01-15T10:30:00Z,
# 2023-01-15T10:30:00+05:30, 2023W015, etc.

astimezone

# CPython: Lib/datetime.py:1935 datetime.astimezone
def astimezone(self, tz=None):
if tz is None:
tz = timezone(self.utcoffset() or timedelta())
...
utc = self.replace(tzinfo=self.tzinfo).utctimetuple()
...
return tz.fromutc(datetime(*utc[:6]).replace(tzinfo=tz))

Converts a timezone-aware datetime to a different timezone by converting to UTC first, then converting to the target timezone.

gopy notes

datetime is partially available via the C extension _datetime. A gopy port should wrap Go's time.Time type. Key differences: Go's time.Time is always timezone-aware (with time.UTC or a *time.Location), while Python's datetime can be naive. fold requires storing an extra boolean per time.Time value.