Get AI summaries of any video or article — Sign up free
Python Tutorial: Datetime Module - How to work with Dates, Times, Timedeltas, and Timezones thumbnail

Python Tutorial: Datetime Module - How to work with Dates, Times, Timedeltas, and Timezones

Corey Schafer·
5 min read

Based on Corey Schafer's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

Use naive datetimes for simple calculations, but switch to aware datetimes when time zones or daylight saving time matter.

Briefing

Python’s datetime module is the backbone for working with dates, times, time deltas, and time zones—but the biggest practical hurdle is knowing when to use “naive” versus “aware” datetimes. Naive datetimes lack enough information to resolve time zones or daylight saving time, making them simpler to manipulate but risky for anything that depends on real-world offsets. Aware datetimes carry time zone (and DST) context, preventing silent mistakes when converting between regions.

The tutorial starts with the basics: importing the module and creating a date using year, month, and day. It highlights a common pitfall—passing leading zeros for integers like 07 triggers a syntax error, so single-digit months and days must be provided as plain integers. From there, it demonstrates convenience constructors such as date.today() for the current local date, plus attribute accessors like year, month, and day. It also compares weekday() and isoweekday(), noting the different numbering schemes: weekday uses Monday=0 through Sunday=6, while ISO weekday uses Monday=1 through Sunday=7.

Time deltas then take center stage as the difference between two dates or times. A timedelta representing seven days can be added to a date to compute “one week from now,” or subtracted to compute “one week ago.” The tutorial also draws a crucial type distinction: adding or subtracting a timedelta from a date yields another date, while subtracting one date from another yields a timedelta. That distinction is used to calculate time until a birthday by subtracting the current date from a fixed birthday date, then extracting results via timedelta.days and timedelta.total_seconds() (to get a seconds-based measure rather than just whole days).

For time-of-day handling, datetime.time focuses on hours, minutes, seconds, and microseconds, while datetime.datetime combines both date and time. The tutorial shows how to access components (like dt.date() and dt.time()) and how to shift datetimes by adding timedelta objects. It further compares constructors like datetime.today(), datetime.now(), and datetime.utcnow(), clarifying that “UTC” in the method name doesn’t automatically make the object time zone aware—TZ info still matters.

Time zones are handled with the third-party pytz package, installed via pip, because Python’s documentation recommends it for using the time zone database. The workflow emphasizes best practice: build time zone aware datetimes in UTC (using tzinfo=pytz.UTC), then convert to other zones with astimezone(pytz.timezone(...)). The tutorial demonstrates converting from UTC to US Mountain time using the correct pytz zone string (e.g., us_Mountain) and explains how to discover valid zone names by iterating over pytz.all_timezones.

Finally, it addresses the conversion problem that naive datetimes can’t be directly converted with astimezone—pytz raises an error when tzinfo is missing. The fix is to “attach” time zone context using localize(): create a naive local datetime, then localize it with the appropriate pytz time zone (like us_Mountain) to make it aware before converting to US Eastern time. The tutorial closes with practical formatting tools: ISO output via isoformat(), custom string formatting using strftime format codes, and parsing strings back into datetimes with strptime (via datetime.strptime).

Cornell Notes

The core lesson is how to manage Python datetimes safely: naive datetimes lack time zone/DST context, while aware datetimes include tzinfo so conversions are reliable. The datetime module supports dates (year-month-day), times (hour-minute-second-microsecond), and combined datetimes, plus timedelta for differences and arithmetic. Date arithmetic works differently depending on what’s subtracted or added: date ± timedelta → date, while date − date → timedelta. For time zones, pytz is used to create UTC-aware datetimes and convert them with astimezone; naive datetimes must first be made aware using localize(). Formatting and parsing complete the workflow with isoformat(), strftime, and strptime.

What’s the practical difference between naive and aware datetimes in Python?

Naive datetimes don’t include enough information to determine a time zone or daylight saving time, so they’re easier to work with but can lead to incorrect results when offsets matter. Aware datetimes include tzinfo so Python can track the correct UTC offset and DST rules during conversions. The tutorial stresses that time zone conversions require aware datetimes; otherwise astimezone raises an error.

How do weekday() and isoweekday() differ, and why does it matter?

weekday() uses Monday=0 and Sunday=6, while isoweekday() uses Monday=1 and Sunday=7. That difference changes the numeric value you get for the same day. For example, if the current day is Tuesday, weekday() returns 1 and isoweekday() returns 2, matching each scheme’s numbering.

What does timedelta represent, and how do results differ when adding/subtracting it versus subtracting two dates?

timedelta represents a duration—the difference between two dates or times. Adding or subtracting a timedelta to/from a date produces another date (e.g., today + 7 days). Subtracting one date from another produces a timedelta (e.g., birthday_this_year − today). The tutorial then extracts timedelta.days and timedelta.total_seconds() to get day counts or second-level precision.

Why does datetime.utcnow() not automatically produce a time zone aware datetime?

Even though the method name includes “UTC,” the tutorial shows that tzinfo can still be set to None. That means the datetime may represent UTC time but remains naive with respect to time zone awareness. To make it aware, tzinfo must be explicitly set (for example, tzinfo=pytz.UTC).

How do you convert between time zones with pytz, and what’s the fix when starting from a naive datetime?

For an aware datetime, convert with astimezone(pytz.timezone('us_Mountain')) (after creating an aware UTC datetime). If the datetime is naive, astimezone cannot be applied; pytz requires localize(). The tutorial’s flow is: create naive local datetime with datetime.now(), then Mountain time zone = pytz.timezone('US_Mountain') and dt_mountain = Mountain time zone.localize(dt_mountain_naive), then convert to Eastern with astimezone(pytz.timezone('US_Eastern')).

What are the main formatting and parsing tools shown for datetimes?

To display in a standard form, use isoformat(). For custom human-readable output, use strftime with format codes (e.g., %B for full month, %d for two-digit day, %Y for full year). To convert a string back into a datetime, use datetime.strptime(string, format) where the format matches the string’s structure; the tutorial uses strptime to parse a formatted date string into a datetime object.

Review Questions

  1. When would you choose a naive datetime over an aware one, and what risk does the naive choice introduce?
  2. If you subtract two dates in datetime, what type do you get back, and how would you extract “days until” from it?
  3. Why must localize() be used before astimezone() when the datetime starts as naive?

Key Points

  1. 1

    Use naive datetimes for simple calculations, but switch to aware datetimes when time zones or daylight saving time matter.

  2. 2

    Create dates with datetime.date(year, month, day) using plain integers—leading zeros like 07 cause syntax errors.

  3. 3

    Use timedelta for duration arithmetic: date ± timedelta yields a date, while date − date yields a timedelta.

  4. 4

    Prefer UTC as the baseline for time zone aware work, then convert with astimezone() to the target zone.

  5. 5

    With pytz, convert aware datetimes directly using astimezone(pytz.timezone(...)), but make naive datetimes aware first using localize().

  6. 6

    Format datetimes for output with isoformat() or strftime, and parse strings back with datetime.strptime() using matching format codes.

Highlights

The tutorial’s clearest type rule: date ± timedelta returns a date, but date − date returns a timedelta.
UTC-aware datetimes require explicit tzinfo (e.g., tzinfo=pytz.UTC); “UTC” in a method name doesn’t guarantee awareness.
pytz conversion fails on naive datetimes—localize() is the required step before astimezone().
weekday() and isoweekday() use different numbering conventions, so the same weekday can map to different integers.
timedelta.total_seconds() provides a seconds-level measure beyond timedelta.days for finer-grained intervals.

Topics

  • Naive vs Aware Datetimes
  • Timedelta Arithmetic
  • Time Zone Conversion with pytz
  • Formatting with strftime
  • Parsing with strptime

Mentioned