Skip to content

Python Dates and Times — datetime Module Complete Guide

DodaTech Updated 2026-06-29 5 min read

In this tutorial, you will learn about Python Dates and Times. We cover key concepts, practical examples, and best practices to help you master this topic.

Working with dates and times is one of the most common tasks in programming. Python's datetime module provides classes for manipulating dates, times, and time intervals. You'll use it for logging timestamps, scheduling tasks, calculating time differences, and handling time zones.

In this tutorial, you'll learn the datetime module from the ground up — how to create, format, compare, and manipulate dates and times in Python. DodaTech uses these techniques for timestamping security events, calculating session expiry, and scheduling automated scans.

What You'll Learn

  • Creating date, time, and datetime objects
  • Date arithmetic with timedelta
  • Formatting dates with strftime
  • Parsing strings into dates with strptime
  • Timezone-aware datetime handling
  • Working with time intervals and durations

Why Datetime Matters

Every application deals with time. Log entries need timestamps, sessions need expiry, reports need date ranges. Python's datetime module handles all of this and more. Without it, you'd be doing manual date math — and date math is deceptively complex (leap years, different month lengths, time zones).

Creating Date and Time Objects

from datetime import date, time, datetime

# Current date and time
today = date.today()
now = datetime.now()
print(today)  # 2026-06-29
print(now)    # 2026-06-29 14:00:00.123456

# Creating specific dates
d = date(2026, 6, 29)
print(d)                      # 2026-06-29
print(d.year, d.month, d.day) # 2026 6 29

# Creating specific times
t = time(14, 30, 45)
print(t)                      # 14:30:45
print(t.hour, t.minute, t.second)  # 14 30 45

# Creating datetime objects
dt = datetime(2026, 6, 29, 14, 30, 45)
print(dt)  # 2026-06-29 14:30:45

Date Arithmetic with timedelta

from datetime import datetime, timedelta

now = datetime(2026, 6, 29, 12, 0, 0)

# Add or subtract time
print(now + timedelta(days=7))     # 2026-07-06 12:00:00
print(now - timedelta(hours=3))    # 2026-06-29 09:00:00
print(now + timedelta(weeks=2, days=1, hours=6))

# Difference between dates
event = datetime(2026, 7, 4, 0, 0, 0)
until_event = event - now
print(until_event)                  # 4 days, 12:00:00
print(until_event.days)             # 4
print(until_event.total_seconds())  # 388800.0

Expected output:

2026-07-06 12:00:00
2026-06-29 09:00:00
2026-07-14 18:00:00
4 days, 12:00:00
4
388800.0

Formatting Dates with strftime

from datetime import datetime

now = datetime(2026, 6, 29, 14, 30, 45)

# Common format codes
print(now.strftime("%Y-%m-%d"))          # 2026-06-29
print(now.strftime("%d/%m/%Y"))          # 29/06/2026
print(now.strftime("%B %d, %Y"))         # June 29, 2026
print(now.strftime("%I:%M %p"))          # 02:30 PM (12-hour)
print(now.strftime("%H:%M:%S"))          # 14:30:45 (24-hour)
print(now.strftime("%A, %B %d"))         # Monday, June 29
print(now.strftime("%Y-%m-%d %H:%M:%S")) # 2026-06-29 14:30:45 (ISO format)
print(now.strftime("%j"))                # 180 (day of year)
print(now.strftime("%W"))                # 26 (week number)

Parsing Strings into Dates (strptime)

from datetime import datetime

# Parse common date formats
date_str1 = "2026-06-29"
dt1 = datetime.strptime(date_str1, "%Y-%m-%d")
print(dt1)  # 2026-06-29 00:00:00

date_str2 = "29/06/2026"
dt2 = datetime.strptime(date_str2, "%d/%m/%Y")
print(dt2)  # 2026-06-29 00:00:00

date_str3 = "June 29, 2026 14:30"
dt3 = datetime.strptime(date_str3, "%B %d, %Y %H:%M")
print(dt3)  # 2026-06-29 14:30:00

# ISO format parsing
iso_str = "2026-06-29T14:30:45"
dt4 = datetime.fromisoformat(iso_str)
print(dt4)  # 2026-06-29 14:30:45

Timezone Handling

from datetime import datetime, timezone, timedelta

# UTC timezone
utc_now = datetime.now(timezone.utc)
print(utc_now)  # 2026-06-29 12:00:00+00:00

# Specific timezone offset
tz_eastern = timezone(timedelta(hours=-5))
eastern_now = datetime.now(tz_eastern)
print(eastern_now)  # 2026-06-29 07:00:00-05:00

# Converting between timezones
utc = datetime(2026, 6, 29, 12, 0, 0, tzinfo=timezone.utc)
eastern = utc.astimezone(timezone(timedelta(hours=-5)))
print(f"UTC: {utc}")
print(f"Eastern: {eastern}")

# For production, use pytz or zoneinfo (Python 3.9+)
from zoneinfo import ZoneInfo
ny = datetime(2026, 6, 29, 12, 0, 0, tzinfo=ZoneInfo("America/New_York"))
london = ny.astimezone(ZoneInfo("Europe/London"))
print(f"NY: {ny}")
print(f"London: {london}")

Real-World: Log Timestamp Parser

from datetime import datetime

def parse_apache_timestamp(ts):
    """
    Parse Apache log timestamp format:
    [29/Jun/2026:14:30:45 +0000]
    """
    return datetime.strptime(ts, "[%d/%b/%Y:%H:%M:%S %z]")

def parse_iso_log(ts):
    """
    Parse ISO 8601 format used in modern logging:
    2026-06-29T14:30:45.123456Z
    """
    return datetime.fromisoformat(ts.replace("Z", "+00:00"))

# Test
apache = "[29/Jun/2026:14:30:45 +0000]"
print(parse_apache_timestamp(apache))

iso_log = "2026-06-29T14:30:45.123456Z"
print(parse_iso_log(iso_log))

Expected output:

2026-06-29 14:30:45+00:00
2026-06-29 14:30:45.123456+00:00

Common Pitfalls

Pitfall 1: Naive vs Aware Datetimes

from datetime import datetime, timezone

# Naive (no timezone) — can't compare with aware
naive = datetime(2026, 6, 29, 12, 0, 0)
aware = datetime(2026, 6, 29, 12, 0, 0, tzinfo=timezone.utc)

# This raises TypeError: can't subtract offset-naive and offset-aware datetimes
try:
    diff = aware - naive
except TypeError as e:
    print(f"Error: {e}")

# Fix: make them consistent
naive_utc = naive.replace(tzinfo=timezone.utc)
print(aware - naive_utc)  # 0:00:00

Pitfall 2: Month Range

Python months are 1-indexed (January=1), but days and weekdays can be 0 or 1-indexed:

from datetime import date

d = date(2026, 6, 29)
print(d.weekday())   # 0=Monday (Sunday=6)
print(d.isoweekday())  # 1=Monday (Sunday=7)

Pitfall 3: timedelta Only Stores Days, Seconds, Microseconds

from datetime import timedelta

# You can't create timedelta(months=1) — use dateutil.relativedelta
td = timedelta(days=30)  # Approximate a month

Practice Questions

  1. Write a function that returns a list of dates for the last N days.

  2. Calculate your age in years, months, and days from your birth date.

  3. Parse "2026-06-29 14:30:45,123" (with comma-separated microseconds).

  4. Write a function that takes two ISO date strings and returns the number of business days between them (Mon-Fri).

  5. Format a datetime object as "Monday, June 29th, 2026 at 2:30 PM".

Challenge: Recurring Schedule Calculator

Write a class Schedule that takes a start date and a recurrence rule (daily, weekly, monthly) and can generate the next N occurrences. For weekly schedules, support specific days of the week (e.g., "every Mon, Wed, Fri"). This is the kind of scheduling logic used in DodaTech's automated security scan system.

Real-World Task: Session Expiry Checker

Write a function that takes a session creation timestamp and a timeout duration (in minutes), and returns whether the session is still valid. Account for timezone differences — the session might be created in UTC but checked in a local timezone. Log a WARNING when the session is about to expire (within 5 minutes) and an INFO message when a new session is created. This pattern is used in DodaTech's authentication system.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro