Virtual assistance

Python Date and Time

Python provides powerful modules for working with dates and times. Learn how to use datetime, time, and calendar modules for date manipulation, formatting, and calculations.

Python Date and Time

Working with Dates and Times

Python's datetime module is the primary way to work with dates and times. It provides classes for manipulating dates and times in both simple and complex ways.

"Time is an illusion. But datetime objects are real."

Current Date and Time

Get the current date and time:

from datetime import datetime, date, time

# Current date and time
now = datetime.now()
print("Current date and time:", now)
print("Type:", type(now))

# Current date only
today = date.today()
print("Today's date:", today)

# Current time only
current_time = datetime.now().time()
print("Current time:", current_time)

# Specific components
print("Year:", now.year)
print("Month:", now.month)
print("Day:", now.day)
print("Hour:", now.hour)
print("Minute:", now.minute)
print("Second:", now.second)
print("Microsecond:", now.microsecond)

Creating DateTime Objects

Create specific dates and times:

from datetime import datetime, date, time

# Create specific datetime
dt = datetime(2023, 12, 25, 10, 30, 45)
print("Christmas morning:", dt)

# Create date object
d = date(2023, 12, 25)
print("Christmas date:", d)

# Create time object
t = time(10, 30, 45)
print("Time:", t)

# Combine date and time
combined = datetime.combine(d, t)
print("Combined:", combined)

# From timestamp (seconds since epoch)
timestamp = 1703500245  # Example timestamp
dt_from_ts = datetime.fromtimestamp(timestamp)
print("From timestamp:", dt_from_ts)

# From ISO format string
iso_string = "2023-12-25T10:30:45"
dt_from_iso = datetime.fromisoformat(iso_string)
print("From ISO:", dt_from_iso)

DateTime Formatting

Format dates for display:

from datetime import datetime

now = datetime.now()

# Common formats
print("Default format:", now)
print("ISO format:", now.isoformat())
print("Date only:", now.date())
print("Time only:", now.time())

# Custom formatting with strftime
print("Formatted date:", now.strftime("%Y-%m-%d"))
print("Formatted time:", now.strftime("%H:%M:%S"))
print("Full format:", now.strftime("%A, %B %d, %Y at %I:%M %p"))
print("Short format:", now.strftime("%m/%d/%Y %H:%M"))

# Common strftime codes:
# %Y - Year (4 digits)
# %m - Month (01-12)
# %d - Day (01-31)
# %H - Hour (00-23)
# %M - Minute (00-59)
# %S - Second (00-59)
# %A - Full weekday name
# %B - Full month name
# %I - Hour (01-12)
# %p - AM/PM

Parsing Date Strings

Convert strings to datetime objects:

from datetime import datetime

# Using strptime
date_string = "2023-12-25 10:30:45"
dt = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")
print("Parsed datetime:", dt)

# Different formats
formats = [
    "25/12/2023",
    "12/25/2023", 
    "December 25, 2023",
    "25-Dec-2023",
    "2023/12/25"
]

format_strings = [
    "%d/%m/%Y",
    "%m/%d/%Y",
    "%B %d, %Y", 
    "%d-%b-%Y",
    "%Y/%m/%d"
]

for fmt_str, fmt in zip(formats, format_strings):
    try:
        parsed = datetime.strptime(fmt_str, fmt)
        print(f"{fmt_str} -> {parsed.date()}")
    except ValueError as e:
        print(f"Error parsing {fmt_str}: {e}")

# Using dateutil parser (more flexible)
from dateutil import parser
flexible_dates = [
    "today",
    "tomorrow", 
    "next week",
    "2023-12-25",
    "12/25/2023",
    "December 25th, 2023"
]

for date_str in flexible_dates:
    try:
        parsed = parser.parse(date_str)
        print(f"'{date_str}' -> {parsed}")
    except:
        print(f"Could not parse: {date_str}")

Date Arithmetic

Add and subtract time periods:

from datetime import datetime, timedelta, date

# Current date
today = date.today()
print("Today:", today)

# Add days
tomorrow = today + timedelta(days=1)
print("Tomorrow:", tomorrow)

next_week = today + timedelta(weeks=1)
print("Next week:", next_week)

# Subtract days
yesterday = today - timedelta(days=1)
print("Yesterday:", yesterday)

# Date differences
date1 = date(2023, 12, 25)
date2 = date(2024, 1, 1)
difference = date2 - date1
print(f"Days between Christmas and New Year: {difference.days}")

# With datetime objects
now = datetime.now()
future = now + timedelta(hours=2, minutes=30)
print(f"Now: {now}")
print(f"In 2.5 hours: {future}")

# Time differences
past = now - timedelta(days=7)
time_diff = now - past
print(f"Time difference: {time_diff}")
print(f"Total seconds: {time_diff.total_seconds()}")

Working with Timezones

Handle different timezones:

from datetime import datetime, timezone, timedelta
import pytz

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

# Create timezone-aware datetime
eastern = timezone(timedelta(hours=-5))  # EST
dt_eastern = datetime(2023, 12, 25, 10, 30, tzinfo=eastern)
print("Eastern time:", dt_eastern)

# Using pytz for proper timezone handling
if 'pytz' in globals():
    # New York timezone
    nyc_tz = pytz.timezone('America/New_York')
    nyc_time = nyc_tz.localize(datetime(2023, 12, 25, 10, 30))
    print("NYC time:", nyc_time)
    
    # Convert to UTC
    utc_time = nyc_time.astimezone(pytz.UTC)
    print("UTC equivalent:", utc_time)
    
    # Convert to London time
    london_tz = pytz.timezone('Europe/London')
    london_time = nyc_time.astimezone(london_tz)
    print("London time:", london_time)

# Timezone conversion
naive_dt = datetime(2023, 12, 25, 10, 30)
# Make it timezone-aware (assuming it's in UTC)
aware_dt = naive_dt.replace(tzinfo=timezone.utc)
print("Timezone-aware:", aware_dt)

# Convert to different timezone
est_tz = timezone(timedelta(hours=-5))
est_time = aware_dt.astimezone(est_tz)
print("EST time:", est_time)

Calendar Operations

Use the calendar module:

import calendar
from datetime import date

# Current year calendar
year = 2024
print(f"Calendar for {year}:")
print(calendar.calendar(year))

# Month calendar
month = 12
print(f"\nCalendar for December {year}:")
print(calendar.month(year, month))

# Check if year is leap year
print(f"Is {year} a leap year? {calendar.isleap(year)}")
print(f"Is 2023 a leap year? {calendar.isleap(2023)}")

# Days in month
days_in_dec = calendar.monthrange(year, month)[1]
print(f"Days in December {year}: {days_in_dec}")

# Weekday of first day of month
first_weekday, days = calendar.monthrange(year, month)
weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
print(f"December {year} starts on a {weekdays[first_weekday]}")

# Get all days in a month
month_days = calendar.monthcalendar(year, month)
print("December calendar:")
for week in month_days:
    print(week)

# Find day of week for specific date
specific_date = date(2023, 12, 25)
weekday_num = specific_date.weekday()  # 0=Monday, 6=Sunday
weekday_name = weekdays[weekday_num]
print(f"December 25, 2023 is a {weekday_name}")

Time Module

Basic time operations:

import time

# Current timestamp (seconds since epoch)
current_time = time.time()
print(f"Current timestamp: {current_time}")

# Sleep for seconds
print("Sleeping for 2 seconds...")
time.sleep(2)
print("Awake!")

# Convert timestamp to struct_time
struct_time = time.localtime(current_time)
print("Structured time:", struct_time)

# Format time
formatted = time.strftime("%Y-%m-%d %H:%M:%S", struct_time)
print("Formatted time:", formatted)

# Parse time string
time_string = "2023-12-25 10:30:45"
parsed_time = time.strptime(time_string, "%Y-%m-%d %H:%M:%S")
print("Parsed time:", parsed_time)

# Time tuple components
print("Year:", parsed_time.tm_year)
print("Month:", parsed_time.tm_mon)
print("Day:", parsed_time.tm_mday)
print("Hour:", parsed_time.tm_hour)
print("Minute:", parsed_time.tm_min)
print("Second:", parsed_time.tm_sec)
print("Weekday:", parsed_time.tm_wday)  # 0=Monday
print("Day of year:", parsed_time.tm_yday)

Practical Examples

from datetime import datetime, timedelta, date
import calendar

def calculate_age(birth_date):
    """Calculate age from birth date"""
    today = date.today()
    age = today.year - birth_date.year
    if (today.month, today.day) < (birth_date.month, birth_date.day):
        age -= 1
    return age

def days_until_birthday(birth_date):
    """Calculate days until next birthday"""
    today = date.today()
    next_birthday = date(today.year, birth_date.month, birth_date.day)
    
    if next_birthday < today:
        next_birthday = date(today.year + 1, birth_date.month, birth_date.day)
    
    return (next_birthday - today).days

def format_duration(seconds):
    """Format seconds into readable duration"""
    days, remainder = divmod(seconds, 86400)
    hours, remainder = divmod(remainder, 3600)
    minutes, seconds = divmod(remainder, 60)
    
    parts = []
    if days > 0:
        parts.append(f"{days} days")
    if hours > 0:
        parts.append(f"{hours} hours")
    if minutes > 0:
        parts.append(f"{minutes} minutes")
    if seconds > 0:
        parts.append(f"{seconds} seconds")
    
    return ", ".join(parts) if parts else "0 seconds"

# Usage examples
birth_date = date(1990, 5, 15)
print(f"Age: {calculate_age(birth_date)}")
print(f"Days until birthday: {days_until_birthday(birth_date)}")

# Duration formatting
durations = [65, 3665, 86465, 31536065]
for duration in durations:
    print(f"{duration} seconds = {format_duration(duration)}")

def get_business_days(start_date, end_date):
    """Get number of business days between two dates"""
    business_days = 0
    current_date = start_date
    
    while current_date <= end_date:
        if current_date.weekday() < 5:  # Monday to Friday
            business_days += 1
        current_date += timedelta(days=1)
    
    return business_days

start = date(2023, 12, 20)
end = date(2024, 1, 5)
print(f"Business days: {get_business_days(start, end)}")

def next_weekday(start_date, weekday):
    """Find next occurrence of specific weekday"""
    days_ahead = weekday - start_date.weekday()
    if days_ahead <= 0:
        days_ahead += 7
    return start_date + timedelta(days=days_ahead)

today = date.today()
next_monday = next_weekday(today, 0)  # 0 = Monday
next_friday = next_weekday(today, 4)  # 4 = Friday
print(f"Next Monday: {next_monday}")
print(f"Next Friday: {next_friday}")

Best Practices

  • Use timezone-aware datetime objects: Avoid naive datetime
  • Store dates as UTC in databases: Convert for display
  • Use ISO format for string representation: datetime.isoformat()
  • Handle daylight saving time carefully: Use pytz library
  • Use date objects for date-only operations: Not datetime
  • Validate date inputs: Check for valid dates
  • Use timedelta for date arithmetic: Not manual calculations
  • Cache strftime format strings: For performance
  • Use calendar for complex date operations: Month calculations
  • Document timezone assumptions: In your code

Common Pitfalls

  • Mixing naive and aware datetime objects: Causes errors
  • February 29 on non-leap years: Validate dates
  • Month/day order confusion: US vs international formats
  • Time zone conversion errors: Double conversion
  • Off-by-one errors in date ranges: Inclusive vs exclusive
  • Timestamp precision loss: Microseconds in databases
  • Locale-dependent formatting: Use explicit formats

Working with dates and times in Python is straightforward with the datetime module, but requires careful attention to timezones and formatting. Always consider whether you need date-only, time-only, or full datetime objects for your use case.