Mastering timezones in Python with UTC

This is the reason why you should use UTC for anything time-related.

You’re building a calendar application but stumble across a common problem: what if I have a user in New York scheduling a meeting with someone in Phoenix, Arizona? Better yet, what if today’s date is March 7th and one of the users schedules a meeting for March 12th?

There’s 2 major problems here that will catch you off guard if you’re not aware:

  • Different time zones: New York is in the eastern timezone, Phoenix is in Mountain time.

  • Daylight Savings: You have to take into consideration daylight savings (aka: “spring forward”).

And to top it all off, Arizona does not observe daylight savings. What if these 2 users also schedule a meeting for November 30th? You’ll have to take into account daylight savings “leap forward”.

Thankfully, the solution is a lot easier than you might think, and it’s to always work with Coordinated Universal Time (UTC) until you’re ready to have the users see the time.

» UTC is the global standard time that doesn’t change with seasons or geography, as it’s the same everywhere on Earth at any given time. To give some geographical perspective, it’s equivalent to the timezone that cities like London, Dublin, Lisbon, and Reykjavík are in.

The Timezone Trap

Let’s see what this trap looks like in code. Here’s how we may approach the meeting schedule problem:

from datetime import datetime

def schedule_meeting(date_str, time_str):
    meeting_time = datetime.strptime(
         f"{date_str} {time_str}", "%Y-%m-%d %H:%M"
    )
    return meeting_time

meeting = schedule_meeting("2024-03-10", "14:30")
print(f"Meeting at: {meeting}")

And yes, it does work. But, there’s a few concerns with this:

  • Ambiguity: Is this 2:30 PM in New York? London? Tokyo? Punxsutawney?

  • Silent failures: Your code works locally but breaks when thrown onto your production servers.

  • DST disasters: Daylight saving time transitions cause times to jump or disappear entirely

Thankfully, starting in Python 3.12 the date time module warns you of not using timezone naive objects. In fact, the above code will be deprecated in “a future version” of Python.

The Solution and Rules

When working with dates and times, follow these 3 rules:

  • Always use timezone-aware date time objects.

  • Always calculate times using UTC.

  • Convert to local time only for display

Following these rules, our meeting scheduler might look something like this:

from datetime import datetime, timezone

def schedule_meeting(date_str, time_str): 
    meeting_time = datetime.strptime(
        f"{date_str} {time_str}", "%Y-%m-%d %H:%M"
    )
    return meeting_time.replace(tzinfo=timezone.utc)

meeting = schedule_meeting("2024-03-10", "14:30") print(f"Meeting at: {meeting}")

As a meteorologist who works in only UTC (and refuses to work in any other timezone), these are my “best practice” guidelines in addition to the 3 rules above:

  • Store everything in UTC: Databases, logs, API responses, etc

  • Use ISO 8601 format: 2024-03-15T14:30:00Z is unambiguous worldwide

  • Test with multiple timezones: Your code should work regardless of deployment location

Real-World Impact

If you’re not carefully paying attention, impacts can be quite devastating. Bugs like this have caused:

  • Financial systems to process transactions at wrong times

  • Scheduled maintenance to run during business hours instead of off-hours

  • Log analysis to miss or double-count events during DST transitions

  • International teams to miss meetings due to inconsistent time handling

By working exclusively in UTC and converting to local time only for user interfaces, you eliminate these entire classes of problems before they can occur.

The Bottom Line

Every timezone-related bug you'll ever encounter stems from the same root cause: mixing timezone-naive and timezone-aware datetime objects, or trying to do business logic in local time.

Start with UTC, stay in UTC, and convert to local time only when humans need to read it. Your applications will be more reliable, your debugging sessions shorter, and your users happier.

Remember: messing around with times can be difficult, but keeping things consistent and using the tools Python gives you makes it significantly more manageable.

Happy coding!

📧 Join the Python Snacks Newsletter! 🐍

Want even more Python-related content that’s useful? Here’s 3 reasons why you should subscribe the Python Snacks newsletter:

  1. Get Ahead in Python with bite-sized Python tips and tricks delivered straight to your inbox, like the one above.

  2. Exclusive Subscriber Perks: Receive a curated selection of up to 6 high-impact Python resources, tips, and exclusive insights with each email.

  3. Get Smarter with Python in under 5 minutes. Your next Python breakthrough could just an email away.

You can unsubscribe at any time.

Interested in starting a newsletter or a blog?

Do you have a wealth of knowledge and insights to share with the world? Starting your own newsletter or blog is an excellent way to establish yourself as an authority in your field, connect with a like-minded community, and open up new opportunities.

If TikTok, Twitter, Facebook, or other social media platforms were to get banned, you’d lose all your followers. This is why you should start a newsletter: you own your audience.

This article may contain affiliate links. Affiliate links come at no cost to you and support the costs of this blog. Should you purchase a product/service from an affiliate link, it will come at no additional cost to you.

Reply

or to participate.