Home/Learn/Python A–Z/datetime — Dates, Timezones & Durations

datetime — Dates, Timezones & Durations

Intermediate
Stdlib Power Tools

datetime + timedelta do date arithmetic; strftime/strptime convert to and from strings; and timezone-aware UTC datetimes are the only correct choice for backends.

Overview

Every backend logs, schedules, and expires things — all datetime work. The objects: date, time, datetime, timedelta (a duration). The two directions: strftime formats a datetime INTO a string, strptime parses a string INTO a datetime (mnemonic: f = format, p = parse). The production rule that separates juniors from engineers: store and compute in UTC with timezone-aware objects (datetime.now(timezone.utc), never naive utcnow()), convert to IST only at display time.

Arithmetic with timedelta

Subtracting datetimes yields a timedelta; adding a timedelta shifts time. Great for deadlines, expiry, and "days until" features.

Dates subtract into durations
from datetime import datetime, timedelta, date

now = datetime.now()
placement_day = datetime(2026, 12, 1, 9, 0)

gap = placement_day - now                # timedelta
print(gap.days, "days left")

token_expiry = now + timedelta(hours=12)
print(now < token_expiry)                # True

# Date-only math
today = date.today()
last_monday = today - timedelta(days=today.weekday())
print("week started:", last_monday)

# timedelta knows seconds too
print(timedelta(days=1).total_seconds())  # 86400.0

# Compare timestamps naturally
t1 = datetime(2026, 7, 10, 14, 30)
t2 = datetime(2026, 7, 10, 18, 0)
print(max(t1, t2))                        # later one

Parsing, Formatting & UTC Discipline

strptime needs the exact format of the input; strftime writes any format you want. For APIs, prefer ISO-8601 (isoformat/fromisoformat). Always attach a timezone in server code.

strptime/strftime + timezone-aware UTC
from datetime import datetime, timezone, timedelta

# String -> datetime (p = parse)
s = "10/07/2026 18:30"
dt = datetime.strptime(s, "%d/%m/%Y %H:%M")

# datetime -> string (f = format)
print(dt.strftime("%d %b %Y, %I:%M %p"))   # 10 Jul 2026, 06:30 PM

# ISO-8601 — the API standard
print(dt.isoformat())                       # 2026-07-10T18:30:00
back = datetime.fromisoformat("2026-07-10T18:30:00+05:30")

# PRODUCTION RULE: aware UTC, convert at the edge
utc_now = datetime.now(timezone.utc)        # aware — has tzinfo
IST = timezone(timedelta(hours=5, minutes=30))
print(utc_now.astimezone(IST).strftime("%H:%M IST"))

# naive vs aware cannot be compared:
# datetime.now() < utc_now   -> TypeError!
# and datetime.utcnow() is deprecated — it returns a NAIVE time.

Key Points to Remember

  • 1datetime - datetime = timedelta; datetime + timedelta = datetime
  • 2strptime parses strings in, strftime formats out; ISO-8601 via isoformat()
  • 3Store/compute in aware UTC — datetime.now(timezone.utc); convert to IST only for display
  • 4Naive and aware datetimes cannot be compared — pick aware, everywhere

Interview Questions

Sign in to ask Aria
1

How do you compute the number of days between two dates?

EasyInfosys
2

Naive vs timezone-aware datetimes — why do backends standardize on aware UTC?

MediumRazorpay

Ask Aria about datetime — Dates, Timezones & Durations

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…