ECX 30 Days of Code and Design
Day 20
Task
Write a program that:
- Asks the user to enter a time duration in the form of a number with a unit of either seconds, minutes, or hours. (E.g., "44s", "32m", "10h")
- The last character of the string entered would be used to determine its unit
- Counts down from the input value, and prints out the time left on the clock every second
- When the time is exhausted, makes a beeping sound non-stop until the user exits the app
For example:
Hint: A "beeping sound" can be achieved using the "bell character", or any library of your choice.T > Enter a time User > 5s T > 5 seconds left > 4 seconds left > 3 seconds left > 2 seconds left > 1 second left Continuous indefinite beeping
My Approach
This is the full code. It would be explained in bits throughout this article.
import time # For sleep
import datetime # For timedelta
# import winsound # For Beep on Windows OS
# Countdown timer function
def countdown(hrs, mins, sec):
"""Counts down time and gives off beeps when the time inputted elapse"""
# Calculate the total number of seconds
total_seconds = hrs * 3600 + mins * 60 + sec
# While loop that checks if total_seconds reaches zero
# If not zero, decrement total time by one second
while total_seconds >= 0:
# Timer represents time left on countdown
timer = datetime.timedelta(seconds=total_seconds)
print(timer, end='\r')
# Delays the program one second
time.sleep(1)
# Reduces total time by one second
total_seconds = total_seconds - 1
# The timer continually beeps for the next 45 seconds
alarm_sec = 45
while alarm_sec > 0:
# winsound.Beep(440, 500)
print('\a', end='\r')
time.sleep(1)
alarm_sec -= 1
# User Input
try:
hours = input("Enter the time in hours: ")
minutes = input("Enter the time in minutes: ")
secs = input("Enter the time in seconds: ")
countdown(int(hours), int(minutes), int(secs))
except ValueError:
print('Invalid input! Only integers are allowed.')
First, we import the time, datetime, and winsound modules. You would notice the winsound module is commented; that is because the bell character (‘\a’) did not work on my Windows PC, so I had to use the winsound module, but the bell character worked on Replit, but not the winsound module; so, I have left it there should incase the bell characters fails to work, the winsound can be used.
import time # For sleep
import datetime # For timedelta
# import winsound # For Beep
Next, we define the function, countdown(), which takes three parameters (hours, minutes, and seconds). We then create a variable, total_seconds, which calculates the number of seconds based on the input of the user. 1 hour has 3600 seconds (60 * 60) and 1 minute has 60 seconds.
def countdown(hrs, min, sec):
total_seconds = hrs * 3600 + min * 60 + sec
Using while loop, we count down the number of seconds. We pass the number of seconds into the timedelta() function which gives X days, hh:mm:ss format if we exceed 86400 seconds (1 day), but if the seconds is less than 86400, we have it formatted to hh:mm:ss. We print out the current time remaining; then use the sleep() function from the time module to sleep the program for a second and deduct the time. We continue this until we get to zero seconds. Carriage return '\r'
is used here to ensure that our timer is displayed on a single line; that is, as we display the number of seconds left, the previous output is overwritten, and the new output takes that space of the previous output.
while total_seconds > 0:
# Timer represents time left on countdown
timer = datetime.timedelta(seconds=total_seconds)
print(timer, end='\r')
# Delays the program one second
time.sleep(1)
# Reduces total time by one second
total_seconds = total_seconds - 1
When the timer is up, we would have a continuous beeping from the bell character for 45 seconds (the task was that the bell should go until the program is interrupted, but I was advised that it could have an adverse effect on the PC. To make it continuous use while True:. If the bell character fails to produce a sound and you are on Windows OS, you can uncomment the
winsound.Beep(440, 500)`. The first argument (440) indicates the frequency of the beep in hertz, while the second argument (500) implies the duration of the beep in milliseconds.
alarm_sec = 45
while alarm_sec > 0:
# winsound.Beep(440, 500)
print('\a', end='\r')
time.sleep(1)
alarm_sec -= 1
Finally, we ask for the user input, and pass them as arguments into the function. We make use of try except block to handle ValueError try: hours = input("Enter the time in hours: ") minutes = input("Enter the time in minutes: ") secs = input("Enter the time in seconds: ")
countdown(int(hours), int(minutes), int(secs))
except ValueError: print('Invalid input! Only integers are allowed.')
Output
Run the code on my Replit.