Python DateTime
Comprehensive guide to date and time manipulation in Python using the datetime module.
Python DateTime Cheatsheet
Comprehensive guide to date and time manipulation in Python using the datetime module.
Overview
Python's datetime module provides classes for manipulating dates and times, from simple date arithmetic to complex timezone-aware operations. It's essential for timestamps, scheduling, data analysis, and logging.
flowchart LR
subgraph datetime_module["datetime Module"]
A[date]
B[time]
C[datetime]
D[timedelta]
E[timezone]
end
subgraph operations["Common Operations"]
F[Parse Strings]
G[Format Output]
H[Arithmetic]
I[Timezone Convert]
J[Timestamps]
end
C --> F
C --> G
C --> H
C --> I
C --> J
D --> H
E --> I
Installation
The datetime module is part of Python's standard library - no installation required.
from datetime import datetime, date, time, timedelta, timezone
datetime Module Basics
Key Concepts
- datetime - Combines date and time into a single object
- date - Represents a date (year, month, day) without time
- time - Represents time (hour, minute, second, microsecond) without date
- timedelta - Represents a duration or difference between two dates/times
- strptime - Parse a string into a datetime object
- strftime - Format a datetime object as a string
flowchart TD
A[String] -->|strptime| B[datetime object]
B -->|strftime| C[Formatted String]
B -->|timedelta| D[New datetime]
B -->|timestamp| E[Unix Timestamp]
E -->|fromtimestamp| B
Common Patterns
from datetime import datetime, date, time, timedelta, timezone
# Get current date and time
now = datetime.now() # Local time
utc_now = datetime.now(timezone.utc) # UTC time (aware; utcnow() is deprecated since 3.12)
today = date.today() # Current date only
# Create specific datetime
dt = datetime(2024, 12, 25, 14, 30, 0) # Christmas 2024, 2:30 PM
d = date(2024, 12, 25) # Date only
t = time(14, 30, 0) # Time only
# Parse string to datetime (strptime)
dt = datetime.strptime('2024-12-25 14:30:00', '%Y-%m-%d %H:%M:%S')
# Format datetime to string (strftime)
formatted = dt.strftime('%d/%m/%Y %H:%M') # '25/12/2024 14:30'
# Time differences with timedelta
delta = timedelta(days=7, hours=3, minutes=30)
next_week = now + delta
Examples
Getting Current Date and Time
from datetime import datetime, date, time
# Current datetime
now = datetime.now()
print(f"Now: {now}") # 2024-03-15 10:30:45.123456
print(f"Date: {now.date()}") # 2024-03-15
print(f"Time: {now.time()}") # 10:30:45.123456
# Access individual components
print(f"Year: {now.year}") # 2024
print(f"Month: {now.month}") # 3
print(f"Day: {now.day}") # 15
print(f"Hour: {now.hour}") # 10
print(f"Minute: {now.minute}") # 30
print(f"Second: {now.second}") # 45
print(f"Microsecond: {now.microsecond}")# 123456
print(f"Weekday: {now.weekday()}") # 4 (Friday, 0=Monday)
Parsing Strings with strptime
from datetime import datetime
# Common date formats
dt1 = datetime.strptime('2024-03-15', '%Y-%m-%d')
dt2 = datetime.strptime('15/03/2024', '%d/%m/%Y')
dt3 = datetime.strptime('March 15, 2024', '%B %d, %Y')
dt4 = datetime.strptime('2024-03-15T10:30:00', '%Y-%m-%dT%H:%M:%S')
# With time component
dt5 = datetime.strptime('15-Mar-2024 10:30:45', '%d-%b-%Y %H:%M:%S')
# 12-hour format with AM/PM
dt6 = datetime.strptime('03/15/2024 02:30 PM', '%m/%d/%Y %I:%M %p')
print(dt6) # 2024-03-15 14:30:00
Formatting with strftime
from datetime import datetime
now = datetime.now()
# Common output formats
print(now.strftime('%Y-%m-%d')) # 2024-03-15
print(now.strftime('%d/%m/%Y')) # 15/03/2024
print(now.strftime('%B %d, %Y')) # March 15, 2024
print(now.strftime('%A, %d %B %Y')) # Friday, 15 March 2024
print(now.strftime('%H:%M:%S')) # 10:30:45
print(now.strftime('%I:%M %p')) # 10:30 AM
print(now.strftime('%Y-%m-%dT%H:%M:%S')) # ISO 8601 format
# Combined formats
print(now.strftime('%d %b %Y, %H:%M')) # 15 Mar 2024, 10:30
print(now.strftime('%a %d/%m/%y %H:%M')) # Fri 15/03/24 10:30
Working with timedelta
from datetime import datetime, timedelta
now = datetime.now()
# Create timedeltas
one_day = timedelta(days=1)
one_week = timedelta(weeks=1)
two_hours = timedelta(hours=2)
complex_delta = timedelta(days=5, hours=3, minutes=30, seconds=45)
# Add and subtract
tomorrow = now + one_day
yesterday = now - one_day
next_week = now + one_week
two_hours_ago = now - two_hours
# Calculate differences
future_date = datetime(2024, 12, 31)
days_until = future_date - now
print(f"Days until: {days_until.days}")
print(f"Total seconds: {days_until.total_seconds()}")
# Multiply and divide timedeltas
double_delta = one_week * 2 # 14 days
half_day = one_day / 2 # 12 hours
Timezone Handling
Key Concepts
- Naive datetime - No timezone information attached
- Aware datetime - Contains timezone information
- UTC - Coordinated Universal Time, the standard reference
- timezone - Class for creating fixed offset timezones
- zoneinfo - Python 3.9+ module for IANA timezone database
flowchart TD
A[Naive datetime] -->|attach timezone| B[Aware datetime]
B -->|astimezone| C[Different timezone]
C -->|utcoffset| D[Offset from UTC]
subgraph Timezones
E[UTC]
F[Local]
G[Custom offset]
H[IANA zones]
end
Common Patterns
from datetime import datetime, timezone, timedelta
from zoneinfo import ZoneInfo # Python 3.9+
# Create UTC timezone
utc = timezone.utc
# Create custom offset timezone
bst = timezone(timedelta(hours=1)) # British Summer Time
# Get current time with timezone
now_utc = datetime.now(timezone.utc)
now_local = datetime.now().astimezone() # Local timezone
# Convert between timezones
dt_utc = datetime.now(timezone.utc)
dt_london = dt_utc.astimezone(ZoneInfo('Europe/London'))
dt_tokyo = dt_utc.astimezone(ZoneInfo('Asia/Tokyo'))
Examples
Working with UTC
from datetime import datetime, timezone
# Current time in UTC (recommended approach)
now_utc = datetime.now(timezone.utc)
print(f"UTC now: {now_utc}") # 2024-03-15 10:30:45.123456+00:00
# Create UTC datetime
dt_utc = datetime(2024, 3, 15, 10, 30, tzinfo=timezone.utc)
# Convert naive to UTC (assuming it's already UTC)
naive_dt = datetime(2024, 3, 15, 10, 30)
utc_dt = naive_dt.replace(tzinfo=timezone.utc)
# Get UTC offset
print(f"UTC offset: {now_utc.utcoffset()}") # 0:00:00
print(f"Timezone name: {now_utc.tzname()}") # UTC
Converting Between Timezones
from datetime import datetime, timezone, timedelta
from zoneinfo import ZoneInfo # Python 3.9+
# Create aware datetime in UTC
dt_utc = datetime(2024, 3, 15, 12, 0, tzinfo=timezone.utc)
# Convert to different timezones
dt_london = dt_utc.astimezone(ZoneInfo('Europe/London'))
dt_paris = dt_utc.astimezone(ZoneInfo('Europe/Paris'))
dt_new_york = dt_utc.astimezone(ZoneInfo('America/New_York'))
dt_tokyo = dt_utc.astimezone(ZoneInfo('Asia/Tokyo'))
print(f"UTC: {dt_utc}") # 12:00+00:00
print(f"London: {dt_london}") # 12:00+00:00 or 13:00+01:00 (DST)
print(f"Paris: {dt_paris}") # 13:00+01:00 or 14:00+02:00 (DST)
print(f"New York: {dt_new_york}") # 08:00-04:00 or 07:00-05:00
print(f"Tokyo: {dt_tokyo}") # 21:00+09:00
Custom Timezone Offsets
from datetime import datetime, timezone, timedelta
# Create timezone with fixed offset
utc_plus_5_30 = timezone(timedelta(hours=5, minutes=30), name='IST')
utc_minus_8 = timezone(timedelta(hours=-8), name='PST')
# Create datetime with custom timezone
dt_india = datetime(2024, 3, 15, 17, 30, tzinfo=utc_plus_5_30)
print(f"India: {dt_india}") # 2024-03-15 17:30:00+05:30
# Convert to UTC
dt_utc = dt_india.astimezone(timezone.utc)
print(f"UTC: {dt_utc}") # 2024-03-15 12:00:00+00:00
Local Time Operations
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
# Get local timezone-aware datetime
local_now = datetime.now().astimezone()
print(f"Local: {local_now}")
print(f"Timezone: {local_now.tzinfo}")
# Get system's local timezone
local_tz = datetime.now().astimezone().tzinfo
# Explicitly use local timezone
# This handles DST automatically
uk_tz = ZoneInfo('Europe/London')
dt_uk = datetime.now(uk_tz)
print(f"UK time: {dt_uk}")
# Check if in daylight saving time
is_dst = bool(dt_uk.dst())
print(f"DST active: {is_dst}")
Common Date Operations
Key Concepts
- Date arithmetic - Add/subtract days, weeks, months using timedelta
- Date comparison - Compare dates using standard operators
- Date replacement - Modify specific components of a date
- Calendar operations - Week numbers, day of year, leap years
Common Patterns
from datetime import datetime, date, timedelta
import calendar
# Add/subtract time
new_date = date.today() + timedelta(days=30)
past_date = datetime.now() - timedelta(weeks=2)
# Compare dates
is_future = date1 > date2
is_same_day = date1.date() == date2.date()
# Replace components
new_dt = dt.replace(year=2025, month=1)
# Calendar functions
is_leap = calendar.isleap(2024)
days_in_month = calendar.monthrange(2024, 2)[1]
Examples
Adding and Subtracting Days
from datetime import datetime, date, timedelta
today = date.today()
# Add days
tomorrow = today + timedelta(days=1)
next_week = today + timedelta(weeks=1)
in_30_days = today + timedelta(days=30)
in_90_days = today + timedelta(days=90)
# Subtract days
yesterday = today - timedelta(days=1)
last_week = today - timedelta(weeks=1)
last_month = today - timedelta(days=30)
print(f"Today: {today}")
print(f"In 30 days: {in_30_days}")
print(f"30 days ago: {last_month}")
# Working with datetime (includes time)
now = datetime.now()
in_two_hours = now + timedelta(hours=2)
thirty_mins_ago = now - timedelta(minutes=30)
Comparing Dates
from datetime import datetime, date
date1 = date(2024, 3, 15)
date2 = date(2024, 6, 20)
date3 = date(2024, 3, 15)
# Basic comparisons
print(date1 < date2) # True (date1 is earlier)
print(date1 > date2) # False
print(date1 == date3) # True (same date)
print(date1 != date2) # True
print(date1 <= date3) # True
# Compare with today
today = date.today()
is_past = date1 < today
is_future = date2 > today
# Sort dates
dates = [date2, date1, date3]
sorted_dates = sorted(dates)
print(sorted_dates) # Ascending order
# Find min/max
earliest = min(dates)
latest = max(dates)
# Check if date is between two dates
start = date(2024, 1, 1)
end = date(2024, 12, 31)
is_in_range = start <= date1 <= end
print(f"In 2024: {is_in_range}") # True
Calculating Date Differences
from datetime import datetime, date
# Difference between dates
date1 = date(2024, 1, 1)
date2 = date(2024, 12, 31)
diff = date2 - date1
print(f"Days between: {diff.days}") # 365
# Difference between datetimes
dt1 = datetime(2024, 3, 15, 10, 0, 0)
dt2 = datetime(2024, 3, 15, 14, 30, 45)
diff = dt2 - dt1
print(f"Hours: {diff.seconds // 3600}") # 4
print(f"Minutes: {(diff.seconds % 3600) // 60}") # 30
print(f"Total seconds: {diff.total_seconds()}") # 16245.0
# Days until an event
today = date.today()
christmas = date(today.year, 12, 25)
if christmas < today:
christmas = date(today.year + 1, 12, 25)
days_until_christmas = (christmas - today).days
print(f"Days until Christmas: {days_until_christmas}")
# Age calculation
birth_date = date(1990, 5, 15)
today = date.today()
age = today.year - birth_date.year
if today.month < birth_date.month or \
(today.month == birth_date.month and today.day < birth_date.day):
age -= 1
print(f"Age: {age} years")
Replacing Date Components
from datetime import datetime, date
dt = datetime(2024, 3, 15, 10, 30, 45)
# Replace individual components
new_year = dt.replace(year=2025)
first_of_month = dt.replace(day=1)
midnight = dt.replace(hour=0, minute=0, second=0, microsecond=0)
end_of_day = dt.replace(hour=23, minute=59, second=59)
print(f"Original: {dt}")
print(f"New year: {new_year}")
print(f"First of month: {first_of_month}")
print(f"Midnight: {midnight}")
# Get start and end of month
start_of_month = dt.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
import calendar
last_day = calendar.monthrange(dt.year, dt.month)[1]
end_of_month = dt.replace(day=last_day, hour=23, minute=59, second=59)
print(f"Month start: {start_of_month}")
print(f"Month end: {end_of_month}")
Week and Calendar Operations
from datetime import datetime, date
import calendar
dt = datetime(2024, 3, 15) # Friday
# Day of week (0=Monday, 6=Sunday)
print(f"Weekday: {dt.weekday()}") # 4 (Friday)
print(f"ISO weekday: {dt.isoweekday()}") # 5 (1=Monday, 7=Sunday)
# Week number
print(f"Week number: {dt.strftime('%W')}") # Week starting Monday
print(f"ISO week: {dt.isocalendar().week}") # ISO week number
# ISO calendar (year, week, weekday)
iso_cal = dt.isocalendar()
print(f"ISO: {iso_cal.year}-W{iso_cal.week}-{iso_cal.weekday}")
# Day of year
day_of_year = dt.timetuple().tm_yday
print(f"Day of year: {day_of_year}") # 75
# Check leap year
year = 2024
is_leap = calendar.isleap(year)
print(f"{year} is leap year: {is_leap}") # True
# Days in month
days_in_feb = calendar.monthrange(2024, 2)[1]
print(f"Days in Feb 2024: {days_in_feb}") # 29
# First weekday of month (0=Monday)
first_weekday = calendar.monthrange(2024, 3)[0]
print(f"March 2024 starts on: {calendar.day_name[first_weekday]}")
Unix Timestamps
Key Concepts
- Unix timestamp - Seconds since 1 January 1970 00:00:00 UTC (Unix epoch)
- fromtimestamp - Convert timestamp to local datetime
- utcfromtimestamp - Convert timestamp to UTC datetime (deprecated)
- timestamp - Convert datetime to Unix timestamp
- Milliseconds - JavaScript and some APIs use milliseconds
flowchart LR
A[datetime] -->|.timestamp| B[Unix timestamp]
B -->|fromtimestamp| C[Local datetime]
B -->|/ 1000| D[Seconds to ms]
D -->|* 1000| B
Common Patterns
from datetime import datetime, timezone
# Current timestamp
timestamp = datetime.now().timestamp()
# Convert timestamp to datetime
dt = datetime.fromtimestamp(timestamp) # Local time
dt_utc = datetime.fromtimestamp(timestamp, tz=timezone.utc) # UTC
# Convert datetime to timestamp
ts = dt.timestamp()
# Milliseconds (for JavaScript interop)
ms_timestamp = int(datetime.now().timestamp() * 1000)
dt_from_ms = datetime.fromtimestamp(ms_timestamp / 1000)
Examples
Getting Current Timestamp
from datetime import datetime, timezone
import time
# Current Unix timestamp (seconds since epoch)
timestamp = datetime.now().timestamp()
print(f"Timestamp: {timestamp}") # 1710502245.123456
# Using time module
timestamp_time = time.time()
print(f"Time module: {timestamp_time}")
# Integer timestamp (no microseconds)
int_timestamp = int(datetime.now().timestamp())
print(f"Integer: {int_timestamp}") # 1710502245
# UTC timestamp (recommended)
utc_timestamp = datetime.now(timezone.utc).timestamp()
print(f"UTC timestamp: {utc_timestamp}")
Converting Timestamp to datetime
from datetime import datetime, timezone
timestamp = 1710502245 # Example timestamp
# To local datetime
dt_local = datetime.fromtimestamp(timestamp)
print(f"Local: {dt_local}") # Depends on system timezone
# To UTC datetime (recommended)
dt_utc = datetime.fromtimestamp(timestamp, tz=timezone.utc)
print(f"UTC: {dt_utc}") # 2024-03-15 11:30:45+00:00
# With specific timezone
from zoneinfo import ZoneInfo
dt_london = datetime.fromtimestamp(timestamp, tz=ZoneInfo('Europe/London'))
print(f"London: {dt_london}")
# Handle timestamps with microseconds
timestamp_micro = 1710502245.123456
dt = datetime.fromtimestamp(timestamp_micro, tz=timezone.utc)
print(f"With microseconds: {dt}")
Converting datetime to Timestamp
from datetime import datetime, timezone
# Current datetime to timestamp
now = datetime.now()
timestamp = now.timestamp()
print(f"Timestamp: {timestamp}")
# Specific datetime to timestamp
dt = datetime(2024, 3, 15, 12, 30, 45)
timestamp = dt.timestamp() # Uses local timezone
print(f"Timestamp: {timestamp}")
# UTC datetime to timestamp
dt_utc = datetime(2024, 3, 15, 12, 30, 45, tzinfo=timezone.utc)
timestamp = dt_utc.timestamp()
print(f"UTC timestamp: {timestamp}")
# Be explicit about timezone for consistency
dt_aware = datetime(2024, 3, 15, 12, 30, 45, tzinfo=timezone.utc)
timestamp = dt_aware.timestamp()
Working with Milliseconds
from datetime import datetime, timezone
# Timestamp in milliseconds (JavaScript format)
ms_timestamp = 1710502245123
# Convert milliseconds to datetime
dt = datetime.fromtimestamp(ms_timestamp / 1000, tz=timezone.utc)
print(f"From ms: {dt}")
# Current time in milliseconds
now_ms = int(datetime.now(timezone.utc).timestamp() * 1000)
print(f"Now (ms): {now_ms}")
# Convert datetime to milliseconds
dt = datetime.now(timezone.utc)
ms = int(dt.timestamp() * 1000)
print(f"To ms: {ms}")
# Microseconds to milliseconds
microseconds = dt.microsecond
milliseconds = microseconds // 1000
Timestamp Range Queries
from datetime import datetime, timezone, timedelta
# Get timestamps for a date range
start_date = datetime(2024, 3, 1, tzinfo=timezone.utc)
end_date = datetime(2024, 3, 31, 23, 59, 59, tzinfo=timezone.utc)
start_ts = int(start_date.timestamp())
end_ts = int(end_date.timestamp())
print(f"Start: {start_ts}")
print(f"End: {end_ts}")
# Database query example
# SELECT * FROM events WHERE timestamp >= {start_ts} AND timestamp <= {end_ts}
# Last 24 hours
now = datetime.now(timezone.utc)
yesterday = now - timedelta(days=1)
last_24h_start = int(yesterday.timestamp())
last_24h_end = int(now.timestamp())
ISO 8601 Formatting
Key Concepts
- ISO 8601 - International standard for date and time representation
- Format -
YYYY-MM-DDTHH:MM:SS.ssssss+HH:MM - Z suffix - Indicates UTC (Zulu time)
- isoformat - Built-in method for ISO 8601 output
- fromisoformat - Parse ISO 8601 strings (Python 3.7+)
flowchart TD
A["2024-03-15T14:30:45.123456+00:00"]
A --> B["2024-03-15"]
A --> C["T"]
A --> D["14:30:45.123456"]
A --> E["+00:00"]
B --> F[Date: YYYY-MM-DD]
C --> G[Separator]
D --> H[Time: HH:MM:SS.microseconds]
E --> I[Timezone offset]
Common Patterns
from datetime import datetime, timezone, date, time
# Output ISO 8601
dt = datetime.now(timezone.utc)
iso_string = dt.isoformat() # 2024-03-15T12:30:45.123456+00:00
# Parse ISO 8601
dt = datetime.fromisoformat('2024-03-15T12:30:45+00:00')
# Date only
d = date.fromisoformat('2024-03-15')
iso_date = d.isoformat()
# Time only
t = time.fromisoformat('12:30:45')
iso_time = t.isoformat()
Examples
Generating ISO 8601 Strings
from datetime import datetime, timezone, date, time
# Full ISO 8601 with timezone
dt = datetime.now(timezone.utc)
iso_full = dt.isoformat()
print(f"Full: {iso_full}") # 2024-03-15T12:30:45.123456+00:00
# Without microseconds
iso_short = dt.replace(microsecond=0).isoformat()
print(f"Short: {iso_short}") # 2024-03-15T12:30:45+00:00
# With custom separator
iso_space = dt.isoformat(sep=' ')
print(f"Space: {iso_space}") # 2024-03-15 12:30:45.123456+00:00
# Truncate to specific precision
iso_seconds = dt.isoformat(timespec='seconds')
iso_minutes = dt.isoformat(timespec='minutes')
iso_hours = dt.isoformat(timespec='hours')
iso_ms = dt.isoformat(timespec='milliseconds')
print(f"Seconds: {iso_seconds}") # 2024-03-15T12:30:45+00:00
print(f"Minutes: {iso_minutes}") # 2024-03-15T12:30+00:00
print(f"Milliseconds: {iso_ms}") # 2024-03-15T12:30:45.123+00:00
# Date only
d = date.today()
print(f"Date: {d.isoformat()}") # 2024-03-15
# Time only
t = time(14, 30, 45)
print(f"Time: {t.isoformat()}") # 14:30:45
Parsing ISO 8601 Strings
from datetime import datetime, date, time
# Parse full ISO 8601
dt = datetime.fromisoformat('2024-03-15T14:30:45')
print(f"Parsed: {dt}")
# With timezone
dt_tz = datetime.fromisoformat('2024-03-15T14:30:45+01:00')
print(f"With TZ: {dt_tz}")
# UTC with Z suffix (Python 3.11+)
# Before 3.11, replace 'Z' with '+00:00' first
iso_z = '2024-03-15T14:30:45Z'
dt_z = datetime.fromisoformat(iso_z)
print(f"From Z: {dt_z}")
# Parse date only
d = date.fromisoformat('2024-03-15')
print(f"Date: {d}")
# Parse time only
t = time.fromisoformat('14:30:45')
print(f"Time: {t}")
# Various ISO 8601 formats
formats = [
'2024-03-15',
'2024-03-15T14:30',
'2024-03-15T14:30:45',
'2024-03-15T14:30:45.123456',
'2024-03-15T14:30:45+00:00',
'2024-03-15 14:30:45', # Space separator also works
]
for fmt in formats:
try:
parsed = datetime.fromisoformat(fmt)
print(f"{fmt} -> {parsed}")
except ValueError as e:
print(f"{fmt} -> Error: {e}")
ISO Week Dates
from datetime import datetime, date
# ISO calendar returns (year, week, weekday)
dt = datetime(2024, 3, 15)
iso_cal = dt.isocalendar()
print(f"ISO year: {iso_cal.year}")
print(f"ISO week: {iso_cal.week}")
print(f"ISO weekday: {iso_cal.weekday}") # 1-7 (Mon-Sun)
# Format as ISO week date
iso_week_date = f"{iso_cal.year}-W{iso_cal.week:02d}-{iso_cal.weekday}"
print(f"ISO week date: {iso_week_date}") # 2024-W11-5
# Parse ISO week date (Python 3.8+)
from datetime import datetime
dt = datetime.strptime('2024-W11-5', '%G-W%V-%u')
print(f"From ISO week: {dt.date()}") # 2024-03-15
API and Database Formats
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
# Common API formats
api_formats = {
'ISO 8601': now.isoformat(),
'ISO compact': now.strftime('%Y%m%dT%H%M%SZ'),
'RFC 2822': now.strftime('%a, %d %b %Y %H:%M:%S +0000'),
'RFC 3339': now.isoformat().replace('+00:00', 'Z'),
}
for name, fmt in api_formats.items():
print(f"{name}: {fmt}")
# Database formats
db_formats = {
'MySQL datetime': now.strftime('%Y-%m-%d %H:%M:%S'),
'PostgreSQL': now.isoformat(),
'SQLite': now.strftime('%Y-%m-%d %H:%M:%S.%f'),
}
for name, fmt in db_formats.items():
print(f"{name}: {fmt}")
# Elasticsearch / JSON
import json
json_dt = json.dumps({'timestamp': now.isoformat()})
print(f"JSON: {json_dt}")
Quick Reference
Format Codes
| Code | Description | Example |
|---|---|---|
%Y |
4-digit year | 2024 |
%y |
2-digit year | 24 |
%m |
Month (01-12) | 03 |
%d |
Day (01-31) | 15 |
%H |
Hour 24h (00-23) | 14 |
%I |
Hour 12h (01-12) | 02 |
%M |
Minute (00-59) | 30 |
%S |
Second (00-59) | 45 |
%f |
Microsecond | 123456 |
%p |
AM/PM | PM |
%A |
Full weekday | Friday |
%a |
Short weekday | Fri |
%B |
Full month | March |
%b |
Short month | Mar |
%j |
Day of year | 075 |
%W |
Week number (Mon) | 11 |
%U |
Week number (Sun) | 10 |
%z |
UTC offset | +0000 |
%Z |
Timezone name | UTC |
Common Operations
| Operation | Code |
|---|---|
| Current datetime | datetime.now() |
| Current UTC | datetime.now(timezone.utc) |
| Current date | date.today() |
| Parse string | datetime.strptime(s, fmt) |
| Format string | dt.strftime(fmt) |
| Add days | dt + timedelta(days=n) |
| Subtract days | dt - timedelta(days=n) |
| Date difference | (dt2 - dt1).days |
| To timestamp | dt.timestamp() |
| From timestamp | datetime.fromtimestamp(ts) |
| To ISO 8601 | dt.isoformat() |
| From ISO 8601 | datetime.fromisoformat(s) |
| Replace component | dt.replace(year=2025) |
| Attach timezone | dt.replace(tzinfo=tz) |
| Convert timezone | dt.astimezone(tz) |
Timezone Quick Reference
| Task | Code |
|---|---|
| UTC timezone | timezone.utc |
| Custom offset | timezone(timedelta(hours=5)) |
| IANA timezone | ZoneInfo('Europe/London') |
| Make aware | dt.replace(tzinfo=timezone.utc) |
| Convert zone | dt.astimezone(new_tz) |
| Get offset | dt.utcoffset() |
| Local to UTC | local_dt.astimezone(timezone.utc) |
| UTC to local | utc_dt.astimezone() |
Common Issues and Solutions
Issue: Naive vs Aware Datetime Comparison
Problem: TypeError: can't compare offset-naive and offset-aware datetimes
Solution:
from datetime import datetime, timezone
naive_dt = datetime.now()
aware_dt = datetime.now(timezone.utc)
# Option 1: Make naive aware (if you know it's UTC)
naive_as_utc = naive_dt.replace(tzinfo=timezone.utc)
can_compare = naive_as_utc > aware_dt
# Option 2: Make aware naive (loses timezone info)
aware_as_naive = aware_dt.replace(tzinfo=None)
can_compare = naive_dt > aware_as_naive
# Best practice: Always use aware datetimes
dt1 = datetime.now(timezone.utc)
dt2 = datetime.now(timezone.utc)
can_compare = dt1 > dt2
Issue: strptime Format Mismatch
Problem: ValueError: time data 'X' does not match format 'Y'
Solution:
from datetime import datetime
date_string = '15/03/2024'
# Ensure format matches exactly
# Wrong: '%Y-%m-%d' expects 2024-03-15
# Right: '%d/%m/%Y' expects 15/03/2024
dt = datetime.strptime(date_string, '%d/%m/%Y')
# For variable formats, try multiple
formats = ['%Y-%m-%d', '%d/%m/%Y', '%m/%d/%Y', '%d-%m-%Y']
def parse_date(date_string):
for fmt in formats:
try:
return datetime.strptime(date_string, fmt)
except ValueError:
continue
raise ValueError(f"Unable to parse: {date_string}")
Issue: Daylight Saving Time Ambiguity
Problem: Ambiguous times during DST transitions
Solution:
from datetime import datetime
from zoneinfo import ZoneInfo
# During DST transition, some times occur twice
# Use fold attribute to disambiguate (Python 3.6+)
tz = ZoneInfo('Europe/London')
# 01:30 occurs twice on last Sunday of October
# fold=0 is first occurrence (before clocks go back)
# fold=1 is second occurrence (after clocks go back)
dt_first = datetime(2024, 10, 27, 1, 30, tzinfo=tz, fold=0)
dt_second = datetime(2024, 10, 27, 1, 30, tzinfo=tz, fold=1)
print(f"First (BST): {dt_first.isoformat()}")
print(f"Second (GMT): {dt_second.isoformat()}")
Issue: Timestamp Timezone Confusion
Problem: fromtimestamp() returns local time unexpectedly
Solution:
from datetime import datetime, timezone
timestamp = 1710502245
# This returns LOCAL time (confusing!)
local_dt = datetime.fromtimestamp(timestamp)
print(f"Local: {local_dt}")
# Always specify timezone explicitly
utc_dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
print(f"UTC: {utc_dt}")
# Or convert to your desired timezone
from zoneinfo import ZoneInfo
london_dt = datetime.fromtimestamp(timestamp, tz=ZoneInfo('Europe/London'))
print(f"London: {london_dt}")
Issue: Parsing ISO 8601 with Z Suffix
Problem: fromisoformat() doesn't recognise 'Z' (before Python 3.11)
Solution:
from datetime import datetime, timezone
iso_string = '2024-03-15T14:30:45.123Z'
# Python 3.11+: Works directly
dt = datetime.fromisoformat(iso_string)
print(f"Parsed: {dt}")
# Python 3.7-3.10: Replace Z with +00:00
# dt = datetime.fromisoformat(iso_string.replace('Z', '+00:00'))
# Alternative: Use strptime
dt = datetime.strptime(iso_string, '%Y-%m-%dT%H:%M:%S.%fZ')
dt = dt.replace(tzinfo=timezone.utc)
Issue: Month Arithmetic
Problem: Adding months isn't straightforward with timedelta
Solution:
from datetime import datetime
from dateutil.relativedelta import relativedelta # pip install python-dateutil
dt = datetime(2024, 1, 31)
# timedelta doesn't support months directly
# This would fail: dt + timedelta(months=1)
# Use dateutil's relativedelta
next_month = dt + relativedelta(months=1)
print(f"Next month: {next_month}") # 2024-02-29 (handles month end)
# Manual approach without dateutil
def add_months(dt, months):
month = dt.month + months
year = dt.year + (month - 1) // 12
month = (month - 1) % 12 + 1
import calendar
max_day = calendar.monthrange(year, month)[1]
day = min(dt.day, max_day)
return dt.replace(year=year, month=month, day=day)
result = add_months(datetime(2024, 1, 31), 1)
print(f"Result: {result}") # 2024-02-29
Issue: Performance with Many Datetime Operations
Problem: Slow performance when processing many dates
Solution:
from datetime import datetime, timezone
# Avoid repeated timezone lookups
from zoneinfo import ZoneInfo
tz = ZoneInfo('Europe/London') # Cache the timezone
# Pre-compile format strings (strptime is slow)
# Use fromisoformat when possible (much faster)
dates = ['2024-03-15', '2024-03-16', '2024-03-17']
parsed = [datetime.fromisoformat(d) for d in dates] # Fast
# For high-performance needs, consider:
# - pandas for bulk datetime operations
# - numpy's datetime64 for numerical operations
# - ciso8601 for fast ISO 8601 parsing
Related Topics
- dateutil - Powerful extensions for datetime parsing and timezone handling
- pytz - Historical timezone library (use zoneinfo for Python 3.9+)
- arrow - Human-friendly datetime library with simpler API
- pendulum - Timezone-aware datetime with natural language support
- pandas datetime - Efficient datetime operations for data analysis
- time module - Lower-level time functions and process timing