Python Datetime Format Cheat Sheet
1 · The lesson
readThe datetime module has three types you will use all the time. A date is a day. A datetime is a day plus a clock time. A timedelta is a length of time: subtract two datetimes and you get one. This page shows how to create them, turn them into text and back, do date maths and work with time zones. For the full tutorial, see Datetime.
The examples use one datetime, d, which is a Saturday:
from datetime import date, time, datetime, timedelta, timezone d = datetime(2026, 3, 14, 9, 30) print(d) # 2026-03-14 09:30:00
1. Create
print(repr(date(2026, 3, 14))) # datetime.date(2026, 3, 14) print(repr(time(9, 30))) # datetime.time(9, 30) print(d.date()) # 2026-03-14 print(datetime.combine(date(2026, 3, 14), time(18))) # 2026-03-14 18:00:00
setup added so this can run · re-runs 1 earlier block on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) def date(*_a, **_kw): print('-> date() called') return _AutoMock('date()') def time(*_a, **_kw): print('-> time() called') return _AutoMock('time()') d = _AutoMock('d') datetime = _AutoMock('datetime') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
A date has no time and a time has no day. d.date() keeps only the date part, and datetime.combine() joins a date and a time.
For the current moment:
| Call | What you get |
|---|---|
datetime.now() | Now, on the local clock, with no time zone attached |
datetime.now(timezone.utc) | Now in UTC (world time): the safe choice for logs and databases |
date.today() | Today's date |
2. Parts
print(d.year, d.month, d.day) # 2026 3 14 print(d.hour, d.minute) # 9 30 print(d.weekday()) # 5 print(d.isoweekday()) # 6 print(d.isocalendar().week) # 11 print(d.replace(day=1).date()) # 2026-03-01
setup added so this can run · re-runs 2 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) d = _AutoMock('d') def date(*_a, **_kw): print('-> date() called') return _AutoMock('date()') def time(*_a, **_kw): print('-> time() called') return _AutoMock('time()') datetime = _AutoMock('datetime') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', 'print(repr(date(2026, 3, 14))) # datetime.date(2026, 3, 14)\nprint(repr(time(9, 30))) # datetime.time(9, 30)\nprint(d.date()) # 2026-03-14\nprint(datetime.combine(date(2026, 3, 14), time(18))) # 2026-03-14 18:00:00', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
weekday() counts Monday as 0 and Sunday as 6. isoweekday() counts Monday as 1 and Sunday as 7. isocalendar().week is the ISO week number. replace() gives a copy with one part changed. Here it gives the first day of the month.
3. Date to text
strftime() ("string format time") turns a date into text. You describe the text with format codes such as %Y for the year (see section 4).
print(d.strftime("%Y-%m-%d")) # 2026-03-14 print(d.strftime("%d/%m/%Y")) # 14/03/2026 print(d.strftime("%a %d %b %Y")) # Sat 14 Mar 2026 print(d.strftime("%A, %B %d")) # Saturday, March 14 print(d.strftime("%I:%M %p")) # 09:30 AM print(f"{d:%d %b, %H:%M}") # 14 Mar, 09:30 print(d.isoformat()) # 2026-03-14T09:30:00 print(d.isoformat(" ", "minutes")) # 2026-03-14 09:30
setup added so this can run · re-runs 3 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) d = _AutoMock('d') def date(*_a, **_kw): print('-> date() called') return _AutoMock('date()') def time(*_a, **_kw): print('-> time() called') return _AutoMock('time()') datetime = _AutoMock('datetime') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', 'print(repr(date(2026, 3, 14))) # datetime.date(2026, 3, 14)\nprint(repr(time(9, 30))) # datetime.time(9, 30)\nprint(d.date()) # 2026-03-14\nprint(datetime.combine(date(2026, 3, 14), time(18))) # 2026-03-14 18:00:00', 'print(d.year, d.month, d.day) # 2026 3 14\nprint(d.hour, d.minute) # 9 30\nprint(d.weekday()) # 5\nprint(d.isoweekday()) # 6\nprint(d.isocalendar().week) # 11\nprint(d.replace(day=1).date()) # 2026-03-01', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
The same codes work inside an f-string after a colon. isoformat() gives the standard ISO 8601 form (year-month-day, then the time), which is the best form for files and APIs.
4. Format codes
| Code | Meaning | For d |
|---|---|---|
%Y / %y | Year, 4 digits / 2 digits | 2026 / 26 |
%m | Month as a number, 2 digits | 03 |
%B / %b | Month name, full / short | March / Mar |
%d | Day of the month, 2 digits | 14 |
%j | Day of the year | 073 |
%A / %a | Weekday name, full / short | Saturday / Sat |
%H | Hour, 24-hour clock | 09 |
%I | Hour, 12-hour clock | 09 |
%p | AM or PM | AM |
%M | Minute | 30 |
%S | Second | 00 |
%f | Microsecond, 6 digits | 000000 |
%z / %Z | UTC offset / zone name (only when the datetime has a zone) | +0530 / IST |
%% | A literal % sign | % |
Note the capitals: %m is the month, %M is the minute.
5. Text to date
strptime() ("string parse time") reads text into a datetime. The format must match the text exactly.
print(repr(datetime.strptime("14/03/2026", "%d/%m/%Y"))) # datetime.datetime(2026, 3, 14, 0, 0) print(datetime.strptime("9:05 PM", "%I:%M %p").hour) # 21 print(date.fromisoformat("2026-03-14")) # 2026-03-14 print(datetime.fromisoformat("2026-03-14T09:30Z").tzinfo) # UTC
setup added so this can run · re-runs 2 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) date = _AutoMock('date') datetime = _AutoMock('datetime') def time(*_a, **_kw): print('-> time() called') return _AutoMock('time()') d = _AutoMock('d') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', 'print(repr(date(2026, 3, 14))) # datetime.date(2026, 3, 14)\nprint(repr(time(9, 30))) # datetime.time(9, 30)\nprint(d.date()) # 2026-03-14\nprint(datetime.combine(date(2026, 3, 14), time(18))) # 2026-03-14 18:00:00', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
%p reads AM or PM. fromisoformat() reads ISO text. Since Python 3.11 it also accepts a Z or an offset like +05:30 at the end.
Bad text, and dates that do not exist, raise ValueError:
for text in ["14/03/2026", "31/02/2026", "next week"]: try: print(datetime.strptime(text, "%d/%m/%Y").date()) except ValueError: print("not a date:", text)
setup added so this can run · re-runs 3 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) datetime = _AutoMock('datetime') def date(*_a, **_kw): print('-> date() called') return _AutoMock('date()') def time(*_a, **_kw): print('-> time() called') return _AutoMock('time()') d = _AutoMock('d') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', 'print(repr(date(2026, 3, 14))) # datetime.date(2026, 3, 14)\nprint(repr(time(9, 30))) # datetime.time(9, 30)\nprint(d.date()) # 2026-03-14\nprint(datetime.combine(date(2026, 3, 14), time(18))) # 2026-03-14 18:00:00', 'print(repr(datetime.strptime("14/03/2026", "%d/%m/%Y")))\n# datetime.datetime(2026, 3, 14, 0, 0)\nprint(datetime.strptime("9:05 PM", "%I:%M %p").hour) # 21\nprint(date.fromisoformat("2026-03-14")) # 2026-03-14\nprint(datetime.fromisoformat("2026-03-14T09:30Z").tzinfo) # UTC', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
2026-03-14 not a date: 31/02/2026 not a date: next week
6. Date maths
Add or subtract a timedelta to move a date. Subtract two dates to get the gap between them.
print(d + timedelta(days=30)) # 2026-04-13 09:30:00 print(d - timedelta(hours=10)) # 2026-03-13 23:30:00 print((date(2026, 12, 25) - d.date()).days) # 286 print(abs(date(2026, 1, 1) - d.date()).days) # 72 print(d.replace(hour=0, minute=0)) # 2026-03-14 00:00:00 print(date(2026, 3, 1) - timedelta(days=1)) # 2026-02-28 print(d < d + timedelta(seconds=1)) # True
setup added so this can run · re-runs 5 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) d = _AutoMock('d') def timedelta(*_a, **_kw): print('-> timedelta() called') return _AutoMock('timedelta()') def date(*_a, **_kw): print('-> date() called') return _AutoMock('date()') def time(*_a, **_kw): print('-> time() called') return _AutoMock('time()') datetime = _AutoMock('datetime') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', 'print(repr(date(2026, 3, 14))) # datetime.date(2026, 3, 14)\nprint(repr(time(9, 30))) # datetime.time(9, 30)\nprint(d.date()) # 2026-03-14\nprint(datetime.combine(date(2026, 3, 14), time(18))) # 2026-03-14 18:00:00', 'print(d.year, d.month, d.day) # 2026 3 14\nprint(d.hour, d.minute) # 9 30\nprint(d.weekday()) # 5\nprint(d.isoweekday()) # 6\nprint(d.isocalendar().week) # 11\nprint(d.replace(day=1).date()) # 2026-03-01', 'print(d.strftime("%Y-%m-%d")) # 2026-03-14\nprint(d.strftime("%d/%m/%Y")) # 14/03/2026\nprint(d.strftime("%a %d %b %Y")) # Sat 14 Mar 2026\nprint(d.strftime("%A, %B %d")) # Saturday, March 14\nprint(d.strftime("%I:%M %p")) # 09:30 AM\nprint(f"{d:%d %b, %H:%M}") # 14 Mar, 09:30\nprint(d.isoformat()) # 2026-03-14T09:30:00\nprint(d.isoformat(" ", "minutes")) # 2026-03-14 09:30', 'print(repr(datetime.strptime("14/03/2026", "%d/%m/%Y")))\n# datetime.datetime(2026, 3, 14, 0, 0)\nprint(datetime.strptime("9:05 PM", "%I:%M %p").hour) # 21\nprint(date.fromisoformat("2026-03-14")) # 2026-03-14\nprint(datetime.fromisoformat("2026-03-14T09:30Z").tzinfo) # UTC', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
Use abs() when you do not know which date is later. Datetimes can be compared and sorted like numbers.
A timedelta stores only days, seconds and microseconds:
print(repr(timedelta(hours=36))) # datetime.timedelta(days=1, seconds=43200) print(timedelta(hours=27).total_seconds()) # 97200.0 print(timedelta(minutes=95)) # 1:35:00 print(timedelta(weeks=2) // timedelta(days=1)) # 14 print(timedelta(hours=1) / 2) # 0:30:00
setup added so this can run · re-runs 1 earlier block on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) def timedelta(*_a, **_kw): print('-> timedelta() called') return _AutoMock('timedelta()') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
total_seconds() gives the whole length in seconds. Dividing one timedelta by another with // tells you how many whole days (or hours) fit. Dividing a timedelta by a number gives a shorter timedelta.
7. Time zones
A datetime with no time zone is called naive. A datetime with a zone is called aware. Use ZoneInfo with a name like "Asia/Kolkata" to attach a zone. On Windows, install the zone data once first:
pip install tzdata
from zoneinfo import ZoneInfo ist = ZoneInfo("Asia/Kolkata") ny = ZoneInfo("America/New_York") t = d.replace(tzinfo=ist) # same clock time, now aware print(f"{t:%H:%M %Z}") # 09:30 IST print(f"{t.astimezone(ny):%H:%M %Z}") # 00:00 EDT print(t.astimezone(timezone.utc).isoformat()) # 2026-03-14T04:00:00+00:00 print(t.utcoffset()) # 5:30:00 print(t.timestamp()) # 1773460800.0 print(datetime.fromtimestamp(0, timezone.utc).year) # 1970
setup added so this can run · re-runs 7 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) d = _AutoMock('d') datetime = _AutoMock('datetime') timezone = _AutoMock('timezone') def date(*_a, **_kw): print('-> date() called') return _AutoMock('date()') def time(*_a, **_kw): print('-> time() called') return _AutoMock('time()') def timedelta(*_a, **_kw): print('-> timedelta() called') return _AutoMock('timedelta()') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', 'print(repr(date(2026, 3, 14))) # datetime.date(2026, 3, 14)\nprint(repr(time(9, 30))) # datetime.time(9, 30)\nprint(d.date()) # 2026-03-14\nprint(datetime.combine(date(2026, 3, 14), time(18))) # 2026-03-14 18:00:00', 'print(d.year, d.month, d.day) # 2026 3 14\nprint(d.hour, d.minute) # 9 30\nprint(d.weekday()) # 5\nprint(d.isoweekday()) # 6\nprint(d.isocalendar().week) # 11\nprint(d.replace(day=1).date()) # 2026-03-01', 'print(d.strftime("%Y-%m-%d")) # 2026-03-14\nprint(d.strftime("%d/%m/%Y")) # 14/03/2026\nprint(d.strftime("%a %d %b %Y")) # Sat 14 Mar 2026\nprint(d.strftime("%A, %B %d")) # Saturday, March 14\nprint(d.strftime("%I:%M %p")) # 09:30 AM\nprint(f"{d:%d %b, %H:%M}") # 14 Mar, 09:30\nprint(d.isoformat()) # 2026-03-14T09:30:00\nprint(d.isoformat(" ", "minutes")) # 2026-03-14 09:30', 'print(repr(datetime.strptime("14/03/2026", "%d/%m/%Y")))\n# datetime.datetime(2026, 3, 14, 0, 0)\nprint(datetime.strptime("9:05 PM", "%I:%M %p").hour) # 21\nprint(date.fromisoformat("2026-03-14")) # 2026-03-14\nprint(datetime.fromisoformat("2026-03-14T09:30Z").tzinfo) # UTC', 'for text in ["14/03/2026", "31/02/2026", "next week"]:\n try:\n print(datetime.strptime(text, "%d/%m/%Y").date())\n except ValueError:\n print("not a date:", text)', 'print(d + timedelta(days=30)) # 2026-04-13 09:30:00\nprint(d - timedelta(hours=10)) # 2026-03-13 23:30:00\nprint((date(2026, 12, 25) - d.date()).days) # 286\nprint(abs(date(2026, 1, 1) - d.date()).days) # 72\nprint(d.replace(hour=0, minute=0)) # 2026-03-14 00:00:00\nprint(date(2026, 3, 1) - timedelta(days=1)) # 2026-02-28\nprint(d < d + timedelta(seconds=1)) # True', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
replace(tzinfo=...) attaches a zone without changing the clock time. astimezone() converts: it shows the same moment on another clock. Store and compare times in UTC, and convert to local time only to show them to a person. A timestamp is the number of seconds since 1 January 1970 UTC.
timezone(timedelta(hours=5, minutes=30)) is a fixed offset with no daylight saving rules. Use a ZoneInfo name when the place changes its clocks in summer.
8. Useful recipes
import calendar print(calendar.monthrange(2026, 2)[1]) # 28 print(calendar.isleap(2028)) # True # Next Monday (0), never today; use 4 for Friday ahead = (0 - d.weekday()) % 7 or 7 print(d.date() + timedelta(days=ahead)) # 2026-03-16 # Age in whole years: t is today, b is the birthday t, b = date(2026, 3, 14), date(1990, 6, 1) age = t.year - b.year - ((t.month, t.day) < (b.month, b.day)) print(age) # 35 # ISO text sorts in date order print(sorted(["2026-03-14", "2025-12-01"])) # ['2025-12-01', '2026-03-14']
setup added so this can run · re-runs 8 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) def date(*_a, **_kw): print('-> date() called') return _AutoMock('date()') def timedelta(*_a, **_kw): print('-> timedelta() called') return _AutoMock('timedelta()') d = _AutoMock('d') def time(*_a, **_kw): print('-> time() called') return _AutoMock('time()') datetime = _AutoMock('datetime') timezone = _AutoMock('timezone') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone from zoneinfo import ZoneInfo except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', 'print(repr(date(2026, 3, 14))) # datetime.date(2026, 3, 14)\nprint(repr(time(9, 30))) # datetime.time(9, 30)\nprint(d.date()) # 2026-03-14\nprint(datetime.combine(date(2026, 3, 14), time(18))) # 2026-03-14 18:00:00', 'print(d.year, d.month, d.day) # 2026 3 14\nprint(d.hour, d.minute) # 9 30\nprint(d.weekday()) # 5\nprint(d.isoweekday()) # 6\nprint(d.isocalendar().week) # 11\nprint(d.replace(day=1).date()) # 2026-03-01', 'print(d.strftime("%Y-%m-%d")) # 2026-03-14\nprint(d.strftime("%d/%m/%Y")) # 14/03/2026\nprint(d.strftime("%a %d %b %Y")) # Sat 14 Mar 2026\nprint(d.strftime("%A, %B %d")) # Saturday, March 14\nprint(d.strftime("%I:%M %p")) # 09:30 AM\nprint(f"{d:%d %b, %H:%M}") # 14 Mar, 09:30\nprint(d.isoformat()) # 2026-03-14T09:30:00\nprint(d.isoformat(" ", "minutes")) # 2026-03-14 09:30', 'print(repr(datetime.strptime("14/03/2026", "%d/%m/%Y")))\n# datetime.datetime(2026, 3, 14, 0, 0)\nprint(datetime.strptime("9:05 PM", "%I:%M %p").hour) # 21\nprint(date.fromisoformat("2026-03-14")) # 2026-03-14\nprint(datetime.fromisoformat("2026-03-14T09:30Z").tzinfo) # UTC', 'for text in ["14/03/2026", "31/02/2026", "next week"]:\n try:\n print(datetime.strptime(text, "%d/%m/%Y").date())\n except ValueError:\n print("not a date:", text)', 'print(d + timedelta(days=30)) # 2026-04-13 09:30:00\nprint(d - timedelta(hours=10)) # 2026-03-13 23:30:00\nprint((date(2026, 12, 25) - d.date()).days) # 286\nprint(abs(date(2026, 1, 1) - d.date()).days) # 72\nprint(d.replace(hour=0, minute=0)) # 2026-03-14 00:00:00\nprint(date(2026, 3, 1) - timedelta(days=1)) # 2026-02-28\nprint(d < d + timedelta(seconds=1)) # True', 'from zoneinfo import ZoneInfo\n\nist = ZoneInfo("Asia/Kolkata")\nny = ZoneInfo("America/New_York")\n\nt = d.replace(tzinfo=ist) # same clock time, now aware\nprint(f"{t:%H:%M %Z}") # 09:30 IST\nprint(f"{t.astimezone(ny):%H:%M %Z}") # 00:00 EDT\nprint(t.astimezone(timezone.utc).isoformat()) # 2026-03-14T04:00:00+00:00\nprint(t.utcoffset()) # 5:30:00\nprint(t.timestamp()) # 1773460800.0\nprint(datetime.fromtimestamp(0, timezone.utc).year) # 1970', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
monthrange() returns the weekday of the first day and the number of days in the month. [1] takes the number of days. In the age recipe, the comparison is True (counted as 1) if the birthday has not come yet this year.
Common mistakes
Comparing naive and aware datetimes. If only one side has a zone, Python raises TypeError:
try: d < d.replace(tzinfo=timezone.utc) except TypeError as e: print(e) # can't compare offset-naive and offset-aware datetimes
setup added so this can run · re-runs 9 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) d = _AutoMock('d') timezone = _AutoMock('timezone') def date(*_a, **_kw): print('-> date() called') return _AutoMock('date()') def time(*_a, **_kw): print('-> time() called') return _AutoMock('time()') datetime = _AutoMock('datetime') def timedelta(*_a, **_kw): print('-> timedelta() called') return _AutoMock('timedelta()') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone from zoneinfo import ZoneInfo import calendar except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', 'print(repr(date(2026, 3, 14))) # datetime.date(2026, 3, 14)\nprint(repr(time(9, 30))) # datetime.time(9, 30)\nprint(d.date()) # 2026-03-14\nprint(datetime.combine(date(2026, 3, 14), time(18))) # 2026-03-14 18:00:00', 'print(d.year, d.month, d.day) # 2026 3 14\nprint(d.hour, d.minute) # 9 30\nprint(d.weekday()) # 5\nprint(d.isoweekday()) # 6\nprint(d.isocalendar().week) # 11\nprint(d.replace(day=1).date()) # 2026-03-01', 'print(d.strftime("%Y-%m-%d")) # 2026-03-14\nprint(d.strftime("%d/%m/%Y")) # 14/03/2026\nprint(d.strftime("%a %d %b %Y")) # Sat 14 Mar 2026\nprint(d.strftime("%A, %B %d")) # Saturday, March 14\nprint(d.strftime("%I:%M %p")) # 09:30 AM\nprint(f"{d:%d %b, %H:%M}") # 14 Mar, 09:30\nprint(d.isoformat()) # 2026-03-14T09:30:00\nprint(d.isoformat(" ", "minutes")) # 2026-03-14 09:30', 'print(repr(datetime.strptime("14/03/2026", "%d/%m/%Y")))\n# datetime.datetime(2026, 3, 14, 0, 0)\nprint(datetime.strptime("9:05 PM", "%I:%M %p").hour) # 21\nprint(date.fromisoformat("2026-03-14")) # 2026-03-14\nprint(datetime.fromisoformat("2026-03-14T09:30Z").tzinfo) # UTC', 'for text in ["14/03/2026", "31/02/2026", "next week"]:\n try:\n print(datetime.strptime(text, "%d/%m/%Y").date())\n except ValueError:\n print("not a date:", text)', 'print(d + timedelta(days=30)) # 2026-04-13 09:30:00\nprint(d - timedelta(hours=10)) # 2026-03-13 23:30:00\nprint((date(2026, 12, 25) - d.date()).days) # 286\nprint(abs(date(2026, 1, 1) - d.date()).days) # 72\nprint(d.replace(hour=0, minute=0)) # 2026-03-14 00:00:00\nprint(date(2026, 3, 1) - timedelta(days=1)) # 2026-02-28\nprint(d < d + timedelta(seconds=1)) # True', 'from zoneinfo import ZoneInfo\n\nist = ZoneInfo("Asia/Kolkata")\nny = ZoneInfo("America/New_York")\n\nt = d.replace(tzinfo=ist) # same clock time, now aware\nprint(f"{t:%H:%M %Z}") # 09:30 IST\nprint(f"{t.astimezone(ny):%H:%M %Z}") # 00:00 EDT\nprint(t.astimezone(timezone.utc).isoformat()) # 2026-03-14T04:00:00+00:00\nprint(t.utcoffset()) # 5:30:00\nprint(t.timestamp()) # 1773460800.0\nprint(datetime.fromtimestamp(0, timezone.utc).year) # 1970', 'import calendar\n\nprint(calendar.monthrange(2026, 2)[1]) # 28\nprint(calendar.isleap(2028)) # True\n\n# Next Monday (0), never today; use 4 for Friday\nahead = (0 - d.weekday()) % 7 or 7\nprint(d.date() + timedelta(days=ahead)) # 2026-03-16\n\n# Age in whole years: t is today, b is the birthday\nt, b = date(2026, 3, 14), date(1990, 6, 1)\nage = t.year - b.year - ((t.month, t.day) < (b.month, b.day))\nprint(age) # 35\n\n# ISO text sorts in date order\nprint(sorted(["2026-03-14", "2025-12-01"])) # [\'2025-12-01\', \'2026-03-14\']', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
Fix: give both a zone.
%M instead of %m. %M is minutes, so d.strftime("%Y-%M-%d") gives '2026-30-14'. Use %m for the month.
.seconds instead of total_seconds(). .seconds leaves out the days:
gap = timedelta(days=1, seconds=5) print(gap.seconds) # 5 print(gap.total_seconds()) # 86405.0
setup added so this can run · re-runs 1 earlier block on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) def timedelta(*_a, **_kw): print('-> timedelta() called') return _AutoMock('timedelta()') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
Adding "a month" as 30 days. timedelta has no months, and months are not all 30 days long: date(2026, 1, 31) + timedelta(days=30) is 2 March, not the end of February. For calendar months, use replace(month=...), or relativedelta from the dateutil package (install it with pip).
29 February in another year. date(2024, 2, 29).replace(year=2025) raises ValueError, because 2025 has no 29 February.
Comparing a datetime with a date. They are never equal:
print(d == date(2026, 3, 14)) # False print(d.date() == date(2026, 3, 14)) # True
setup added so this can run · re-runs 10 earlier blocks on this page first
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) d = _AutoMock('d') def date(*_a, **_kw): print('-> date() called') return _AutoMock('date()') def time(*_a, **_kw): print('-> time() called') return _AutoMock('time()') datetime = _AutoMock('datetime') def timedelta(*_a, **_kw): print('-> timedelta() called') return _AutoMock('timedelta()') timezone = _AutoMock('timezone') # Earlier blocks on this page that this one builds on, re-run quietly first. try: from datetime import date, time, datetime, timedelta, timezone from zoneinfo import ZoneInfo import calendar except Exception: pass _pm_earlier = [ 'from datetime import date, time, datetime, timedelta, timezone\n\nd = datetime(2026, 3, 14, 9, 30)\nprint(d) # 2026-03-14 09:30:00', 'print(repr(date(2026, 3, 14))) # datetime.date(2026, 3, 14)\nprint(repr(time(9, 30))) # datetime.time(9, 30)\nprint(d.date()) # 2026-03-14\nprint(datetime.combine(date(2026, 3, 14), time(18))) # 2026-03-14 18:00:00', 'print(d.year, d.month, d.day) # 2026 3 14\nprint(d.hour, d.minute) # 9 30\nprint(d.weekday()) # 5\nprint(d.isoweekday()) # 6\nprint(d.isocalendar().week) # 11\nprint(d.replace(day=1).date()) # 2026-03-01', 'print(d.strftime("%Y-%m-%d")) # 2026-03-14\nprint(d.strftime("%d/%m/%Y")) # 14/03/2026\nprint(d.strftime("%a %d %b %Y")) # Sat 14 Mar 2026\nprint(d.strftime("%A, %B %d")) # Saturday, March 14\nprint(d.strftime("%I:%M %p")) # 09:30 AM\nprint(f"{d:%d %b, %H:%M}") # 14 Mar, 09:30\nprint(d.isoformat()) # 2026-03-14T09:30:00\nprint(d.isoformat(" ", "minutes")) # 2026-03-14 09:30', 'print(repr(datetime.strptime("14/03/2026", "%d/%m/%Y")))\n# datetime.datetime(2026, 3, 14, 0, 0)\nprint(datetime.strptime("9:05 PM", "%I:%M %p").hour) # 21\nprint(date.fromisoformat("2026-03-14")) # 2026-03-14\nprint(datetime.fromisoformat("2026-03-14T09:30Z").tzinfo) # UTC', 'for text in ["14/03/2026", "31/02/2026", "next week"]:\n try:\n print(datetime.strptime(text, "%d/%m/%Y").date())\n except ValueError:\n print("not a date:", text)', 'print(d + timedelta(days=30)) # 2026-04-13 09:30:00\nprint(d - timedelta(hours=10)) # 2026-03-13 23:30:00\nprint((date(2026, 12, 25) - d.date()).days) # 286\nprint(abs(date(2026, 1, 1) - d.date()).days) # 72\nprint(d.replace(hour=0, minute=0)) # 2026-03-14 00:00:00\nprint(date(2026, 3, 1) - timedelta(days=1)) # 2026-02-28\nprint(d < d + timedelta(seconds=1)) # True', 'from zoneinfo import ZoneInfo\n\nist = ZoneInfo("Asia/Kolkata")\nny = ZoneInfo("America/New_York")\n\nt = d.replace(tzinfo=ist) # same clock time, now aware\nprint(f"{t:%H:%M %Z}") # 09:30 IST\nprint(f"{t.astimezone(ny):%H:%M %Z}") # 00:00 EDT\nprint(t.astimezone(timezone.utc).isoformat()) # 2026-03-14T04:00:00+00:00\nprint(t.utcoffset()) # 5:30:00\nprint(t.timestamp()) # 1773460800.0\nprint(datetime.fromtimestamp(0, timezone.utc).year) # 1970', 'import calendar\n\nprint(calendar.monthrange(2026, 2)[1]) # 28\nprint(calendar.isleap(2028)) # True\n\n# Next Monday (0), never today; use 4 for Friday\nahead = (0 - d.weekday()) % 7 or 7\nprint(d.date() + timedelta(days=ahead)) # 2026-03-16\n\n# Age in whole years: t is today, b is the birthday\nt, b = date(2026, 3, 14), date(1990, 6, 1)\nage = t.year - b.year - ((t.month, t.day) < (b.month, b.day))\nprint(age) # 35\n\n# ISO text sorts in date order\nprint(sorted(["2026-03-14", "2025-12-01"])) # [\'2025-12-01\', \'2026-03-14\']', "try:\n d < d.replace(tzinfo=timezone.utc)\nexcept TypeError as e:\n print(e) # can't compare offset-naive and offset-aware datetimes", ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
datetime.utcnow(). utcnow() is deprecated, and its result has no zone even though the time is UTC. Use datetime.now(timezone.utc).
See also
- Datetime (tutorial)
- F-strings cheat sheet
- Files and paths cheat sheet for timestamps in log files
Practice this
on practicepython.inShort exercises that run in your browser and tell you what your code did, as well as whether a test passed.
Found this useful? Share it with a friend who’s learning Python.