How to create a wordclock with Python
How I built a word clock that tells time in three zones
Some projects are born out of necessity; others, out of sheer “I never did this before so I guess it will turn out great”-attitude. This project firmly falls into the latter category. Inspired by the concept of word clocks (thanks Waldek Mastykarz) and motivated by the challenge of tackling time zones, I wanted to create a Python-powered word clock that tells time in phrases across three zones: Pacific Time (PT), Greenwich Mean Time (GMT), and Indian Standard Time (IST).

How I approached it
When I’m tackling something new, it helps to divide and conquer. Here’s how I broke the problem down into smaller steps:
Displaying time in words
The first step was figuring out how to translate digital time into phrases like “It’s a quarter past six.” I created rules based on the minute ranges:
- If the minute is between
0and5, show “It’s [hour] o’clock.” - If the minute is between
15and20, show “It’s a quarter past [hour].” - If the minute is between
35and40, show “It’s twenty-five to [next hour].”
I stored these rules in a function called get_highlighted_phrases, which dynamically selects phrases to highlight based on the current time.
Building the clock GUI
Once I had the logic for the words, I needed a way to display them. I used Tkinter to build a graphical interface where the phrases are arranged in a circle, mimicking the feel of a classic clock. Each time zone has its own circle with phrases like “It’s” and “half past” positioned radially.
Handling time zones
Here’s where things got tricky. Time zones aren’t just about adding or subtracting hours. Some, like Indian Standard Time (IST), involve half-hour offsets. To handle this, I used the pytz library for PT and GMT but calculated IST manually using:
def get_ist_from_gmt(gmt_time):
return gmt_time + timedelta(hours=5, minutes=30)
AM/PM quirks
One of the most unexpected challenges was ensuring the AM/PM indicator displayed correctly for IST, especially during transitions like midnight. I ended up flipping AM/PM specifically for IST using a conditional flag:
def get_am_pm(hour_24, invert=False):
if invert:
return "AM" if hour_24 >= 12 else "PM"
else:
if hour_24 == 0:
return "AM"
elif hour_24 < 12:
return "AM"
elif hour_24 == 12:
return "PM"
else:
return "PM"
Debug tricks
Testing multiple time zones in real time meant countless print() statements, which eventually morphed into a helpful debugging function:
def debug_current_times(pt_time, gmt_time, ist_time):
print("Debugging Current Times:")
print(f"PT: {format_time(pt_time)}")
print(f"GMT: {format_time(gmt_time)}")
print(f"IST: {format_time(ist_time, invert_am_pm=True)}")
print("-" * 30)
Where you can find the code
If you’re curious about how it all came together, or you want to try it yourself, check out the code at https://github.com/LuiseFreese/wordclock
Published on:
Learn moreRelated posts
You are holding GitHub Copilot Wrong!
Most developers think that one can’t really use GitHub Copilot wrong. There is a chat interface that lets you also choose a model, so th...
You are holding GitHub Copilot Wrong!
Part 0 showed why constant prompting, re-prompting, and steering GitHub Copilot feels fragile. Not because Copilot is unreliable, but because ...
Building a Multi-Hierarchy Ticket Classification System (Because Keywords Aren't Enough)
Look, I love a good keyword-based system as much as the next developer. They’re fast, predictable, and when your user says “VPN,&r...
Secretless cross-tenant dataverse access
Client secrets are like hiding your house key under the mat; easy to grab and impossible to audit. Certificates are just slightly better, beca...
How Azure CLI handles your tokens and what you might be ignoring
Running az login feels like magic. A browser pops up, you pick an account, and from then on, everything just works. No more passwords, no more...
How Dev Proxy teaches you to make your apps more resilient
I added Microsoft Dev Proxy to my Mermaid → Dataverse converter, because I wanted to test how it handled rate limits and API errors. What I go...
Building Azure functions that never store secrets — ever
What if your function could hit Microsoft Graph with no client secrets, no certs, and no Key Vault entries? That is exactly what a Managed id...
Introducing Mermaid to Dataverse Converter
Why diagrams matter (and why they usually fail us) Entity-Relationship Diagrams (ERDs) are the universal shorthand for talking about data mode...
It’s OK to be seen trying
It’s OK to be seen trying Somewhere along the way, we started believing that you’re only allowed to speak after you’ve figured everything out....
Stuck in pilot - Part 1: no foundations, no future
“We just need to test the AI. We’ll figure out the data later.” That sentence has quietly killed more AI pilots than any model failure ever ...