🎉 75% of content is free forever — Unlock Premium from $10/mo →
CW
Search courses…
💼 Servicesℹ️ About✉️ ContactView Pricing Plansfrom $10

Python Date & Time — datetime Module Mastery

Python Standard LibraryDate and Time🟢 Free Lesson

Advertisement

Python Date & Time — datetime Module Mastery

The datetime module provides classes for manipulating dates, times, and time intervals.

Learning Objectives

  • Create and manipulate date, time, and datetime objects
  • Format dates with strftime and parse with strptime
  • Calculate date differences with timedelta
  • Handle timezones correctly
  • Build real-world scheduling and timezone tools

Creating Dates and Times

from datetime import date, time, datetime, timedelta

# Date object
today = date.today()
print(today)           # 2024-01-15
print(today.year)      # 2024
print(today.month)     # 1
print(today.day)       # 15
print(today.weekday()) # 0 (Monday)

specific = date(2024, 12, 25)
print(specific)        # 2024-12-25

# Time object
noon = time(12, 0, 0)
print(noon.hour)       # 12
print(noon.minute)     # 0
print(noon.second)     # 0

# Datetime object
now = datetime.now()
specific_dt = datetime(2024, 6, 15, 14, 30, 0)
print(now)             # 2024-01-15 14:30:00.123456

# From timestamp
dt_from_timestamp = datetime.fromtimestamp(1700000000)
print(dt_from_timestamp)

# Combine date and time
dt = datetime.combine(date.today(), time(12, 0))
print(dt)

# Extract components
dt = datetime(2024, 6, 15, 14, 30, 45)
print(dt.date())       # 2024-06-15
print(dt.time())       # 14:30:45

datetime vs date vs time

from datetime import date, time, datetime

# date: calendar date only
d = date(2024, 6, 15)
print(f"Date: {d}")
print(f"Year: {d.year}, Month: {d.month}, Day: {d.day}")

# time: time of day only
t = time(14, 30, 45, 123456)
print(f"Time: {t}")
print(f"Hour: {t.hour}, Minute: {t.minute}, Second: {t.second}, Microsecond: {t.microsecond}")

# datetime: date and time combined
dt = datetime(2024, 6, 15, 14, 30, 45, 123456)
print(f"Datetime: {dt}")
print(f"Date: {dt.date()}, Time: {dt.time()}")

Formatting Dates

now = datetime(2024, 6, 15, 14, 30, 45)

# strftime — format datetime to string
print(now.strftime("%Y-%m-%d"))           # 2024-06-15
print(now.strftime("%B %d, %Y"))          # June 15, 2024
print(now.strftime("%I:%M %p"))           # 02:30 PM
print(now.strftime("%Y-%m-%d %H:%M:%S"))  # 2024-06-15 14:30:45
print(now.strftime("%a, %b %d %Y"))       # Sat, Jun 15 2024
print(now.strftime("%Y-%m-%dT%H:%M:%SZ")) # ISO 8601 format

# Common format codes
# %Y — Year (4 digits)    %y — Year (2 digits)
# %m — Month (01-12)      %B — Full month name
# %b — Abbreviated month  %d — Day (01-31)
# %H — Hour (00-23)       %I — Hour (01-12)
# %M — Minute (00-59)     %S — Second (00-59)
# %A — Full weekday name  %a — Abbreviated weekday
# %p — AM/PM              %j — Day of year (001-366)
# %U — Week number (Sun)  %W — Week number (Mon)
# %Z — Timezone name      %z — UTC offset

Format Codes Reference Table

CodeMeaningExample
%Y4-digit year2024
%y2-digit year24
%mMonth (zero-padded)06
%dDay (zero-padded)15
%HHour (24-hour)14
%IHour (12-hour)02
%MMinute30
%SSecond45
%pAM/PMPM
%AWeekday nameSaturday
%BMonth nameJune
%bAbbreviated monthJun
%aAbbreviated weekdaySat
%jDay of year167
%UWeek number (Sun)24
%WWeek number (Mon)24
%ZTimezone nameUTC
%zUTC offset+0000
%fMicrosecond123456
%%Literal %%

Parsing Dates

from datetime import datetime

# strptime — parse string to datetime
date_str = "2024-06-15"
dt = datetime.strptime(date_str, "%Y-%m-%d")
print(dt)  # 2024-06-15 00:00:00

# Flexible parsing
dt = datetime.strptime("15/06/2024 14:30", "%d/%m/%Y %H:%M")
dt = datetime.strptime("June 15, 2024", "%B %d, %Y")
dt = datetime.strptime("15-Jun-2024", "%d-%b-%Y")
dt = datetime.strptime("2024-06-15T14:30:00", "%Y-%m-%dT%H:%M:%S")

# Handle multiple formats
def parse_date(date_string):
    formats = [
        "%Y-%m-%d",
        "%d/%m/%Y",
        "%B %d, %Y",
        "%m-%d-%Y",
        "%Y/%m/%d",
    ]
    for fmt in formats:
        try:
            return datetime.strptime(date_string, fmt)
        except ValueError:
            continue
    raise ValueError(f"Cannot parse date: {date_string}")

print(parse_date("2024-06-15"))       # 2024-06-15 00:00:00
print(parse_date("15/06/2024"))       # 2024-06-15 00:00:00
print(parse_date("June 15, 2024"))    # 2024-06-15 00:00:00

Parsing Examples

from datetime import datetime

# ISO 8601 format
dt = datetime.fromisoformat("2024-06-15T14:30:45")
print(dt)  # 2024-06-15 14:30:45

# With timezone
dt = datetime.fromisoformat("2024-06-15T14:30:45+05:30")
print(dt)  # 2024-06-15 14:30:45+05:30

# Common formats
formats = [
    "%Y-%m-%d",          # 2024-06-15
    "%Y/%m/%d",          # 2024/06/15
    "%d-%m-%Y",          # 15-06-2024
    "%d/%m/%Y",          # 15/06/2024
    "%B %d, %Y",         # June 15, 2024
    "%b %d, %Y",         # Jun 15, 2024
    "%Y-%m-%d %H:%M:%S", # 2024-06-15 14:30:45
    "%Y-%m-%dT%H:%M:%S", # 2024-06-15T14:30:45
]

test_dates = [
    "2024-06-15",
    "15/06/2024",
    "June 15, 2024",
    "2024-06-15 14:30:45",
]

for date_str in test_dates:
    for fmt in formats:
        try:
            dt = datetime.strptime(date_str, fmt)
            print(f"Parsed '{date_str}' with '{fmt}': {dt}")
            break
        except ValueError:
            continue

timedelta — Date Arithmetic

from datetime import timedelta, date, datetime

today = date.today()

# Add/subtract days
tomorrow = today + timedelta(days=1)
next_week = today + timedelta(weeks=1)
next_month = today + timedelta(days=30)
next_year = today + timedelta(days=365)
in_two_hours = datetime.now() + timedelta(hours=2)

# Subtract dates
birthday = date(1990, 5, 15)
age = today - birthday
print(f"You are {age.days} days old")
print(f"That's about {age.days // 365} years")

# Time difference
start = datetime.now()
import time
time.sleep(2)
elapsed = datetime.now() - start
print(f"Elapsed: {elapsed.total_seconds():.1f} seconds")

# timedelta components
td = timedelta(days=1, hours=2, minutes=30)
print(td.days)        # 1
print(td.seconds)     # 9000 (2*3600 + 30*60)
print(td.total_seconds())  # 99000.0

# Business days calculation
def add_business_days(start_date, days):
    current = start_date
    added = 0
    while added < days:
        current += timedelta(days=1)
        if current.weekday() < 5:  # Monday=0, Friday=4
            added += 1
    return current

next_business = add_business_days(date.today(), 5)
print(f"5 business days from now: {next_business}")

timedelta Arithmetic

from datetime import timedelta, date, datetime

# Basic arithmetic
td1 = timedelta(days=1)
td2 = timedelta(hours=12)
td3 = timedelta(minutes=30)

# Addition
total = td1 + td2 + td3
print(f"Total: {total}")  # 1 day, 12:30:00
print(f"Total seconds: {total.total_seconds()}")  # 131400.0

# Subtraction
diff = td1 - td2
print(f"Difference: {diff}")  # 0:12:00

# Multiplication
doubled = td1 * 2
print(f"Doubled: {doubled}")  # 2 days

# Comparison
print(td1 > td2)  # True
print(td1 < timedelta(days=2))  # True

# Convert to different units
td = timedelta(days=1, hours=2, minutes=30, seconds=15)
print(f"Days: {td.days}")
print(f"Hours: {td.seconds // 3600}")
print(f"Minutes: {(td.seconds % 3600) // 60}")
print(f"Seconds: {td.seconds % 60}")
print(f"Total hours: {td.total_seconds() / 3600}")

Timezones

from datetime import datetime, timezone, timedelta

# UTC
utc_now = datetime.now(timezone.utc)
print(utc_now)

# Specific timezone using timedelta
est = timezone(timedelta(hours=-5))
eastern_now = datetime.now(est)
print(eastern_now)

# Make a naive datetime timezone-aware
naive = datetime(2024, 6, 15, 12, 0)
aware = naive.replace(tzinfo=timezone.utc)
print(aware)

# Convert between timezones (Python 3.9+)
from zoneinfo import ZoneInfo

tokyo_tz = ZoneInfo("Asia/Tokyo")
tokyo_now = datetime.now(tokyo_tz)
print(f"Tokyo: {tokyo_now}")

ny_tz = ZoneInfo("America/New_York")
ny_now = tokyo_now.astimezone(ny_tz)
print(f"New York: {ny_now}")

# List available timezones
import zoneinfo
all_zones = sorted(zoneinfo.available_timezones())
print(f"Total timezones: {len(all_zones)}")

Timezone Conversion

from datetime import datetime
from zoneinfo import ZoneInfo

def convert_timezone(dt, from_tz, to_tz):
    """Convert datetime from one timezone to another."""
    source_tz = ZoneInfo(from_tz)
    target_tz = ZoneInfo(to_tz)

    # Make timezone-aware if naive
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=source_tz)

    # Convert
    return dt.astimezone(target_tz)

# Usage
meeting = datetime(2024, 6, 15, 14, 0)
tokyo_time = convert_timezone(meeting, "America/New_York", "Asia/Tokyo")
print(f"Meeting in Tokyo: {tokyo_time.strftime('%Y-%m-%d %H:%M %Z')}")

Timezone Awareness

from datetime import datetime, timezone
from zoneinfo import ZoneInfo

# Naive datetime (no timezone info)
naive = datetime(2024, 6, 15, 12, 0)
print(naive.tzinfo)  # None

# Timezone-aware datetime
aware = datetime(2024, 6, 15, 12, 0, tzinfo=timezone.utc)
print(aware.tzinfo)  # UTC

# Convert naive to aware
eastern = ZoneInfo("America/New_York")
aware_eastern = naive.replace(tzinfo=eastern)
print(aware_eastern.tzinfo)  # America/New_York

# Convert between timezones
utc_time = datetime.now(timezone.utc)
tokyo_time = utc_time.astimezone(ZoneInfo("Asia/Tokyo"))
print(f"UTC: {utc_time}")
print(f"Tokyo: {tokyo_time}")

# Naive vs aware comparison
# naive == aware  # TypeError: can't compare naive and aware datetimes

Real-World: Scheduler

from datetime import datetime, timedelta
from zoneinfo import ZoneInfo

class EventScheduler:
    def __init__(self, timezone="UTC"):
        self.events = []
        self.tz = ZoneInfo(timezone)

    def add_event(self, title, start_time, duration_minutes=60, recurring=False):
        event = {
            "title": title,
            "start": start_time,
            "duration": timedelta(minutes=duration_minutes),
            "recurring": recurring,
            "id": len(self.events)
        }
        self.events.append(event)
        return event["id"]

    def get_upcoming(self, hours=24):
        now = datetime.now(self.tz)
        cutoff = now + timedelta(hours=hours)
        return [e for e in self.events if now <= e["start"] <= cutoff]

    def get_events_on_date(self, target_date):
        return [
            e for e in self.events
            if e["start"].date() == target_date
        ]

    def time_until_event(self, event_id):
        now = datetime.now(self.tz)
        event = self.events[event_id]
        delta = event["start"] - now
        if delta.total_seconds() < 0:
            return "Event has passed"
        hours, remainder = divmod(int(delta.total_seconds()), 3600)
        minutes, seconds = divmod(remainder, 60)
        return f"{hours}h {minutes}m {seconds}s"

# Usage
scheduler = EventScheduler("America/New_York")
now = datetime.now(ZoneInfo("America/New_York"))

scheduler.add_event("Team Meeting", now + timedelta(hours=2))
scheduler.add_event("Lunch", now + timedelta(hours=4, minutes=30))
scheduler.add_event("Code Review", now + timedelta(days=1))

print(f"Upcoming: {len(scheduler.get_upcoming(hours=12))} events")
print(f"Time until meeting: {scheduler.time_until_event(0)}")

Real-World: Age Calculator

from datetime import date

def calculate_age(birth_date):
    """Calculate precise age in years, months, and days."""
    today = date.today()

    years = today.year - birth_date.year
    months = today.month - birth_date.month
    days = today.day - birth_date.day

    if days < 0:
        months -= 1
        # Get days in previous month
        import calendar
        prev_month = today.month - 1 or 12
        prev_year = today.year if today.month > 1 else today.year - 1
        days += calendar.monthrange(prev_year, prev_month)[1]

    if months < 0:
        years -= 1
        months += 12

    return years, months, days

# Usage
birthday = date(1990, 5, 15)
years, months, days = calculate_age(birthday)
print(f"Age: {years} years, {months} months, {days} days")

# Days until next birthday
def days_until_birthday(birth_date):
    today = date.today()
    next_birthday = birth_date.replace(year=today.year)
    if next_birthday < today:
        next_birthday = next_birthday.replace(year=today.year + 1)
    return (next_birthday - today).days

print(f"Days until birthday: {days_until_birthday(birthday)}")

Common Mistakes

from datetime import datetime, timedelta, timezone

# Mistake 1: Naive vs aware datetime
naive = datetime.now()
aware = datetime.now(timezone.utc)
# naive.astimezone(aware.tzinfo)  # Fails in Python 3.9+
aware.astimezone(timezone.utc)    # Works

# Fix: always use timezone-aware datetimes
dt = datetime.now(timezone.utc)

# Mistake 2: Mutable datetime
dt = datetime(2024, 6, 15)
# dt.replace() returns new object, doesn't modify in place
new_dt = dt.replace(day=16)

# Mistake 3: Timedelta doesn't have months/years
# timedelta(days=30) != 1 month
# timedelta(days=365) != 1 year

# Fix: use dateutil.relativedelta for calendar-aware math
from dateutil.relativedelta import relativedelta
dt = datetime(2024, 1, 31)
dt + relativedelta(months=1)  # 2024-02-29 (handles leap years)

# Mistake 4: Timezone conversion without awareness
from zoneinfo import ZoneInfo
dt_naive = datetime(2024, 6, 15, 12, 0)
# dt_naive.replace(tzinfo=ZoneInfo("US/Eastern"))  # Wrong! Assumes local time

# Fix: localize properly
from datetime import timezone
dt_utc = datetime(2024, 6, 15, 12, 0, tzinfo=timezone.utc)
dt_eastern = dt_utc.astimezone(ZoneInfo("US/Eastern"))

# Mistake 5: Comparing naive and aware datetimes
# naive_dt == aware_dt  # TypeError!

Key Takeaways

  1. date for calendar dates, time for times, datetime for both
  2. strftime() formats to string, strptime() parses from string
  3. timedelta handles date arithmetic
  4. Always use timezone.utc for timezone-aware datetimes
  5. Use zoneinfo (Python 3.9+) for timezone support
  6. Use dateutil.relativedelta for calendar-aware arithmetic (months, years)
  7. Pre-compile format strings for repeated parsing
  8. Use fromisoformat() for ISO 8601 parsing
  9. Naive datetimes cannot be compared with aware datetimes
  10. Always validate timezone conversions with real-world examples

Premium Content

Python Date & Time — datetime Module Mastery

Unlock this lesson and 900+ advanced tutorials with a Premium plan.

🎯End-to-end Projects
💼Interview Prep
📜Certificates
🤝Community Access

Already a member? Log in

Need Expert Python Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement