Basic Alarm Clock
Abstract
Section titled “Abstract”An alarm clock teaches a deceptively rich set of concepts in a small amount of code: parsing user input that represents a time, comparing the current time against a target, looping until that target is reached, and triggering an external effect (sound) once it is. In this project you will build a command-line alarm clock that lets the user enter a 24-hour-format time and waits until exactly that moment to play an alert.
Along the way you will learn:
- How Python represents time with the
datetimeandtimemodules. - The polling pattern: “do something until a condition is true.”
- How to play sounds across platforms.
- How to validate human-friendly input.
- How a one-shot alarm grows into a scheduler with snooze, multiple alarms, and persistence.
Prerequisites
Section titled “Prerequisites”- Python 3.6 or above.
- A text editor or IDE.
- A working speaker. (Headphones if a 3 AM alarm test would disturb anyone.)
- Familiarity with running scripts from the terminal.
Concepts You Will Use
Section titled “Concepts You Will Use”| Concept | Purpose |
|---|---|
datetime | Get the current date and time, format it as text, parse text back into a time object. |
time.sleep(seconds) | Pause execution. Used so we do not check the clock millions of times per second. |
winsound / playsound / pygame.mixer | Make noise when the alarm fires. Choice depends on your OS. |
String formatting (strftime) | Turn a datetime object into a string like "14:30:00". |
| Polling loop | A while True loop that wakes periodically and checks whether the alarm time has arrived. |
Getting Started
Section titled “Getting Started”Create the project
Section titled “Create the project”- Create a folder named
basic-alarm-clock. - Inside it, create
basicalarmclock.py. - (Optional) drop a custom
alarm.wavfile in the folder to use as the alert sound.
Write the code
Section titled “Write the code”Basic Alarm Clock
pch.viewSource# Basic Alarm Clock
# Importing the libraries
import datetime
import time
import winsound
# Defining the alarm function
def alarm(Timing):
altime = str(datetime.datetime.now().strptime(Timing,"%I:%M %p"))
altime = altime[11:-3]
print(altime)
Horeal = altime[:2]
Horeal = int(Horeal)
Mireal = altime[3:5]
Mireal = int(Mireal)
print(f"Done, alarm is set for {Timing}")
while True:
if Horeal == datetime.datetime.now().hour:
if Mireal == datetime.datetime.now().minute:
print("Alarm is running")
winsound.PlaySound('abc',winsound.SND_LOOP)
elif Mireal<datetime.datetime.now().minute:
break
# Taking user input
print("Set a time to alarm(HH:MM AM/PM)")
Alarm_Time = input("Enter the time of alarm to be set: ")
alarm(Alarm_Time) Run it
Section titled “Run it”C:\Users\username\Documents\basic-alarm-clock> python basicalarmclock.py
Enter the time of alarm to be set (HH:MM:SS, 24-hour): 14:30:00
Alarm is set for 14:30:00
Waiting for alarm time...
*Alarm sound plays*
Wake Up! Wake Up!💡 To test without waiting hours, set the alarm one minute into the future.
How it fits together
Section titled “How it fits together”Read from the top: this is what runs when you execute the file, and which function calls which. It is generated from the code, so it cannot drift from it.
flowchart TD
RUN(["python basicalarmclock.py"])
alarm("alarm")
RUN --> alarm
Step-by-Step Explanation
Section titled “Step-by-Step Explanation”1. Import what you need
Section titled “1. Import what you need”import datetime
import time
import winsound # Windows only — see "Cross-platform sound" belowdatetimegives youdatetime.datetime.now(), which returns the current local date and time.timegives youtime.sleep(seconds)for pausing.winsoundplays a.wavfile with one call. It only works on Windows. macOS and Linux need a different approach.
2. Ask for the alarm time
Section titled “2. Ask for the alarm time”alarm_time = input("Enter the time of alarm (HH:MM:SS, 24-hour): ")
print(f"Alarm is set for {alarm_time}")Using 24-hour format (14:30:00 instead of 2:30:00 PM) is the simplest choice: it avoids ambiguity, and strftime("%H:%M:%S") produces the same format directly.
3. Poll the clock
Section titled “3. Poll the clock”while True:
now = datetime.datetime.now().strftime("%H:%M:%S")
if now == alarm_time:
print("Wake Up! Wake Up!")
winsound.PlaySound("alarm.wav", winsound.SND_ASYNC)
break
time.sleep(1)datetime.datetime.now()returns a full date+time object..strftime("%H:%M:%S")formats it asHH:MM:SS(zero-padded).- The comparison is a string equality check — both sides are strings in the same format.
winsound.SND_ASYNCplays the sound in the background so the nextprintis not delayed.time.sleep(1)is the key to making this loop efficient. Without it, Python would check the clock millions of times per second and pin a CPU core.
4. Why we sleep for one second
Section titled “4. Why we sleep for one second”If the alarm is set for 14:30:00, we have exactly one second during which the time string equals "14:30:00". Sleeping for more than a second could cause us to skip past it entirely. One second is the right balance.
Cross-Platform Sound
Section titled “Cross-Platform Sound”winsound only exists on Windows. For a program that works everywhere, use playsound (any OS) or pygame.mixer:
pip install playsound==1.2.2from playsound import playsound
playsound("alarm.wav")Or with Pygame:
from pygame import mixer
mixer.init()
mixer.music.load("alarm.wav")
mixer.music.play()If you have no .wav file handy, beep the terminal:
print("\a") # ASCII bell — terminal may flash or beepRobust Input
Section titled “Robust Input”The basic version accepts any string. A malformed value like "14:30" (missing seconds) silently fails — the loop just never matches. Validate up front:
from datetime import datetime
while True:
raw = input("Enter alarm time (HH:MM:SS): ")
try:
alarm_dt = datetime.strptime(raw, "%H:%M:%S")
break
except ValueError:
print("Bad format. Use HH:MM:SS, for example 07:30:00.")strptime parses the string into a real datetime object and raises ValueError if the format is wrong. Once you have a datetime, you can compare numerically instead of by string.
Better: Compute the Delay and Sleep Once
Section titled “Better: Compute the Delay and Sleep Once”The polling pattern is fine for short waits. For long waits, it is cleaner to compute exactly how many seconds away the alarm is and sleep that long:
from datetime import datetime, timedelta
target = datetime.strptime(input("Time HH:MM:SS: "), "%H:%M:%S").time()
now = datetime.now()
alarm_dt = now.replace(hour=target.hour, minute=target.minute,
second=target.second, microsecond=0)
if alarm_dt <= now:
alarm_dt += timedelta(days=1) # next day if the time already passed
seconds = (alarm_dt - now).total_seconds()
print(f"Sleeping for {seconds:.0f} seconds...")
time.sleep(seconds)
print("Wake Up!")This:
- Handles next-day alarms automatically (e.g., set 06:00 at midnight).
- Sleeps a single, precise interval instead of waking every second.
- Uses one clear
datetimeobject rather than two strings to compare.
Common Mistakes
Section titled “Common Mistakes”| Problem | Cause | Fix |
|---|---|---|
| Alarm never triggers | Mismatched format ("2:30:00" vs "02:30:00") | Use strptime validation; require zero-padding |
| 100 % CPU spike | Forgot time.sleep(1) | Always sleep inside polling loops |
ModuleNotFoundError: No module named 'winsound' on Mac/Linux | winsound is Windows-only | Use playsound or pygame.mixer |
| Sound plays once then silence | SND_ASYNC returns immediately — script then exits | Loop the sound or time.sleep after triggering |
| Alarm fires twice the same second | Loop did not break after match | Add break after firing |
Variations to Try
Section titled “Variations to Try”1. Snooze
Section titled “1. Snooze”After the alarm fires, ask the user:
choice = input("Snooze 5 minutes? (y/n): ")
if choice.lower() == "y":
time.sleep(5 * 60)
fire_alarm()2. Multiple alarms
Section titled “2. Multiple alarms”Keep a list of alarm times. Sort, then sleep until the soonest:
alarms = sorted({"06:30:00", "07:00:00", "07:15:00"})
for a in alarms:
wait_until(a)
fire_alarm()
print(f"Alarm at {a} fired.")3. Custom alarm message
Section titled “3. Custom alarm message”Let the user attach a label: “Take medicine — 14:30” — show it on trigger.
4. Persistent alarms
Section titled “4. Persistent alarms”Save alarms to a JSON file so they survive restarts.
import json
alarms = json.loads(Path("alarms.json").read_text())5. GUI version
Section titled “5. GUI version”Build a Tkinter window with time-entry fields, a list of pending alarms, and a snooze button. See Simple Reminder App for a similar pattern.
6. Recurring alarms
Section titled “6. Recurring alarms”Use the schedule library:
import schedule
schedule.every().day.at("07:00").do(fire_alarm)
while True:
schedule.run_pending()
time.sleep(30)7. System notification
Section titled “7. System notification”On Windows use plyer; on macOS use osascript. Combine with sound for a full desktop alert.
Real-World Applications
Section titled “Real-World Applications”- Personal wake-up alarm or pomodoro timer.
- Reminder for medication, meetings, calls.
- Trigger automation scripts at a specific time (lights, backups, downloads).
- Build the timing core of a meditation or workout app.
- Server-side cron alternative for tasks that need a specific local time.
Features Implemented
Section titled “Features Implemented”- 24-hour time format input.
- Real-time monitoring with a polling loop.
- Audio alert via
winsound. - Automatic termination once the alarm fires.
- Simple, distraction-free CLI.
Educational Value
Section titled “Educational Value”This project teaches:
- Working with time —
datetime,strftime,strptime,timedelta. - Loop control — polling with
time.sleep. - OS-specific code — recognizing when a module only works on one platform.
- Input validation — converting and validating user input early.
- Trade-offs — polling versus single-sleep, simple versus precise.
Next Steps
Section titled “Next Steps”- Replace
winsoundwith a cross-platform library so it runs on Mac/Linux. - Add a Tkinter GUI with multiple slots, on/off switches, and snooze.
- Schedule daily recurring alarms with the
schedulelibrary. - Combine with a TTS library (
pyttsx3) to have the alarm read out a message. - Persist alarms across restarts in a JSON or SQLite file.
- Wrap as a Windows Service or macOS LaunchAgent so it runs at boot.
Try it here
Section titled “Try it here”Here’s a live analog clock — the hands track the current time, the same value your code reads
from datetime.now() each tick:
Conclusion
Section titled “Conclusion”You built a working alarm clock and saw two ways to wait for a target time — polling and single-sleep — each with its own trade-offs. The same patterns (polling loop, time formatting, input validation) appear in scheduled-task tools, monitoring scripts, and game timers. Source on GitHub. Explore more beginner projects on Python Central Hub.
pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading