Skip to content

Python Date & Time

Handling dates and times is a common requirement in programming. Python offers powerful modules for working with dates, times, and time intervals.

The primary built-in modules are:

  • time: Provides functions related to system time, including time measurement and sleeping. Often lower-level.
  • datetime: Offers classes for manipulating dates and times in a more object-oriented way. Generally preferred for most date/time calculations and representation.
  • calendar: Provides calendar-related functions, like generating text calendars.

Many systems measure time as the number of seconds that have passed since a specific starting point called the Epoch. For Unix-based systems (including Linux and macOS), the epoch is typically January 1, 1970, 00:00:00 (UTC). Windows may use a different epoch for some system functions but Python’s time module consistently uses the Unix epoch.

The function time.time() returns the current time as a floating-point number representing seconds since the epoch. This value is sometimes referred to as “Unix timestamp” or “ticks” (though ‘ticks’ can have other meanings in different contexts).

#!/usr/bin/env python3
import time
seconds_since_epoch = time.time()
print(f"Seconds since epoch: {seconds_since_epoch}")

This would produce output like:

Seconds since epoch: 1678886400.123456

Working directly with epoch seconds can be useful for simple time difference calculations, but representing specific dates and times usually requires more structured formats.

Several functions in the time module work with or return a tuple-like object called time.struct_time. It represents a specific point in time with components like year, month, day, hour, minute, etc.

The structure contains the following attributes (accessible by index or name):

IndexAttributeValues
0tm_yearYear (e.g., 2023)
1tm_monMonth (1-12)
2tm_mdayDay of the month (1-31)
3tm_hourHour (0-23)
4tm_minMinute (0-59)
5tm_secSecond (0-61; includes leap seconds)
6tm_wdayDay of the week (0=Monday to 6=Sunday)
7tm_ydayDay of the year (1-366)
8tm_isdstDaylight Saving Time flag (0, 1, or -1 if unknown)

time.localtime() converts seconds since the epoch (or the current time if no argument is given) into a struct_time representing the local time.

#!/usr/bin/env python3
import time
local_time_struct = time.localtime() # Uses current time
print(f"Local time struct: {local_time_struct}")
# Accessing elements
print(f"Year: {local_time_struct.tm_year}")
print(f"Hour: {local_time_struct.tm_hour}")

time.gmtime() works similarly but returns the struct_time in Coordinated Universal Time (UTC).

While struct_time is structured, it’s not very human-readable. Python provides functions to format time into strings.

time.asctime(): Converts a struct_time (or current local time if no argument) into a standard 24-character string format.

#!/usr/bin/env python3
import time
# Using current local time
ascii_time_now = time.asctime()
print(f"Formatted time (asctime): {ascii_time_now}")
# Using a specific struct_time
local_time_struct = time.localtime()
ascii_time_local = time.asctime(local_time_struct)
print(f"Formatted time from struct: {ascii_time_local}")

Output might look like: Formatted time (asctime): Wed Mar 15 12:30:00 2023

time.strftime(): Provides much more flexibility by allowing custom format codes.

#!/usr/bin/env python3
import time
local_time_struct = time.localtime()
# Example format codes:
# %Y - Year with century (e.g., 2023)
# %m - Month as zero-padded decimal (01-12)
# %d - Day of the month as zero-padded decimal (01-31)
# %H - Hour (24-hour clock) as zero-padded decimal (00-23)
# %M - Minute as zero-padded decimal (00-59)
# %S - Second as zero-padded decimal (00-61)
# %a - Abbreviated weekday name (Sun, Mon, ...)
# %A - Full weekday name (Sunday, Monday, ...)
# %b - Abbreviated month name (Jan, Feb, ...)
# %B - Full month name (January, February, ...)
formatted_string = time.strftime("%Y-%m-%d %H:%M:%S", local_time_struct)
print(f"Custom format 1: {formatted_string}")
formatted_string_verbose = time.strftime("%A, %B %d, %Y (%I:%M:%S %p %Z)", local_time_struct)
# %I - Hour (12-hour clock), %p - AM/PM, %Z - Timezone name
print(f"Custom format 2: {formatted_string_verbose}")

strftime is very useful for creating human-readable date/time strings in various formats.

Key functions in the time module:

FunctionDescription
time.time()Returns current time as seconds since the epoch (float).
time.sleep(secs)Suspends execution for the specified number of seconds (can be float).
time.localtime([secs])Converts seconds since epoch to local struct_time.
time.gmtime([secs])Converts seconds since epoch to UTC struct_time.
time.mktime(t)Converts a local struct_time t back into seconds since the epoch.
time.asctime([t])Converts a struct_time t to a standard formatted string.
time.strftime(format[, t])Formats a struct_time t into a string according to format codes.
time.strptime(string, format)Parses a string representing a time according to format codes, returning a struct_time.
time.perf_counter()Returns a high-resolution performance counter value (for measuring short durations). The absolute value is undefined, only the difference between calls is valid.
time.process_time()Returns the sum of system and user CPU time of the current process. Use for benchmarking CPU usage.

Note: time.clock() was deprecated in Python 3.3 and removed in 3.8. Use time.perf_counter() or time.process_time() instead, depending on whether you need wall-clock time for performance measurement or CPU time.

While the time module is useful, the datetime module provides a more powerful and object-oriented way to work with dates and times. It’s generally recommended for most applications.

Key classes in datetime:

  • datetime.date: Represents a date (year, month, day).
  • datetime.time: Represents a time (hour, minute, second, microsecond).
  • datetime.datetime: Represents both date and time.
  • datetime.timedelta: Represents a duration or difference between two dates or times.
  • datetime.timezone: Represents timezone information (more robust timezone handling often requires external libraries like pytz or uses zoneinfo in Python 3.9+).
#!/usr/bin/env python3
from datetime import datetime, date, timedelta
# Get current date and time
now = datetime.now()
print(f"Current datetime: {now}")
# Get current date
today = date.today()
print(f"Current date: {today}")
# Create specific date and datetime objects
d1 = date(2024, 7, 20)
dt1 = datetime(2024, 7, 20, 15, 30, 0)
print(f"Specific date: {d1}")
print(f"Specific datetime: {dt1}")
# Formatting using strftime (also available on datetime objects)
print(f"Formatted datetime: {now.strftime('%Y/%m/%d %H:%M')}")
# Date arithmetic using timedelta
yesterday = today - timedelta(days=1)
next_week = today + timedelta(weeks=1)
print(f"Yesterday was: {yesterday}")
print(f"Next week is: {next_week}")
# Calculate difference between datetimes
diff = now - dt1
print(f"Difference between now and dt1: {diff}")
print(f"Difference in seconds: {diff.total_seconds()}")
# Parsing strings into datetime objects
date_string = "2023-01-15 10:00:00"
parsed_dt = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")
print(f"Parsed datetime: {parsed_dt}")

The datetime module offers a cleaner interface for date and time arithmetic and manipulation compared to time.struct_time.

The calendar module provides functions related to the calendar, like generating monthly or yearly text calendars and determining leap years.

#!/usr/bin/env python3
import calendar
# Get a formatted text calendar for March 2024
cal_text = calendar.month(2024, 3)
print("Calendar for March 2024:")
print(cal_text)
# Check for leap year
is_leap = calendar.isleap(2024)
print(f"Is 2024 a leap year? {is_leap}")
# Get the weekday code for a specific date (0=Monday)
weekday_code = calendar.weekday(2024, 3, 15)
print(f"Weekday code for 2024-03-15: {weekday_code} (Friday)")
# Set first day of week (e.g., Sunday = 6)
# calendar.setfirstweekday(calendar.SUNDAY)
# cal_text_sun_start = calendar.month(2024, 3)
# print("\nCalendar starting on Sunday:")
# print(cal_text_sun_start)

For more advanced date/time handling, especially involving time zones or parsing complex date strings, consider these popular third-party libraries:

  • pytz: Provides comprehensive timezone support (using the Olson timezone database). Essential for accurate timezone-aware applications.
  • python-dateutil: Offers powerful extensions to datetime, including advanced parsing of date strings in various formats.
  • zoneinfo (Built-in, Python 3.9+): Provides access to the system’s IANA time zone database, offering a standard library alternative to pytz for many use cases.