Problem with dates and daylight savings...

J

John Taylor

I was wondering if some one could explain this anomaly. I wrote a program to add/subtract
dates. For example,

../ComputeDay.py 2004/04/12 -7 %Y/%m/%d
2004/04/05

Here is the anomaly....
../ComputeDay.py 2004/04/12 -8 %Y/%m/%d
2004/04/03

I would have thought this would have returned the 4th. I have a feeling that daylight savings
has something to do with this, as the time changed on the 3rd.
Can someone explain this? How can I correct this problem?

../ComputeDay.py 2004/04/12 -9 %Y/%m/%d
2004/04/02



Thanks,
-John


Here is the code:

#!/usr/bin/env python2

##
## ComputeDay.py
## John Taylor, Apr 12, 2004
##

import time
import sys

############################################################################

def Usage():
print
print "Usage: %s [ t1 ] [ n ] [ format string ]" % sys.argv[0]
print "Given arguments t1 and n, where n is a positvie or negative number,"
print "return the date +/- t1"
print """format should be a date format string, such as: %Y/%m/%d"""
print "See the man page for strptime for formatting options"
print
print "Example:", sys.argv[0], "2004/03/01 -1 %Y/%m/%d"
print
sys.exit()


############################################################################

def main():
if len(sys.argv) != 4:
Usage()

fmt = sys.argv[3]

try:
t1 = time.strptime(sys.argv[1], fmt)
except ValueError, e:
print "Error for t1: ", e
return

try:
n = int(sys.argv[2])
except ValueError, e:
print "Error for n: ", e
return

oneday = 60 * 60 * 24 * 1.0
diff = time.mktime(t1) + (n * oneday)
diff = time.localtime(diff)

try:
result = time.strftime(fmt, diff)
except ValueError, e:
print "Error for result: ", e
return

print "%s" % ( result )

############################################################################

main()


-- end of code
 
P

Peter Hansen

John said:
I was wondering if some one could explain this anomaly. I wrote a program to add/subtract
dates. For example,

./ComputeDay.py 2004/04/12 -7 %Y/%m/%d
2004/04/05

Here is the anomaly....
./ComputeDay.py 2004/04/12 -8 %Y/%m/%d
2004/04/03

I would have thought this would have returned the 4th. I have a feeling that daylight savings
has something to do with this, as the time changed on the 3rd.
Can someone explain this? How can I correct this problem?

Doing date math using seconds is highly error-prone and frustrating.

The way to correct this is to use the datetime module:

c:\>python
Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)] on
win32datetime.datetime(2004, 4, 4, 0, 0)

You might be right about the daylight savings time thing, but who
cares? ;-) The datetime module is the right tool for the job here
and it gets the correct result.

-Peter
 
M

Mark Tolonen

John Taylor said:
I was wondering if some one could explain this anomaly. I wrote a program to add/subtract
dates. For example,

./ComputeDay.py 2004/04/12 -7 %Y/%m/%d
2004/04/05

Here is the anomaly....
./ComputeDay.py 2004/04/12 -8 %Y/%m/%d
2004/04/03

I would have thought this would have returned the 4th. I have a feeling that daylight savings
has something to do with this, as the time changed on the 3rd.
Can someone explain this? How can I correct this problem?

./ComputeDay.py 2004/04/12 -9 %Y/%m/%d
2004/04/02



Thanks,
-John


Here is the code:

#!/usr/bin/env python2

##
## ComputeDay.py
## John Taylor, Apr 12, 2004
##

import time
import sys

############################################################################

def Usage():
print
print "Usage: %s [ t1 ] [ n ] [ format string ]" % sys.argv[0]
print "Given arguments t1 and n, where n is a positvie or negative number,"
print "return the date +/- t1"
print """format should be a date format string, such as: %Y/%m/%d"""
print "See the man page for strptime for formatting options"
print
print "Example:", sys.argv[0], "2004/03/01 -1 %Y/%m/%d"
print
sys.exit()


############################################################################

def main():
if len(sys.argv) != 4:
Usage()

fmt = sys.argv[3]

try:
t1 = time.strptime(sys.argv[1], fmt)
except ValueError, e:
print "Error for t1: ", e
return

try:
n = int(sys.argv[2])
except ValueError, e:
print "Error for n: ", e
return

oneday = 60 * 60 * 24 * 1.0
diff = time.mktime(t1) + (n * oneday)
diff = time.localtime(diff)

When crossing a daylight savings boundary an hour is added or subtracted.
If you display diff at this point, you can see the error:
(2004, 4, 3, 23, 0, 0, 5, 94, 0)

It is 2004/4/3 11:00pm instead of 2004/4/4 12:00am.

One thing the time.mktime() will do is normalize an invalid date/time
specification. In C it will correct the structure passed to it, but in
Python you have to call time.localtime() to see the correction. If you
subtract the number of days directly from the date field the time will be
corrected for you. Example:
[2004, 4, 12, 0, 0, 0, 0, 103, -1] # 2004/4/12, 103rd day of year,
DST unknown
[2004, 4, 4, 0, 0, 0, 0, 103, -1] # 2004/4/4, invalid weekday and
yearday, DST unknown(2004, 4, 4, 0, 0, 0, 6, 95, 0) # 95th day of year, standard time
t1[2] -= 8 # another 8 days earlier
t1
[2004, 4, -4, 0, 0, 0, 0, 103, -1] # date, weekday, yearday invalid.
DST unknown(2004, 3, 27, 0, 0, 0, 5, 87, 0) # 2004/3/27, 87th day of year,
standard time.

Mark
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top