[Tutor] Could I have used time or datetime modules here?
Brian van den Broek
bvande at po-box.mcgill.ca
Mon Dec 6 01:53:01 CET 2004
Dick Moores said unto the world upon 2004-12-05 15:03:
> Thanks, Brian. I looked at your code a long time, and also read the
> 11/26 thread you started. I can see how I could use datetime() and your
> t2 - t1 to get the seconds for time.sleep(), but the resulting code I
> have in mind is more convoluted than the heart of my timer3.py, which I
> quote below. (I don't need the alarm time to be more than 24 hours from
> current time--therefore I want to ignore the year, month, and day.)
>
> =======================================
> import time
>
> alarm = raw_input("Enter alarm time as hhmm: ")
>
> now = time.strftime("%X") # produces current time in format hh:mm:ss
> nowSecond = int(now[6:])
> nowMinute = int(now[3:5])
> nowHour = int(now[0:2])
>
> alarmMinute = int(alarm[2:4])
> alarmHour = int(alarm[0:2])
>
> hoursDiff = alarmHour - nowHour
> minutesDiff = alarmMinute - nowMinute
>
> if hoursDiff < 0 or (hoursDiff == 0 and minutesDiff <= 0):
> hoursDiff = hoursDiff + 24 # add a day
>
> sleepSeconds = hoursDiff*3600 + minutesDiff*60 - nowSecond
>
> time.sleep(sleepSeconds)
> ====================================
> If I'm wrong, could someone please set me right?
>
> Dick
>
Hi Dick and all,
sorry I was too lazy to follow your link before, Dick. Thanks for
posting the relevant portions.
I took another run, but my code is a lot longer as I put in some error
checking on the input request -- hope you don't mind ;-) (I might have
gone overboard -- I did it to learn how as much as anything else.)
I suspect that my way is easier than yours. (I don't know about Liam's.
His came in as I was writing mine, and I've not read his closely yet.)
In mine, the key bit is that if you have two datetime objects, d1 and
d2, d1 - d2 gives a timedelta object expressing the time difference
between them in the form (days, seconds, microseconds). So, the datetime
module seems to do the work you want -- just make the current time a
datetime object, use the user input to get a datetime object in the
future and then find their timedelta and ask it for its seconds
attribute. This disregards any difference in days and gives only the
hour + minute + seconds difference expressed in seconds.
That logic is near the bottom, though, as first you've got to read
through my error checking code ;-)
I tested it pretty well, but as always, undetected errors entitle you to
a full refund of purchase price. (Minus a reasonable handling fee, of
course.)
I hope this is of some use to you.
Best to all,
Brian vdB
CODE:
import datetime
import time
def get_alarm_time():
'''Asks user for a time in the form 'hh:mm' and return tuple of ints.
Includes error checking to make sure user input really is of form
'hh:mm' where the values of 'hh' and 'mm' are appropriate.
'''
while True:
alarm_time = raw_input("Enter alarm time as hh:mm")
er_msg = '''
An alarm time must be entered in the format 'hh:mm' where 'hh'
is a number between 0 and 23 inclusive and mm is a number
between 0 and 59 inclusive.
You entered: '%s', which is not of that form.
Please try again.
''' %alarm_time
alarm_time_list = alarm_time.split(':')
# yields a list with first element the characters from before
# the ':' and second from after.
try:
alarm_hour, alarm_minute = (int(alarm_time_list[0]),
int(alarm_time_list[1]) )
except ValueError:
# raised if the user entered something like "silly:input"
print er_msg
continue
if len(str(alarm_minute)) == 1:
alarm_minute_string = '0' + str(alarm_minute)
# if the user entered, say, 12:05, str(alarm_minute) would
# give '5' rather than the needed '05'.
else:
alarm_minute_string = str(alarm_minute)
if ( (alarm_hour > 24 or alarm_hour < 0)
or (alarm_minute > 59 or alarm_minute < 0)
or str(alarm_hour) + ':' + alarm_minute_string != alarm_time):
# The first two clauses check that minutes and hours are
# within the expected ranges. The final clause checks that
# the inputs were string representations of integers.
# (Without it, the user could have entered something like
# 16.845:57.0000343.)
print er_msg
else:
return alarm_hour, alarm_minute
alarm_hour, alarm_minute = get_alarm_time()
now = datetime.datetime.now()
alarm_datetime = datetime.datetime(now.year + 4, now.month, now.day,
alarm_hour, alarm_minute)
# now.year + 4 to ensure that the alarm_datetime represents a time in
# the future. I used a multiple of 4 to avoid leap year issues. + 44
# would work equally well. (This ignores the additional correction every
# 100 or 400 years -- I forget which. But what do you want for free ;-)
alarm_in_seconds = (alarm_datetime - now).seconds
# a_datetime_object - another_datetime_object gives a_timedelta_object.
# a_timedelta_object.seconds returns only the hour and minute difference
# (discarding days) expressed in seconds. It has to be the future time
# minus the current time for the .seconds to give the wanted result.
print "I should wake up in %d seconds" %alarm_in_seconds
time.sleep(alarm_in_seconds)
print "I'm awake!"
More information about the Tutor
mailing list