[Tutor] Re: Could I have used time or datetime modules here?

Liam Clarke cyresse at gmail.com
Wed Dec 8 07:12:31 CET 2004


 >alarm_datetime = datetime.datetime(now.year, now.month, now.day,
                                   alarm_hour, alarm_minute)

Now that's clever.

I too, have learnt a large amount from this thread.


On Tue, 07 Dec 2004 23:57:59 -0500, Brian van den Broek
<bvande at po-box.mcgill.ca> wrote:
> Dick Moores said unto the world upon 2004-12-07 12:04:
> 
> 
> > Brian van den Broek wrote at 07:50 12/7/2004:
> >
> >>> It seems I've missed out on something important
> >>> BTW I'm not sure you need the +4 of "now.year + 4". I've run this
> >>> without the +4 and it doesn't seem to be needed. And notes (1) and
> >>> (4) on that page seem to say this, as far as I understand them.
> >>
> >>
> >> I'm not sure I do either :-)
> >>
> >> Here's why I did it:
> >>
> >> I discovered that in order to get the right "seconds until alarm"
> >> value from the datetime for now and the alarm datetime by subtracting
> >> one datetime object from another, I needed the alarm datetime to be in
> >> the future. But, since you can set an alarm for 09:00 tomorrow at
> >> 22:00 today, I needed the alarm datetime to not use today's date. (If
> >> you use today's, you end up with seconds *since* 09:00 this morning,
> >> not the desired seconds *until* 09:00 tomorrow morning.) Since
> >> timedelta_object.seconds discards all difference save the seconds save
> >> those from the hours, minutes, and seconds difference in the two
> >> datetime objects, it doesn't matter what date the alarm datetime is
> >> set to. (The day information is in timedelta_object.days.)
> >>
> >> Or, so I thought. I'd first tried getting the alarm datetime by simply
> >> taking the date component of datetime.datetime.now() and adding to the
> >> day value. That works fine, provided you are not on the last day of
> >> the month. But, when checking boundary cases before posting the code I
> >> sent, I discovered this sort of thing:
> >>
> >> >>> last_day_of_june = datetime.datetime(2004, 6, 30) # long for clarity
> >> >>> ldj = last_day_of_june                            # short for typing
> >> >>> new_day = datetime.datetime(ldj.year, ldj.month, ldj.day + 1)
> >>
> >> Traceback (most recent call last):
> >>   File "<pyshell#8>", line 1, in -toplevel-
> >>     new_day = datetime.datetime(ldj.year, ldj.month, ldj.day + 1)
> >> ValueError: day is out of range for month
> >> >>>
> >>
> >> So, adding to the day or the month was out, unless I wanted elaborate
> >> code to determine which to add to under what circumstances. So then I
> >> thought, "Well, just change from now.day + 1 to now.year + 1, and all
> >> problems go away". And then I thought "Ah, but what if I try to run
> >> the script on Feb. 29?
> >>
> >> So, that's why I used now.year + 4. It still leaves open the
> >> possibility of getting bit by the every so often further correction to
> >> the calender, but, I *believe* the next one is due in 2100, so I think
> >> I can live with it. ;-)
> >>
> >> I'm not saying it isn't hackish, though. Better ways surely exist.
> >
> >
> > Brian,
> >
> > I just can't succeed in reproducing the problems with the boundary
> > cases  with the +4 removed. I've tried setting my computer's clock to
> > Nov 30, Feb 29, 2004, and Dec 31, 2004 (without changing the time). It's
> > now about 9 am where I am, and setting the alarm time to 0700 (i.e., on
> > the next day) works fine in all 3 cases. And of course no problem at
> > today's date with setting the alarm time to 07:00.
> >
> > Isn't that what that note (1) on
> > <http://docs.python.org/lib/datetime-date.html> implies?
> >
> > I did the testing with <http://www.rcblue.com/Python/timer4-ForWeb.py>,
> > by remarking out the time.sleep() line and noting what the
> > print_hms(sleepSeconds) function prints.
> >
> > Dick
> 
> Hi Dick and all,
> 
> I haven't checked your link yet, but thanks for it. (It's in the 'follow
> when I've time' file.)
> 
> I think this is all moot in light of Tim's post explaining:
> 
> >
> > Actually, you needed simpler code <wink>:
> >
> >
> >>>>>>> import datetime
> >>>>>>> ldj = datetime.datetime(2004, 6, 30)
> >>>>>>> new_day = ldj + datetime.timedelta(days=1)
> >>>>>>> print new_day
> >
> > 2004-07-01 00:00:00
> 
> Why I thought I needed it was that I was trying to do datetime's work
> for it :-)
> 
> I'd done:
> alarm_datetime = datetime.datetime(now.year+4, now.month, now.day,
>                                     alarm_hour, alarm_minute)
> 
> after trying:
> alarm_datetime = datetime.datetime(now.year, now.month, now.day+1,
>                                     alarm_hour, alarm_minute)
> 
> That did cause problems if the now datetime was the last day of a month
> (see last_day_of_june example for proof). (If you aren't getting the
> same problem is similar circumstances, well, I'm out of ideas on that one.)
> 
> This was all to the end of constructing an alarm_datetime guaranteed to
> be in the future from the user supplied alarm_hour, alarm_minute.
> 
> On the bus today (great place for ideas, the bus ;-), I figured out I
> could avoid the whole +4 because of leap years by doing something like
> 
> alarm_datetime = datetime.datetime(now.year+1, 1, 1,
>                                     alarm_hour, alarm_minute)
> 
> thus making the new datetime on Jan. 1 and skirting all month-end and
> leap year issues. But, that is still a kludge, compared to Tim's way.
> 
> In light of Tim's post (and without having thought about possible
> further improvements to my approach given this new knowledge) I'd now do:
> 
> >>> import datetime
> >>> alarm_hour = 13               # skipping actual user
> >>> alarm_minute = 25             # input part for ease
> >>> now = datetime.datetime.now()
> >>> alarm_datetime = datetime.datetime(now.year, now.month, now.day,
>                                     alarm_hour, alarm_minute)
> >>> # I wouldn't be surprised if this can be done more smoothly.
> >>> # It is likely residue of my original and wrong approach.
> >>> # I will check and post back if I see the suspicion is right.
> >>> # But, not before the weekend, I don't think.
> >>> alarm_datetime = alarm_datetime + datetime.timedelta(days=1)
> >>> print now
> 2004-12-07 23:24:58.050000
> >>> print alarm_datetime
> 2004-12-08 13:25:00
> >>>
> 
> And, all is in order :-)
> 
> (The worry that goes "But wait, what if I want my alarm later today, and
> not tomorrow?" is what using .seconds is for:
> 
> >>> alarm_in_seconds = (alarm_datetime - now).seconds
> >>> alarm_in_seconds
> 50401
> >>> _ / ( 60 * 60.0)
> 14.000277777777777
> 
> Which is what's wanted, as the alarm_datetime is just a midge over 14
> hours ahead of the now datetime. The .seconds discards the difference in
> days, and handles only the difference in seconds.)
> 
> The note you reference:
> 
> date2 is moved forward in time if timedelta.days > 0, or backward if
> timedelta.days < 0. Afterward date2 - date1 == timedelta.days.
> timedelta.seconds and timedelta.microseconds are ignored. OverflowError
> is raised if date2.year would be smaller than MINYEAR or larger than
> MAXYEAR.
> 
> presupposes you are adding a timedelta to a datetime as in Tim's
> suggestion. It makes no promises if you were doing something goofy like
> I was. (If that is what you were trying to get me to see, sorry, but I
> missed it.)
> 
> I hope this clarifies things some :-)
> 
> Thanks, Dick, Liam, and Tim. I've learned a good deal off this thread.
> 
> 
> 
> Best to all,
> 
> Brian vdB
> 
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
> 


-- 
'There is only one basic human right, and that is to do as you damn well please.
And with it comes the only basic human duty, to take the consequences.


More information about the Tutor mailing list