Home Python Python datetime Module Explained — Dates, Times, and Formatting

Python datetime Module Explained — Dates, Times, and Formatting

In Plain English 🔥
Think of the datetime module as a really smart wall calendar that also has a clock built in. Just like you'd glance at your calendar to find out what day it is, calculate how many days until your birthday, or write today's date on a letter, the datetime module lets your Python program do exactly those same things. Without it, Python would have no idea whether 'today' is a Monday or a leap year — it's the part of Python that understands the concept of time.
⚡ Quick Answer
Think of the datetime module as a really smart wall calendar that also has a clock built in. Just like you'd glance at your calendar to find out what day it is, calculate how many days until your birthday, or write today's date on a letter, the datetime module lets your Python program do exactly those same things. Without it, Python would have no idea whether 'today' is a Monday or a leap year — it's the part of Python that understands the concept of time.

Every useful program eventually needs to deal with time. A banking app needs to timestamp every transaction. A fitness tracker needs to know how many days you've been on a streak. An e-commerce site needs to calculate whether a coupon has expired. Time is everywhere in software, and Python gives you a clean, built-in way to handle it — the datetime module.

Before the datetime module existed, developers had to manually juggle numbers for days, months, and years, writing messy arithmetic to figure out things like 'what date is 90 days from now?' That's surprisingly error-prone — months have different lengths, leap years exist, and time zones are a nightmare. The datetime module solves all of this by giving you dedicated objects that already understand how calendars work.

By the end of this article you'll know how to get today's date and current time, create specific date and time objects from scratch, calculate the difference between two dates, format dates into human-readable strings, and parse date strings back into date objects. These are skills you'll use in almost every real-world Python project.

The Four Core Classes Inside the datetime Module

The datetime module isn't just one thing — it's a toolbox with four main tools inside it. Understanding which tool to reach for is the first step.

date — Handles only calendar dates: year, month, day. Use this when you don't care about the time of day. Example: a user's birthday, a product release date.

time — Handles only the time of day: hour, minute, second, microsecond. Use this when you don't care about the date. Example: a store's opening hours.

datetime — The combination of both. It holds a year, month, day, hour, minute, second, and microsecond all together. This is the one you'll use most often. Example: the exact moment a user logged in.

timedelta — Represents a duration or difference between two points in time. Think of it as a stopwatch result. Example: 'this event lasts 3 days and 4 hours'.

A common beginner confusion is that the module is called datetime and the class inside it is also called datetime. So when you write datetime.datetime.now() — the first datetime is the module, and the second is the class inside that module. We'll show you a cleaner way to import to avoid this.

datetime_classes_overview.py · PYTHON
1234567891011121314151617181920212223
# First, let's import the specific classes we need from the datetime module.
# This cleaner import style avoids writing 'datetime.datetime' everywhere.
from datetime import date, time, datetime, timedelta

# --- date object: only year, month, day ---
release_date = date(2024, 11, 15)          # November 15, 2024
print("Release date:", release_date)        # Prints the date
print("Year:", release_date.year)           # Access individual parts
print("Month:", release_date.month)
print("Day:", release_date.day)

# --- time object: only hour, minute, second ---
store_opens = time(9, 30, 0)               # 9:30:00 AM
print("\nStore opens at:", store_opens)

# --- datetime object: date AND time together ---
user_login = datetime(2024, 11, 15, 14, 35, 22)  # Nov 15, 2024 at 2:35:22 PM
print("\nUser logged in at:", user_login)

# --- timedelta object: a duration (not a specific moment) ---
trial_period = timedelta(days=14)          # A 14-day free trial
print("\nTrial lasts:", trial_period)
print("Trial days:", trial_period.days)
▶ Output
Release date: 2024-11-15
Year: 2024
Month: 11
Day: 15

Store opens at: 09:30:00

User logged in at: 2024-11-15 14:35:22

Trial lasts: 14 days, 0:00:00
Trial days: 14
🔥
Module vs Class Name:The module `datetime` contains a class also called `datetime`. Using `from datetime import datetime` lets you write `datetime.now()` instead of the redundant-looking `datetime.datetime.now()`. Always prefer the cleaner import in real projects.

Getting Today's Date and the Current Date-Time

The most common thing you'll do with the datetime module is ask Python 'what time is it right now?' There are two methods for this depending on whether you need just the date or the full timestamp.

date.today() returns a date object with today's year, month, and day. No hours, no minutes. Perfect for things like 'show me tasks due today'.

datetime.now() returns a datetime object with the full current timestamp — right down to the microsecond. Use this for logging, timestamps on records, or anything where the exact moment matters.

You can also extract the date portion from a datetime object using the .date() method. This is useful when you receive a full datetime but only need to compare calendar dates — for example, checking if an event happened today regardless of what time it happened.

One thing to note: both today() and now() return your local machine's time. They have no awareness of time zones by default. For time-zone-aware work you'd use datetime.now(timezone.utc), but that's an intermediate topic — let's master the basics first.

getting_current_datetime.py · PYTHON
12345678910111213141516171819202122232425
from datetime import date, datetime

# Get today's date only (no time component)
today = date.today()
print("Today's date:", today)                  # e.g. 2024-11-15
print("Day of week (0=Mon, 6=Sun):", today.weekday())  # Monday=0, Sunday=6
print("Is today a weekday?", today.weekday() < 5)       # True if Mon-Fri

# Get the current full timestamp (date + time)
right_now = datetime.now()
print("\nFull timestamp:", right_now)           # e.g. 2024-11-15 14:35:22.123456
print("Current hour:", right_now.hour)          # Just the hour portion
print("Current minute:", right_now.minute)      # Just the minute portion

# Extract just the date part from a datetime object
login_timestamp = datetime(2024, 11, 15, 8, 45, 0)   # Simulated login time
login_date_only = login_timestamp.date()              # Strip away the time part
print("\nLogin timestamp:", login_timestamp)
print("Login date only:", login_date_only)

# Check if the login happened today
if login_date_only == date.today():
    print("User logged in today!")
else:
    print("Login was on a different day.")
▶ Output
Today's date: 2024-11-15
Day of week (0=Mon, 6=Sun): 4
Is today a weekday? True

Full timestamp: 2024-11-15 14:35:22.847312
Current hour: 14
Current minute: 35

Login timestamp: 2024-11-15 08:45:00
Login date only: 2024-11-15
User logged in today!
⚠️
Pro Tip:Use `date.today()` when you only need to compare calendar days — it's cleaner and avoids accidental time-of-day comparisons. If you compare two `datetime` objects for equality, `2024-11-15 08:00` and `2024-11-15 23:00` are NOT equal even though they're the same day.

Calculating Durations with timedelta — The Date Arithmetic Tool

Here's where datetime really earns its keep. Imagine you're building a subscription service. You need to know when a 30-day trial ends, or whether a user's password hasn't been changed in over 90 days. This is date arithmetic, and timedelta is how you do it.

A timedelta object represents a span of time — not a specific moment, but a duration. You can create one with days, seconds, microseconds, milliseconds, minutes, hours, or weeks. Then you can add or subtract it from a date or datetime object.

You can also subtract two date or datetime objects from each other — the result is automatically a timedelta. This is how you calculate 'how many days between these two events'.

The .days property gives you the total number of whole days in the delta. For anything under a day, use .seconds. If you want the total duration as a single float in seconds, use .total_seconds() — this is especially useful for performance measurements and countdowns.

timedelta_date_arithmetic.py · PYTHON
12345678910111213141516171819202122232425262728293031323334
from datetime import date, datetime, timedelta

# --- Scenario 1: Calculate when a free trial expires ---
trial_start = date(2024, 11, 1)         # Trial started November 1st
trial_duration = timedelta(days=30)     # Free trial lasts 30 days
trial_end = trial_start + trial_duration  # Add the duration to the start date
print("Trial started:", trial_start)
print("Trial ends:", trial_end)          # Should be December 1st

# --- Scenario 2: How many days until an event? ---
today = date.today()
new_year = date(2025, 1, 1)             # Next New Year's Day
days_until_new_year = new_year - today  # Subtracting two dates gives a timedelta
print("\nDays until New Year:", days_until_new_year.days, "days")

# --- Scenario 3: Check if a password is too old (security feature) ---
last_password_change = datetime(2024, 7, 20, 10, 0, 0)  # Changed July 20th
current_time = datetime.now()
password_age = current_time - last_password_change       # timedelta result
max_age = timedelta(days=90)                             # Force reset after 90 days

print("\nPassword age:", password_age.days, "days")
if password_age > max_age:
    print("WARNING: Password is too old! Please reset it.")
else:
    days_left = max_age - password_age
    print(f"Password OK. Must be changed in {days_left.days} days.")

# --- Scenario 4: total_seconds() for precise measurement ---
downtime_start = datetime(2024, 11, 15, 2, 0, 0)  # Server went down at 2:00 AM
downtime_end   = datetime(2024, 11, 15, 2, 47, 33) # Back up at 2:47:33 AM
downtime_duration = downtime_end - downtime_start
print(f"\nServer was down for {downtime_duration.total_seconds()} seconds")
print(f"That's {downtime_duration.seconds // 60} minutes and {downtime_duration.seconds % 60} seconds")
▶ Output
Trial started: 2024-11-01
Trial ends: 2024-12-01

Days until New Year: 47 days

Password age: 118 days
WARNING: Password is too old! Please reset it.

Server was down for 2853.0 seconds
That's 47 minutes and 33 seconds
⚠️
Watch Out:You can subtract two `date` objects or two `datetime` objects — but you CANNOT subtract a `date` from a `datetime` or vice versa. Python will throw a TypeError. Always make sure both operands are the same type before doing date arithmetic.

Formatting and Parsing Dates — strftime and strptime

Right now your date objects print in a format like 2024-11-15. That's clean for a computer, but your users expect to see something like 'Friday, 15 November 2024' or '11/15/2024'. This is where strftime and strptime come in — two methods with confusing names that do opposite things.

strftime means 'string format time' — it takes a datetime object and converts it INTO a formatted string for display. Think of it as 'formatting for output'.

strptime means 'string parse time' — it takes a date string and converts it INTO a datetime object. Think of it as 'reading a date from user input or a file'.

Both use format codes — special placeholders that start with %. For example, %Y means the 4-digit year, %m means the 2-digit month, %d means the day. You combine these like a template to describe how the date is written.

This is one of the most practically useful parts of datetime — nearly every real app needs to display dates nicely and read dates from form inputs or CSV files.

strftime_strptime_formatting.py · PYTHON
1234567891011121314151617181920212223242526272829303132333435363738394041424344
from datetime import datetime

right_now = datetime(2024, 11, 15, 14, 35, 22)  # A fixed datetime for consistent output

# --- strftime: datetime object --> formatted string ---
# Format codes: %Y=4-digit year, %m=month number, %d=day, %B=full month name,
#               %A=full weekday name, %H=hour(24h), %M=minute, %S=second

# Format for a European audience
europe_format = right_now.strftime("%d/%m/%Y")         # 15/11/2024
print("European format:", europe_format)

# Format for an American audience
usa_format = right_now.strftime("%m/%d/%Y")            # 11/15/2024
print("US format:", usa_format)

# A long, human-readable format
friendly_format = right_now.strftime("%A, %d %B %Y")  # Friday, 15 November 2024
print("Friendly format:", friendly_format)

# A format good for filenames (no slashes or spaces)
file_safe_format = right_now.strftime("%Y%m%d_%H%M%S") # 20241115_143522
print("Filename-safe format:", file_safe_format)

# Including the time
full_readable = right_now.strftime("%d %B %Y at %H:%M")
print("Full readable:", full_readable)

# --- strptime: formatted string --> datetime object ---
# Imagine reading a date from a web form or CSV file:
user_input_date = "25/12/2024"    # Christmas Day typed by a user

# Tell strptime exactly what format the string is in
parsed_date = datetime.strptime(user_input_date, "%d/%m/%Y")
print("\nParsed date object:", parsed_date)         # Now it's a real datetime
print("Type:", type(parsed_date))                  # Confirm it's a datetime object
print("Month number:", parsed_date.month)           # Access the month as a number
print("Day of week:", parsed_date.strftime("%A"))   # 'Wednesday'

# Real-world example: reading dates from a CSV log file
log_entry = "2024-11-15 08:45:00"   # Common log file timestamp format
parsed_log_time = datetime.strptime(log_entry, "%Y-%m-%d %H:%M:%S")
print("\nLog timestamp parsed:", parsed_log_time)
print("Log entry hour:", parsed_log_time.hour)
▶ Output
European format: 15/11/2024
US format: 11/15/2024
Friendly format: Friday, 15 November 2024
Filename-safe format: 20241115_143522
Full readable: 15 November 2024 at 14:35

Parsed date object: 2024-12-25 00:00:00
Type: <class 'datetime.datetime'>
Month number: 12
Day of week: Wednesday

Log timestamp parsed: 2024-11-15 08:45:00
Log entry hour: 8
🔥
Memory Trick:Struggling to remember which is which? strfTIME = format for ouTPUT (going out to a string). strpTIME = parse from inPUT (coming in from a string). The 'f' is for 'format out', the 'p' is for 'parse in'.
Featurestrftimestrptime
What it doesConverts datetime → stringConverts string → datetime
DirectionOutput / DisplayInput / Parsing
Called onA datetime object instanceThe datetime class directly
Example callmy_date.strftime('%d/%m/%Y')datetime.strptime('15/11/2024', '%d/%m/%Y')
ReturnsA formatted stringA datetime object
Common use caseDisplaying dates to usersReading dates from forms or files
Raises error if format wrong?No — silently uses wrong codesYes — ValueError if format doesn't match string

🎯 Key Takeaways

  • The datetime module has four core classes: date (calendar day only), time (clock time only), datetime (both combined), and timedelta (a duration). Picking the right class matters.
  • Subtracting two datetime objects gives you a timedelta. Adding a timedelta to a date gives you a new date. This is how all date arithmetic works — no manual day-counting needed.
  • strftime formats a datetime INTO a string for display; strptime parses a string INTO a datetime object. The format codes (like %Y, %m, %d) must exactly match the string structure or you get a ValueError.
  • Use date.today() for calendar-day comparisons and datetime.now() for full timestamps. Never compare a date object directly with a datetime object — they're different types and Python will raise a TypeError.

⚠ Common Mistakes to Avoid

  • Mistake 1: Confusing the module name with the class name — Writing import datetime and then trying to call datetime.now() raises AttributeError because now() belongs to the datetime CLASS inside the datetime MODULE, not the module itself. Fix it by using from datetime import datetime so datetime.now() works, OR keep the full path and write datetime.datetime.now().
  • Mistake 2: Mismatching the strptime format string with the actual date string — If your string is '15-11-2024' but your format is '%d/%m/%Y' (using slashes), Python raises a ValueError: time data does not match format. Always make sure every separator, space, and code in your format string exactly mirrors the structure of the date string you're parsing.
  • Mistake 3: Subtracting a date from a datetime (or vice versa) — Writing datetime.now() - date.today() raises a TypeError: unsupported operand type(s) because one is a datetime object and the other is a date object. Fix it by converting the date to a datetime first: datetime.now() - datetime.combine(date.today(), time.min), or compare only dates using datetime.now().date() - date.today().

Interview Questions on This Topic

  • QWhat's the difference between the `date`, `time`, and `datetime` classes in Python's datetime module, and when would you use each one?
  • QIf you receive a date as a string in the format 'DD-MM-YYYY' from an API and need to check whether it's more than 30 days in the past, how would you do that in Python?
  • QWhat does `timedelta.total_seconds()` return that `.days` and `.seconds` don't — and can you give a scenario where using `.days` alone would give you a wrong answer?

Frequently Asked Questions

How do I get today's date in Python?

Use from datetime import date then call date.today(). This returns a date object with the current year, month, and day based on your system clock. If you also need the current time, use datetime.now() from the datetime class instead.

What is the difference between datetime.now() and datetime.today() in Python?

For most practical purposes they return the same result — the current local date and time. The technical difference is that datetime.now() accepts an optional tz (timezone) argument to return timezone-aware datetimes, while datetime.today() always returns a naive (timezone-unaware) datetime. Prefer datetime.now() for new code since it's more flexible.

Why do I get 'TypeError: unsupported operand type' when subtracting dates?

This happens when you try to subtract a date object from a datetime object or vice versa. Python won't automatically convert between them. The fix is to ensure both values are the same type — either extract the .date() from your datetime first, or convert your date to a datetime using datetime.combine(my_date, time.min) before doing the arithmetic.

🔥
TheCodeForge Editorial Team Verified Author

Written and reviewed by senior developers with real-world experience across enterprise, startup and open-source projects. Every article on TheCodeForge is written to be clear, accurate and genuinely useful — not just SEO filler.

← Previouscollections Module in PythonNext →regex Module in Python
Forged with 🔥 at TheCodeForge.io — Where Developers Are Forged