Skip to content

Commit 5964719

Browse files
author
Richard Jones
committed
Oops, there's 24 hours in a day...
...and subtraction of intervals now works properly.
1 parent e328789 commit 5964719

File tree

2 files changed

+76
-30
lines changed

2 files changed

+76
-30
lines changed

roundup/date.py

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: date.py,v 1.19 2002-02-21 23:11:45 richard Exp $
18+
# $Id: date.py,v 1.20 2002-02-21 23:34:51 richard Exp $
1919

2020
__doc__ = """
2121
Date, time and time interval handling.
@@ -123,8 +123,8 @@ def __add__(self, other):
123123
elif second > 59: minute += 1; second -= 60
124124
if minute < 0: hour -= 1; minute += 60
125125
elif minute > 59: hour += 1; minute -= 60
126-
if hour < 0: day -= 1; hour += 60
127-
elif hour > 59: day += 1; hour -= 60
126+
if hour < 0: day -= 1; hour += 24
127+
elif hour > 59: day += 1; hour -= 24
128128

129129
# fix up the month so we're within range
130130
while month < 1 or month > 12:
@@ -157,31 +157,35 @@ def __sub__(self, other):
157157
1. an interval from this date to produce another date.
158158
2. a date from this date to produce an interval.
159159
"""
160-
if isinstance(other, Date):
161-
# TODO this code will fall over laughing if the dates cross
162-
# leap years, phases of the moon, ....
163-
a = calendar.timegm((self.year, self.month, self.day, self.hour,
164-
self.minute, self.second, 0, 0, 0))
165-
b = calendar.timegm((other.year, other.month, other.day,
166-
other.hour, other.minute, other.second, 0, 0, 0))
167-
diff = a - b
168-
if diff < 0:
169-
sign = 1
170-
diff = -diff
171-
else:
172-
sign = -1
173-
S = diff%60
174-
M = (diff/60)%60
175-
H = (diff/(60*60))%60
176-
if H>1: S = 0
177-
d = (diff/(24*60*60))%30
178-
if d>1: H = S = M = 0
179-
m = (diff/(30*24*60*60))%12
180-
if m>1: H = S = M = 0
181-
y = (diff/(365*24*60*60))
182-
if y>1: d = H = S = M = 0
183-
return Interval((y, m, d, H, M, S), sign=sign)
184-
return self.__add__(other)
160+
if isinstance(other, Interval):
161+
other = Interval(other.get_tuple(), sign=-other.sign)
162+
return self.__add__(other)
163+
164+
assert isinstance(other, Date), 'May only subtract Dates or Intervals'
165+
166+
# TODO this code will fall over laughing if the dates cross
167+
# leap years, phases of the moon, ....
168+
a = calendar.timegm((self.year, self.month, self.day, self.hour,
169+
self.minute, self.second, 0, 0, 0))
170+
b = calendar.timegm((other.year, other.month, other.day,
171+
other.hour, other.minute, other.second, 0, 0, 0))
172+
diff = a - b
173+
if diff < 0:
174+
sign = 1
175+
diff = -diff
176+
else:
177+
sign = -1
178+
S = diff%60
179+
M = (diff/60)%60
180+
H = (diff/(60*60))%60
181+
if H>1: S = 0
182+
d = (diff/(24*60*60))%30
183+
if d>1: H = S = M = 0
184+
m = (diff/(30*24*60*60))%12
185+
if m>1: H = S = M = 0
186+
y = (diff/(365*24*60*60))
187+
if y>1: d = H = S = M = 0
188+
return Interval((y, m, d, H, M, S), sign=sign)
185189

186190
def __cmp__(self, other):
187191
"""Compare this date to another date."""
@@ -433,6 +437,11 @@ def test():
433437

434438
#
435439
# $Log: not supported by cvs2svn $
440+
# Revision 1.19 2002/02/21 23:11:45 richard
441+
# . fixed some problems in date calculations (calendar.py doesn't handle over-
442+
# and under-flow). Also, hour/minute/second intervals may now be more than
443+
# 99 each.
444+
#
436445
# Revision 1.18 2002/01/23 20:00:50 jhermann
437446
# %e is a UNIXism and not documented for Python
438447
#

test/test_dates.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: test_dates.py,v 1.10 2002-02-21 23:11:45 richard Exp $
18+
# $Id: test_dates.py,v 1.11 2002-02-21 23:34:52 richard Exp $
1919

2020
import unittest, time
2121

@@ -74,14 +74,15 @@ def testOffset(self):
7474
# now check calculations
7575
date = Date('2000-01-01') + Interval('- 2y 2m')
7676
ae(str(date), '1997-11-01.00:00:00')
77-
date = Date('2000-01-01') + Interval('+ 2m')
77+
date = Date('2000-01-01') + Interval('2m')
7878
ae(str(date), '2000-03-01.00:00:00')
7979

8080
date = Date('2000-01-01') + Interval('60d')
8181
ae(str(date), '2000-03-01.00:00:00')
8282
date = Date('2001-01-01') + Interval('60d')
8383
ae(str(date), '2001-03-02.00:00:00')
8484

85+
# time additions
8586
date = Date('2000-02-28.23:59:59') + Interval('00:00:01')
8687
ae(str(date), '2000-02-29.00:00:00')
8788
date = Date('2001-02-28.23:59:59') + Interval('00:00:01')
@@ -102,6 +103,37 @@ def testOffset(self):
102103
date = Date('2001-02-28.22:58:59') + Interval('00:00:3661')
103104
ae(str(date), '2001-03-01.00:00:00')
104105

106+
# now subtractions
107+
date = Date('2000-01-01') - Interval('- 2y 2m')
108+
ae(str(date), '2002-03-01.00:00:00')
109+
date = Date('2000-01-01') - Interval('2m')
110+
ae(str(date), '1999-11-01.00:00:00')
111+
112+
date = Date('2000-03-01') - Interval('60d')
113+
ae(str(date), '2000-01-01.00:00:00')
114+
date = Date('2001-03-02') - Interval('60d')
115+
ae(str(date), '2001-01-01.00:00:00')
116+
117+
date = Date('2000-02-29.00:00:00') - Interval('00:00:01')
118+
ae(str(date), '2000-02-28.23:59:59')
119+
date = Date('2001-03-01.00:00:00') - Interval('00:00:01')
120+
ae(str(date), '2001-02-28.23:59:59')
121+
122+
date = Date('2000-02-29.00:00:00') - Interval('00:01:01')
123+
ae(str(date), '2000-02-28.23:58:59')
124+
date = Date('2001-03-01.00:00:00') - Interval('00:01:01')
125+
ae(str(date), '2001-02-28.23:58:59')
126+
127+
date = Date('2000-02-29.00:00:00') - Interval('01:01:01')
128+
ae(str(date), '2000-02-28.22:58:59')
129+
date = Date('2001-03-01.00:00:00') - Interval('01:01:01')
130+
ae(str(date), '2001-02-28.22:58:59')
131+
132+
date = Date('2000-02-29.00:00:00') - Interval('00:00:3661')
133+
ae(str(date), '2000-02-28.22:58:59')
134+
date = Date('2001-03-01.00:00:00') - Interval('00:00:3661')
135+
ae(str(date), '2001-02-28.22:58:59')
136+
105137
def testInterval(self):
106138
ae = self.assertEqual
107139
ae(str(Interval('3y')), '+ 3y')
@@ -118,6 +150,11 @@ def suite():
118150

119151
#
120152
# $Log: not supported by cvs2svn $
153+
# Revision 1.10 2002/02/21 23:11:45 richard
154+
# . fixed some problems in date calculations (calendar.py doesn't handle over-
155+
# and under-flow). Also, hour/minute/second intervals may now be more than
156+
# 99 each.
157+
#
121158
# Revision 1.9 2002/02/21 06:57:39 richard
122159
# . Added popup help for classes using the classhelp html template function.
123160
# - add <display call="classhelp('priority', 'id,name,description')">

0 commit comments

Comments
 (0)