Web Analytics

Working with Dates and Times

Intermediate ~25 min read

The datetime module is Python's Swiss Army knife for dates and times. Whether you're calculating deadlines, formatting timestamps for display, parsing date strings from user input, or finding the difference between two dates - this module has you covered. It's essential for scheduling, logging, data analysis, and virtually any application that deals with time!

Creating and Using datetime Objects

The datetime module provides several classes: date for dates only, time for times only, and datetime for both combined. You can create objects representing the current moment or specific dates, then access individual components like year, month, day, hour, and more.

Output
Click Run to execute your code
datetime vs date vs time: Use date when you only need the date (no time component), time for time without a date, and datetime when you need both. The datetime.now() method includes microseconds, while date.today() gives you just the date.

Formatting Dates with strftime()

The strftime() method (string format time) converts datetime objects into human-readable strings using format codes. Each code starts with % and represents a date/time component. This is essential for displaying dates in your application or generating formatted output for users.

Output
Click Run to execute your code
Common Format Patterns:
%Y-%m-%d - ISO format (2024-03-15)
%m/%d/%Y - US format (03/15/2024)
%d/%m/%Y - UK/EU format (15/03/2024)
%B %d, %Y - Full date (March 15, 2024)
%I:%M %p - 12-hour time (03:30 PM)

Date Arithmetic with timedelta

The timedelta class represents a duration - the difference between two dates or times. You can add or subtract timedeltas from dates to calculate future or past dates, find the difference between two dates, or measure elapsed time. This is crucial for scheduling, expiration dates, and age calculations.

Output
Click Run to execute your code
timedelta Limitations: timedelta only supports days, seconds, microseconds, milliseconds, minutes, hours, and weeks. It doesn't have months or years because they're not fixed durations (months have 28-31 days, years have 365-366). For month/year arithmetic, use the dateutil library or manually calculate using replace().

Parsing Date Strings with strptime()

The strptime() method (string parse time) does the opposite of strftime - it converts a string into a datetime object. This is essential when reading dates from files, APIs, or user input. The format string must match the input string's structure exactly.

Output
Click Run to execute your code

Common Mistakes

1. Confusing strftime and strptime

# strftime = format datetime TO string
# strptime = parse string TO datetime

from datetime import datetime

now = datetime.now()

# Wrong - strptime expects a string, not datetime!
result = datetime.strptime(now, "%Y-%m-%d")  # TypeError!

# Correct usage:
formatted = now.strftime("%Y-%m-%d")  # datetime -> string
parsed = datetime.strptime("2024-03-15", "%Y-%m-%d")  # string -> datetime

2. Format string doesn't match input

from datetime import datetime

# Wrong - format doesn't match string!
date_str = "15/03/2024"
parsed = datetime.strptime(date_str, "%Y-%m-%d")  # ValueError!

# The string is DD/MM/YYYY, not YYYY-MM-DD
# Correct:
parsed = datetime.strptime(date_str, "%d/%m/%Y")

# Common mistake: US vs UK format
us_date = "03/15/2024"  # MM/DD/YYYY
uk_date = "15/03/2024"  # DD/MM/YYYY
# These need different format strings!

3. Comparing dates with timezones

from datetime import datetime, timezone

# Naive datetime (no timezone)
naive = datetime.now()

# Aware datetime (has timezone)
aware = datetime.now(timezone.utc)

# Wrong - can't compare naive and aware!
if naive > aware:  # TypeError!
    print("naive is later")

# Fix: Make both naive or both aware
naive_utc = datetime.utcnow()  # Both naive
aware_utc = datetime.now(timezone.utc)  # Keep both aware

4. Calculating months/years with timedelta

from datetime import datetime, timedelta

now = datetime.now()

# Wrong - timedelta doesn't have months!
# one_month = timedelta(months=1)  # TypeError!

# Approximation (not always accurate)
one_month_approx = timedelta(days=30)

# Better - use replace() for month arithmetic
def add_months(dt, months):
    month = dt.month + months
    year = dt.year + (month - 1) // 12
    month = (month - 1) % 12 + 1
    day = min(dt.day, [31,28,31,30,31,30,31,31,30,31,30,31][month-1])
    return dt.replace(year=year, month=month, day=day)

# Or use dateutil library
# from dateutil.relativedelta import relativedelta
# next_month = now + relativedelta(months=1)

5. Forgetting to import the right class

# Wrong - datetime module vs datetime class confusion
import datetime

# This is verbose
now = datetime.datetime.now()
today = datetime.date.today()
delta = datetime.timedelta(days=1)

# Better - import specific classes
from datetime import datetime, date, timedelta

now = datetime.now()
today = date.today()
delta = timedelta(days=1)

Exercise: Age Calculator

Task: Create an age calculator that works with birthdays.

Requirements:

  • Parse a birthday string in format "YYYY-MM-DD"
  • Calculate the person's age in years
  • Determine how many days until their next birthday
  • Display the next birthday date formatted as "Month Day, Year"
Output
Click Run to execute your code
Show Solution
from datetime import datetime, date

def calculate_age(birthday_str):
    """Calculate age and days until next birthday."""
    # Parse the birthday
    birthday = datetime.strptime(birthday_str, "%Y-%m-%d").date()
    today = date.today()

    # Calculate age
    age = today.year - birthday.year
    # Adjust if birthday hasn't occurred this year
    if (today.month, today.day) < (birthday.month, birthday.day):
        age -= 1

    # Calculate next birthday
    next_birthday = birthday.replace(year=today.year)
    if next_birthday < today:
        next_birthday = birthday.replace(year=today.year + 1)

    days_until = (next_birthday - today).days

    # Format the next birthday
    next_bday_formatted = next_birthday.strftime("%B %d, %Y")

    return age, days_until, next_bday_formatted

# Test it
birthday = "1990-06-15"
age, days_until, next_bday = calculate_age(birthday)
print(f"Birthday: {birthday}")
print(f"Age: {age} years")
print(f"Days until next birthday: {days_until}")
print(f"Next birthday: {next_bday}")

Summary

  • datetime classes: date, time, datetime, timedelta
  • Current time: datetime.now(), date.today()
  • Components: Access .year, .month, .day, .hour, etc.
  • strftime(): Format datetime to string - now.strftime("%Y-%m-%d")
  • strptime(): Parse string to datetime - datetime.strptime(str, format)
  • timedelta: Duration for date arithmetic - timedelta(days=7)
  • Date math: tomorrow = today + timedelta(days=1)
  • Date difference: (date2 - date1).days gives days between

What's Next?

Now that you can work with dates, let's explore Python's math module for mathematical operations beyond basic arithmetic - including trigonometry, logarithms, factorials, and more advanced calculations!