Dates & Times

Working with dates and times is an essential skill in Python programming, especially for applications involving scheduling, logging events, or time-based calculations. While it might seem straightforward, managing dates and times can quickly become complex due to different formats, time zones, and daylight saving changes. This lesson introduces you to Python's datetime module—the powerful and versatile toolkit for handling date and time data.

By the end of this lesson, you will understand how to create, manipulate, and format dates and times, compare them, and perform arithmetic operations on them. Let's dive in!

Why Python's datetime Module?

Python's built-in datetime module offers classes for manipulating dates and times in both simple and complex ways. It supports:

  • Representing dates, times, or both together
  • Timezone-aware and naive datetime objects
  • Parsing and formatting dates and times in human-readable strings
  • Performing arithmetic operations like addition and subtraction

Before datetime, developers manually parsed strings or used less consistent methods, making date-time handling error-prone. With datetime, Python provides a standardized, reliable API.

Core Classes in datetime

The module contains several classes, but the key ones you'll use are:

  • date: Handles calendar dates (year, month, day)
  • time: Handles time independent of any date (hour, minute, second, microsecond)
  • datetime: Combines date and time into one object
  • timedelta: Represents a duration, the difference between two dates or times
  • timezone: For handling timezone-aware datetime objects

Let's explore these classes practically.

Getting Started: Importing datetime

To access the module's features, import it as follows:

📌 Deep Dive: Importing datetime

PYTHON
import datetime

Alternatively, you can import specific classes for convenience:

📌 Deep Dive: Importing Specific Classes

PYTHON
from datetime import date, time, datetime, timedelta

Working with Dates

The date class represents a calendar date. You can create a date object by specifying the year, month, and day.

📌 Deep Dive: Creating and Using date Objects

PYTHON
from datetime import date

# Create a date object for July 4, 2024
independence_day = date(2024, 7, 4)

print(independence_day)       # 2024-07-04
print(independence_day.year)  # 2024
print(independence_day.month) # 7
print(independence_day.day)   # 4

# Get today's date
today = date.today()
print(today)
Output
2024-07-04 2024 7 4 2024-06-15

Note: The date.today() method returns the current local date.

Working with Times

The time class allows you to represent a specific time independent of any date. It supports hour, minute, second, microsecond, and timezone info.

📌 Deep Dive: Creating and Using time Objects

PYTHON
from datetime import time

# Create a time object for 2:30:45 PM
afternoon = time(14, 30, 45)

print(afternoon)          # 14:30:45
print(afternoon.hour)     # 14
print(afternoon.minute)   # 30
print(afternoon.second)   # 45
print(afternoon.microsecond)  # 0 (default)
Output
14:30:45 14 30 45 0

The datetime Class: Combining Date & Time

The datetime class is the most commonly used class because it combines a date and a time into one object. This is useful for timestamps, event logging, or any context where date and time go hand-in-hand.

📌 Deep Dive: Creating and Using datetime Objects

PYTHON
from datetime import datetime

# Create a datetime object for January 1, 2023 at 12:00 noon
new_year = datetime(2023, 1, 1, 12, 0, 0)

print(new_year)           # 2023-01-01 12:00:00
print(new_year.year)      # 2023
print(new_year.month)     # 1
print(new_year.day)       # 1
print(new_year.hour)      # 12
print(new_year.minute)    # 0
print(new_year.second)    # 0

# Get the current date and time
now = datetime.now()
print(now)
Output
2023-01-01 12:00:00 2023 1 1 12 0 0 2024-06-15 10:23:54.123456

Formatting Dates and Times: strftime and strptime

Often, you need to convert dates and times to strings in a readable or specific format or parse strings into datetime objects. The strftime method converts datetime objects to strings, and strptime parses strings into datetime objects.

📌 Deep Dive: Formatting and Parsing Dates

PYTHON
from datetime import datetime

now = datetime.now()

# Format datetime to string
formatted = now.strftime("%A, %B %d, %Y at %I:%M %p")
print("Formatted date:", formatted)

# Parse string back to datetime
date_string = "21 June, 2024 15:30"
parsed_date = datetime.strptime(date_string, "%d %B, %Y %H:%M")
print("Parsed datetime:", parsed_date)
Output
Formatted date: Saturday, June 15, 2024 at 10:23 AM Parsed datetime: 2024-06-21 15:30:00

Here are some common formatting directives for strftime and strptime:

Common DateTime Format Codes
DirectiveDescription
%YYear with century (e.g., 2024)
%mMonth as zero-padded decimal (01-12)
%dDay of the month (01-31)
%HHour (24-hour clock) (00-23)
%IHour (12-hour clock) (01-12)
%MMinute (00-59)
%SSecond (00-59)
%pAM or PM
%AFull weekday name (e.g., Monday)
%BFull month name (e.g., January)

Performing Date and Time Arithmetic with timedelta

The timedelta class represents a duration or difference between two dates or times. You can add or subtract timedeltas to manipulate date or datetime objects.

📌 Deep Dive: Using timedelta for Date Arithmetic

PYTHON
from datetime import datetime, timedelta

# Current datetime
now = datetime.now()

# 10 days from now
ten_days_later = now + timedelta(days=10)
print("10 days later:", ten_days_later)

# 3 hours ago
three_hours_ago = now - timedelta(hours=3)
print("3 hours ago:", three_hours_ago)

# Difference between two dates
new_year = datetime(2025, 1, 1)
diff = new_year - now
print(f"Days until New Year 2025: {diff.days}")
print(f"Seconds until New Year 2025: {diff.total_seconds():.0f}")
Output
10 days later: 2024-06-25 10:23:54.123456 3 hours ago: 2024-06-15 07:23:54.123456 Days until New Year 2025: 200 Seconds until New Year 2025: 17280000

Time Zones and Aware vs Naive Objects

By default, datetime objects are "naive" — they do not contain timezone information. This is usually fine for many applications, but when working across time zones or with UTC, you need "aware" datetime objects.

Python's datetime.timezone class helps you create timezone-aware datetime objects.

📌 Deep Dive: Creating Timezone-Aware Datetimes

PYTHON
from datetime import datetime, timezone, timedelta

# UTC timezone
utc_now = datetime.now(timezone.utc)
print("Current UTC time:", utc_now)

# Create timezone for UTC+2 hours
utc_plus_two = timezone(timedelta(hours=2))

# Local time with UTC+2 offset
local_time = datetime.now(utc_plus_two)
print("Local time (UTC+2):", local_time)
Output
Current UTC time: 2024-06-15 08:23:54.123456+00:00 Local time (UTC+2): 2024-06-15 10:23:54.123456+02:00

💡 Timezone Tips

Handling time zones can be tricky. For comprehensive timezone support (including daylight saving time), consider using third-party libraries like pytz or Python 3.9+'s zoneinfo module.

Comparing Dates and Times

Python allows direct comparison of date, time, and datetime objects using the usual comparison operators (<, <=, >, >=, ==, !=).

📌 Deep Dive: Comparing Dates and Times

PYTHON
from datetime import date

d1 = date(2024, 6, 15)
d2 = date(2024, 12, 25)

if d1 < d2:
    print("d1 is earlier than d2")
else:
    print("d1 is the same or later than d2")
Output
d1 is earlier than d2

Note that comparing naive and aware datetime objects will raise an error. Always ensure consistency when comparing.

Parsing Dates from User Input

When accepting dates from users (command line input, files, APIs), the input will often be strings. Use datetime.strptime() to safely parse these strings into datetime objects.

📌 Deep Dive: Parsing User Input

PYTHON
from datetime import datetime

user_input = "2024-06-15 14:45:00"
try:
    user_date = datetime.strptime(user_input, "%Y-%m-%d %H:%M:%S")
    print("Parsed datetime:", user_date)
except ValueError:
    print("Invalid date format. Please use YYYY-MM-DD HH:MM:SS")
Output
Parsed datetime: 2024-06-15 14:45:00

Common Pitfalls and Tips

  • Beware of naive vs aware datetime: Mixing timezone-aware and naive datetimes in comparisons or arithmetic causes errors.
  • Use UTC internally: For apps involving multiple time zones, store and operate in UTC, then convert for display.
  • Always validate user input: Use try-except blocks around strptime to handle unexpected formats gracefully.
  • Remember that months and days are one-indexed: January is month 1, not 0.
Architecture of Dates & Times
Architecture of Dates & Times

Summary

Handling dates and times in Python is straightforward once you understand the datetime module's classes and methods. You can:

  • Create date, time, and combined datetime objects
  • Get the current date and time
  • Format dates and times into readable strings and parse strings back
  • Do arithmetic with date/time differences using timedelta
  • Work with time zones and create timezone-aware datetime objects
  • Compare dates and times using comparison operators

With these skills, you can confidently build robust, time-aware applications.

💡 Next Steps

Explore modules like calendar for advanced calendar operations, or third-party libraries such as dateutil and pytz for enhanced timezone and parsing capabilities.