Skip to main content

Module 18 - Dates & Time

Working with dates and times is essential in programming. Python's datetime module provides classes for manipulating dates, times, timezones, and time intervals.


1. The datetime Module

Core Classes

ClassDescriptionExample
datetimeDate and time combined2024-01-15 10:30:45
dateDate only (year, month, day)2024-01-15
timeTime only (hour, minute, second)10:30:45
timedeltaDuration/difference between times5 days, 3 hours
timezoneTimezone informationUTC, EST
import datetime

# Current date and time
now = datetime.datetime.now()
print(now) # 2024-01-15 10:30:45.123456

# Current date only
today = datetime.date.today()
print(today) # 2024-01-15

# Current time only
current_time = datetime.datetime.now().time()
print(current_time) # 10:30:45.123456

2. Creating Date and Time Objects

2.1 datetime Objects

from datetime import datetime

# Create specific datetime
dt = datetime(2024, 1, 15, 10, 30, 45)
print(dt) # 2024-01-15 10:30:45

# With microseconds
dt = datetime(2024, 1, 15, 10, 30, 45, 123456)
print(dt) # 2024-01-15 10:30:45.123456

# Current datetime
now = datetime.now()
print(now)

# UTC datetime
utc_now = datetime.utcnow()
print(utc_now)

2.2 date Objects

from datetime import date

# Create specific date
d = date(2024, 1, 15)
print(d) # 2024-01-15

# Current date
today = date.today()
print(today)

# Access components
print(today.year) # 2024
print(today.month) # 1
print(today.day) # 15

2.3 time Objects

from datetime import time

# Create specific time
t = time(14, 30, 45)
print(t) # 14:30:45

# With microseconds
t = time(14, 30, 45, 123456)
print(t) # 14:30:45.123456

# Access components
print(t.hour) # 14
print(t.minute) # 30
print(t.second) # 45
print(t.microsecond) # 123456

3. Formatting Dates and Times

3.1 strftime() - Date to String

from datetime import datetime

now = datetime.now()

# Common formats
print(now.strftime("%Y-%m-%d")) # 2024-01-15
print(now.strftime("%d/%m/%Y")) # 15/01/2024
print(now.strftime("%B %d, %Y")) # January 15, 2024
print(now.strftime("%I:%M %p")) # 10:30 AM
print(now.strftime("%A, %B %d, %Y")) # Monday, January 15, 2024
print(now.strftime("%Y-%m-%d %H:%M:%S")) # 2024-01-15 10:30:45

Format Codes

CodeMeaningExample
%YYear (4 digits)2024
%yYear (2 digits)24
%mMonth (01-12)01
%BMonth name (full)January
%bMonth name (abbr)Jan
%dDay of month (01-31)15
%AWeekday (full)Monday
%aWeekday (abbr)Mon
%HHour (00-23)14
%IHour (01-12)02
%MMinute (00-59)30
%SSecond (00-59)45
%pAM/PMPM

3.2 strptime() - String to Date

from datetime import datetime

# Parse date strings
date_string = "2024-01-15"
dt = datetime.strptime(date_string, "%Y-%m-%d")
print(dt) # 2024-01-15 00:00:00

# Parse with time
date_string = "15/01/2024 14:30:45"
dt = datetime.strptime(date_string, "%d/%m/%Y %H:%M:%S")
print(dt) # 2024-01-15 14:30:45

# Parse various formats
formats = [
("January 15, 2024", "%B %d, %Y"),
("15-Jan-2024", "%d-%b-%Y"),
("01/15/2024", "%m/%d/%Y")
]

for date_str, fmt in formats:
dt = datetime.strptime(date_str, fmt)
print(f"{date_str}{dt}")

4. timedelta - Time Differences

timedelta represents a duration or difference between two dates/times.

Creating timedelta

from datetime import timedelta

# Create durations
delta = timedelta(days=7)
print(delta) # 7 days, 0:00:00

delta = timedelta(hours=5, minutes=30)
print(delta) # 5:30:00

delta = timedelta(weeks=2, days=3, hours=4, minutes=30, seconds=15)
print(delta) # 17 days, 4:30:15

Arithmetic with Dates

from datetime import datetime, timedelta

now = datetime.now()

# Add time
future = now + timedelta(days=7)
print(f"One week from now: {future}")

past = now - timedelta(days=30)
print(f"30 days ago: {past}")

# Subtract dates
date1 = datetime(2024, 1, 15)
date2 = datetime(2024, 1, 1)
difference = date1 - date2
print(f"Difference: {difference.days} days") # 14 days

# Calculate age
birthday = datetime(1990, 5, 15)
age = datetime.now() - birthday
age_years = age.days // 365
print(f"Age: {age_years} years")

Practical Examples

from datetime import datetime, timedelta

# Calculate deadlines
project_start = datetime(2024, 1, 15)
duration = timedelta(weeks=8)
deadline = project_start + duration
print(f"Project deadline: {deadline.strftime('%B %d, %Y')}")

# Business days calculation
def add_business_days(start_date, days):
"""Add business days (skip weekends)"""
current = start_date
while days > 0:
current += timedelta(days=1)
if current.weekday() < 5: # Monday=0, Sunday=6
days -= 1
return current

start = datetime(2024, 1, 15) # Monday
result = add_business_days(start, 10)
print(f"10 business days from {start.date()}: {result.date()}")

5. Working with Weekdays

from datetime import datetime, date

today = date.today()

# Get weekday
weekday = today.weekday() # Monday=0, Sunday=6
print(f"Weekday number: {weekday}")

# Get weekday name
weekday_name = today.strftime("%A")
print(f"Today is {weekday_name}")

# Check if weekend
if today.weekday() >= 5:
print("It's the weekend!")
else:
print("It's a weekday")

# Find next Monday
days_until_monday = (7 - today.weekday()) % 7
if days_until_monday == 0:
days_until_monday = 7
next_monday = today + timedelta(days=days_until_monday)
print(f"Next Monday: {next_monday}")

6. Timezones

Using timezone and tzinfo

from datetime import datetime, timezone, timedelta

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

# Custom timezone (EST = UTC-5)
est = timezone(timedelta(hours=-5))
now_est = datetime.now(est)
print(now_est)

# Convert between timezones
utc_time = datetime.now(timezone.utc)
est_time = utc_time.astimezone(timezone(timedelta(hours=-5)))
print(f"UTC: {utc_time}")
print(f"EST: {est_time}")
# Install: pip install pytz
import pytz
from datetime import datetime

# List all timezones
# print(pytz.all_timezones)

# Create timezone-aware datetime
utc = pytz.UTC
eastern = pytz.timezone('America/New_York')
tokyo = pytz.timezone('Asia/Tokyo')

# Current time in different zones
now_utc = datetime.now(utc)
now_eastern = now_utc.astimezone(eastern)
now_tokyo = now_utc.astimezone(tokyo)

print(f"UTC: {now_utc}")
print(f"New York: {now_eastern}")
print(f"Tokyo: {now_tokyo}")

# Localize naive datetime
naive = datetime(2024, 1, 15, 10, 30)
localized = eastern.localize(naive)
print(localized)

7. Practical Examples

7.1 Age Calculator

from datetime import datetime

def calculate_age(birthdate):
"""Calculate age in years"""
today = datetime.now().date()
age = today.year - birthdate.year
# Adjust if birthday hasn't occurred this year
if today.month < birthdate.month or \
(today.month == birthdate.month and today.day < birthdate.day):
age -= 1
return age

birthday = datetime(1990, 5, 15).date()
age = calculate_age(birthday)
print(f"Age: {age} years")

7.2 Countdown Timer

from datetime import datetime

def countdown_to_event(event_date):
"""Calculate time until event"""
now = datetime.now()
delta = event_date - now

if delta.total_seconds() < 0:
return "Event has passed!"

days = delta.days
hours, remainder = divmod(delta.seconds, 3600)
minutes, seconds = divmod(remainder, 60)

return f"{days} days, {hours} hours, {minutes} minutes, {seconds} seconds"

# New Year 2025
new_year = datetime(2025, 1, 1, 0, 0, 0)
print(f"Time until New Year: {countdown_to_event(new_year)}")

7.3 Date Range Generator

from datetime import datetime, timedelta

def date_range(start, end, step=1):
"""Generate dates between start and end"""
current = start
while current <= end:
yield current
current += timedelta(days=step)

# Generate all Mondays in January 2024
start = datetime(2024, 1, 1)
end = datetime(2024, 1, 31)

for date in date_range(start, end):
if date.weekday() == 0: # Monday
print(date.strftime("%A, %B %d"))

7.4 Working Hours Calculator

from datetime import datetime, time

def is_working_hours(dt, start_hour=9, end_hour=17):
"""Check if datetime is during working hours"""
if dt.weekday() >= 5: # Weekend
return False
work_start = time(start_hour, 0)
work_end = time(end_hour, 0)
return work_start <= dt.time() <= work_end

# Test
test_times = [
datetime(2024, 1, 15, 10, 30), # Monday 10:30 AM
datetime(2024, 1, 15, 19, 0), # Monday 7:00 PM
datetime(2024, 1, 20, 10, 30), # Saturday 10:30 AM
]

for dt in test_times:
status = "Working hours" if is_working_hours(dt) else "Outside working hours"
print(f"{dt.strftime('%A %I:%M %p')}: {status}")

8. Performance and Best Practices

Comparing Dates

from datetime import datetime

date1 = datetime(2024, 1, 15)
date2 = datetime(2024, 1, 20)

# Comparison operators
print(date1 < date2) # True
print(date1 == date2) # False
print(date1 != date2) # True

# Get maximum/minimum
dates = [datetime(2024, 1, 15), datetime(2024, 1, 10), datetime(2024, 1, 20)]
print(f"Earliest: {min(dates)}")
print(f"Latest: {max(dates)}")

Unix Timestamp

from datetime import datetime

# Current timestamp
timestamp = datetime.now().timestamp()
print(f"Timestamp: {timestamp}")

# Convert timestamp to datetime
dt = datetime.fromtimestamp(timestamp)
print(f"Datetime: {dt}")

# UTC timestamp
dt_utc = datetime.utcfromtimestamp(timestamp)
print(f"UTC: {dt_utc}")
Best Practices
  1. Always use timezone-aware datetimes for production applications
  2. Store UTC in databases, convert to local timezone for display
  3. Use date.today() for current date, not datetime.now().date()
  4. Validate date inputs to prevent invalid dates

9. Common Pitfalls

from datetime import datetime, timedelta

# ❌ Incorrect: Comparing naive and aware datetimes
naive = datetime(2024, 1, 15)
aware = datetime.now(timezone.utc)
# This raises TypeError!
# print(naive < aware)

# ✅ Correct: Both naive or both aware
naive1 = datetime(2024, 1, 15)
naive2 = datetime(2024, 1, 20)
print(naive1 < naive2) # OK

# ❌ Incorrect: Assuming 30 days per month
# Wrong for February, months with 31 days
future = datetime.now() + timedelta(days=30)

# ✅ Correct: Use dateutil.relativedelta for months
from dateutil.relativedelta import relativedelta
future = datetime.now() + relativedelta(months=1)

Summary

datetime module handles dates, times, and durations
✅ Use strftime() to format dates, strptime() to parse
timedelta represents time differences
✅ Always use timezone-aware datetimes in production
pytz library for comprehensive timezone support
✅ Store UTC in databases, display in local time


Next Steps

In Module 19, you'll learn:

  • JSON serialization and deserialization
  • Working with the json module
  • pickle for Python object serialization
  • Data persistence techniques

Practice Exercises

  1. Create a function that calculates the number of days until your next birthday
  2. Build a date formatter that converts between different date formats
  3. Write a function to find all Fridays in a given year
  4. Create a timezone converter between major world cities
  5. Build a simple reminder system that checks if an event is due
Challenge

Create a meeting scheduler that:

  • Takes meeting duration and preferred time
  • Checks availability across multiple timezones
  • Suggests next available slot during business hours (9 AM - 5 PM)
  • Accounts for weekends and holidays
  • Returns meeting time in all participant timezones