4

I'm currently working on a calendar project using django that involves some time calculation, and I encountered a problem when I try to calculate time difference between 2 datetime objects. When I create the time, I do:

tz = timezone.get_default_timezone()
curr_day = timezone.make_aware(datetime.datetime(curr_day.year,
                                                 curr_day.month,
                                                 curr_day.day,
                                                 0, 0, 0), tz)

When I create it, only the date matters, but since the object should be using datetime for historical reason, I added three 0's for hour, minute, second.

My program tries to compare if 2 datetime has difference of 1 in days, so I do

if (event1 - event2).days == 1:
    # do something

The problem comes up when I try to compare 03/12/2017 and 03/13/2017(03/12/2017 is the DST).

event1
datetime.datetime(2017, 3, 13, 4, 0, tzinfo=<UTC>)

event2
datetime.datetime(2017, 3, 12, 5, 0, tzinfo=<UTC>)

(event1-event2).days
0

I know that it's because the Daylight Saving Time that makes the difference less than one day, but I don't know the solution for this, because in theory the result should be 1 as well. How can I fix my code to detect this? Thanks!

karthikr
  • 97,368
  • 26
  • 197
  • 188
Shang Wang
  • 24,909
  • 20
  • 73
  • 94
  • What is "a day"? Is it 24 hours exactly? Related: [How can I subtract a day from a python date?](http://stackoverflow.com/a/25427822/4279) – jfs Aug 25 '14 at 14:21
  • @J.F.Sebastian: a day might not be necessarily be 24 hrs, in my program it means 2 datetime objects identical in hour, minute, second, and the date is different by 1. – Shang Wang Aug 25 '14 at 14:32
  • 1
    If you need identical hour, minute, second but the difference may be less/more than 24 hours then you could use the algorithm that computes `yesterday` in [my answer](http://stackoverflow.com/a/25427822/4279) – jfs Aug 25 '14 at 14:40
  • unrelated: you should probably use `delta // timedelta(days=1)` (or its analog on older Python versions) instead of `delta.days` if the difference may be negative. – jfs Aug 25 '14 at 14:51
  • @J.F.Sebastian: What is the advantage of using `delta // timedelta(days=1)`? – unutbu Aug 25 '14 at 17:43
  • @unutbu: [the difference is visible if true division is used: `delta / timedelta(days=1)`](http://stackoverflow.com/questions/508727/python-time-to-age/508742#comment39666382_508742) – jfs Aug 25 '14 at 18:03

1 Answers1

4

You could set the hours, minutes, days back to 0 before taking the difference:

In [79]: import datetime as DT
In [80]: (DT.datetime.combine(event1, DT.time(0)) - DT.datetime.combine(event2, DT.time(0))).days
Out[80]: 1

Note that according to this definition of "days", two timezone-aware datetimes may have a difference of 1 with respect to one timezone, and yet have difference of 0 with respect to another timezone.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • I tried and it works! But I wonder what does your way to "set to 0" different from my initial object creation of "set to 0"? – Shang Wang Aug 25 '14 at 14:37
  • note: `event1` and `event2` must be in the same timezone for the result to make sense. – jfs Aug 25 '14 at 14:42
  • I'm guessing that `event1` and `event2` have been converted to some other timezone and this is the reason why the hours is no longer zero. If that is the case, then in your code the hours was set to zero before the conversion, while in the code I posted, the hours was reset to zero after the conversion. – unutbu Aug 25 '14 at 14:49
  • 1
    @da_zhuang: `event1` and `event2` from you question have different hours (`4` and `5`). The reason might be that (necessary) `tz.normalize()` is called after you "set to 0", see the discussion in [python - datetime with timezone to epoch](http://stackoverflow.com/a/12166400/4279). – jfs Aug 25 '14 at 15:04