Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
217: The datetime Module in Depth
A few years ago, I was reviewing a PR for a colleague who had built a "daily" cleanup script. He used datetime.now() to check if the current date matched the scheduled cleanup date. It worked perfectly in development. Then we deployed it to a cluster of servers across three different AWS regions. Suddenly, the script was running twice for some users and not at all for others because the servers were set to UTC, but the logic was implicitly assuming the local time of the developer's laptop in New York. He spent an entire weekend chasing a "ghost" bug that turned out to be the classic mistake of using naive datetime objects.
If you've ever felt like time is a lie in programming, you're not alone. The datetime module is powerful, but it has some sharp edges that will cut you if you aren't careful. Most people know how to get the current time, but to actually master this module, you need to understand the distinction between "naive" and "aware" objects.
The Naive vs. Aware Divide
In Python, a naive object is one that doesn't contain any timezone information. It's just a set of numbers (year, month, day, etc.). The problem is that Python doesn't know if that time is UTC, EST, or Martian Standard Time—it just assumes it's "whatever the system says." An aware object, on the other hand, includes a tzinfo object that anchors it to a specific point in global time.
I always recommend sticking to UTC internally for everything. Store your data in UTC, do your math in UTC, and only convert to a local timezone at the very last second when you're displaying a string to a human. Since Python 3.9, the zoneinfo module has become the gold standard for this. Here is how you actually handle a timezone-aware object:
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
# The wrong way (Naive)
naive_now = datetime.now()
# The right way (Aware - UTC)
utc_now = datetime.now(timezone.utc)
# Converting UTC to a specific local time
tokyo_time = utc_now.astimezone(ZoneInfo("Asia/Tokyo"))
print(f"UTC: {utc_now}")
print(f"Tokyo: {tokyo_time}")
Slicing Time with Timedelta
You'll rarely just want the current time; usually, you want to know when something expires or how long ago a user logged in. This is where timedelta comes in. Think of a datetime object as a point on a map and a timedelta as the distance between two points.
One thing that trips people up is that you can't just add "one month" to a date using timedelta because months vary in length. timedelta handles days, seconds, and microseconds. If you need to do complex calendar math (like "the last Friday of next month"), you'll want to look into the dateutil library, but for 90% of your tasks, timedelta is your best friend.
from datetime import datetime, timedelta
# Calculate a trial expiration date (14 days from now)
start_date = datetime.now(timezone.utc)
expiry_date = start_date + timedelta(days=14)
# Find out exactly how much time is left
time_remaining = expiry_date - start_date
print(f"Seconds until expiration: {time_remaining.total_seconds()}")
Parsing the Chaos of Date Strings
At some point, you're going to have to deal with a CSV or an API that sends you dates as strings. This is where strptime (string-parse time) and strftime (string-format time) come in. I remember a trick to keep these straight: p is for parse (string to object), and f is for format (object to string).
The format codes (like %Y for a four-digit year) feel like a secret language, but you'll memorize the common ones quickly. Just be wary of %y (lowercase), which only gives you the last two digits of the year—a recipe for Y2K-style disasters if you're not careful.
# Parsing a log timestamp: "2023-10-25 14:30:05"
log_string = "2023-10-25 14:30:05"
dt_object = datetime.strptime(log_string, "%Y-%m-%d %H:%M:%S")
# Formatting it for a friendly user UI: "Oct 25, 2023"
friendly_date = dt_object.strftime("%b %d, %Y")
print(friendly_date) # Output: Oct 25, 2023
📋 Practical Task
Exercise: Global Webinar Countdown Timer
You are building a notification system for a global webinar. The webinar starts at a fixed UTC time, but you need to display the countdown and the local start time for users in different cities.
Your Task: Write a script that does the following:
- Define a webinar start time for December 1st, 2025, at 15:00 (3 PM) UTC. Ensure this object is timezone-aware.
- Create a list of cities and their corresponding IANA timezone strings (e.g.,
{"New York": "America/New_York", "London": "Europe/London", "Sydney": "Australia/Sydney"}). - For each city, calculate and print the local start time of the webinar in a readable format (e.g., "New York: 2025-12-01 10:00:00").
- Calculate the total number of days and hours remaining from the moment the script is run until the webinar starts.
Hint: Use zoneinfo.ZoneInfo for the timezones and datetime.now(timezone.utc) to get the current time for your calculations.
There are no comments for now.