2008-02-17 Douglas S. Blank <dblank@cs.brynmawr.edu>

* src/gen/lib/date.py (Date.__sub__): fixed some date math (#1649)
	* src/gen/lib/test/date_test.py: added some unit tests for date math



svn: r10043
This commit is contained in:
Doug Blank 2008-02-17 17:53:43 +00:00
parent 3cb7f74e1c
commit 6ad3a48d64
3 changed files with 108 additions and 10 deletions

View File

@ -1,3 +1,7 @@
2008-02-17 Douglas S. Blank <dblank@cs.brynmawr.edu>
* src/gen/lib/date.py (Date.__sub__): fixed some date math (#1649)
* src/gen/lib/test/date_test.py: added some unit tests for date math
2008-02-15 Gary Burton <gary.burton@zen.co.uk>
* src/DataViews/RelationView.py:
* src/Editors/_EditFamily.py: prevent right mouse button causing crash.

View File

@ -246,13 +246,20 @@ class Date:
"""
Date artithmetic: Date() - years, Date - (y,m,d), or Date() - Date()
"""
if type(other) == int:
if type(other) == int: # Date - value -> Date
return self.copy_offset_ymd(-other)
elif type(other) == type(self): # date
elif type(other) in [tuple, list]: # Date - (y, m, d) -> Date
return self.copy_offset_ymd(*map(lambda x: -x, other))
elif type(other) == type(self): # Date1 - Date2 -> tuple
# We should make sure that Date2 + tuple -> Date1 and
# Date1 - tuple -> Date2
d1 = map(lambda i: i or 1, self.get_ymd())
d2 = map(lambda i: i or 1, other.get_ymd())
date1 = self
date2 = other
if d1 < d2:
d1, d2 = d2, d1
date1, date2 = date2, date1
# d1 - d2 (1998, 12, 32) - (1982, 12, 15) =
# days:
if d2[2] > d1[2]:
@ -269,18 +276,39 @@ class Date:
days = d1[2] - d2[2]
months = d1[1] - d2[1]
years = d1[0] - d2[0]
if days > 31:
if days > 31:
months += days / 31
days = days % 31
if months > 12:
years += months / 12
months = months % 12
return (years, months, days)
elif type(other) in [tuple, list]:
return self.copy_offset_ymd(*map(lambda x: -x, other))
# estimate: (years, months, days)
# Check transitivity:
eDate = date1 - (years, months, days)
if eDate < date2: # too small
diff = 0
while eDate < date2 and diff < 60:
diff += 1
eDate = eDate + (0, 0, diff)
if diff == 60:
return (0, 0, 0)
return (years, months, days - diff)
elif eDate > date2:
diff = 0
while eDate > date2 and diff > -60:
diff -= 1
eDate = eDate - (0, 0, abs(diff))
if diff == -60:
return (0, 0, 0)
return (years, months, days + diff)
else:
return (years, months, days)
else:
raise AttributeError, "unknown date sub type: %s " % type(other)
def __eq__(self, other):
return self.sortval == other.sortval
def __lt__(self, other):
return self.sortval < other.sortval
@ -629,12 +657,18 @@ class Date:
if dv[Date._POS_MON]:
dv[Date._POS_MON] += month
elif month:
dv[Date._POS_MON] = month
if month < 0:
dv[Date._POS_MON] = 1 + month
else:
dv[Date._POS_MON] = month
# Fix if month out of bounds:
if month != 0: # only check if changed
if dv[Date._POS_MON] <= 0: # subtraction
dv[Date._POS_YR] -= int(-dv[Date._POS_MON] / 12)
dv[Date._POS_MON] = 13 - dv[Date._POS_MON] % 12
if dv[Date._POS_MON] == 0: # subtraction
dv[Date._POS_MON] = 12
dv[Date._POS_YR] -= 1
elif dv[Date._POS_MON] < 0: # subtraction
dv[Date._POS_YR] -= int((-dv[Date._POS_MON]) / 12) + 1
dv[Date._POS_MON] = (dv[Date._POS_MON] % 12)
elif dv[Date._POS_MON] > 12 or dv[Date._POS_MON] < 1:
dv[Date._POS_YR] += int(dv[Date._POS_MON] / 12)
dv[Date._POS_MON] = dv[Date._POS_MON] % 12

View File

@ -135,5 +135,65 @@ def suite():
count += 1
return suite
def assert_func(exp1, exp2):
Date = date.Date
e1 = eval(exp1)
e2 = eval(exp2)
assert e1 == e2, "%s should be %s but was %s" % (exp1, e2, e1)
class Assert(unittest.TestCase):
def __init__(self, method_name, part, exp1, exp2):
self.__dict__[method_name + ("-%d" % part)] = \
lambda: assert_func(exp1, exp2)
unittest.TestCase.__init__(self, method_name + ("-%d" % part))
def suite2():
""" interface to automated test runner test/regrtest.py """
Config.set(Config.DATE_BEFORE_RANGE, 9999)
Config.set(Config.DATE_AFTER_RANGE, 9999)
Config.set(Config.DATE_ABOUT_RANGE, 10)
tests = [
# Date +/- int/tuple -> Date
("Date(2008, 1, 1) - 1", "Date(2007, 1, 1)"),
("Date(2008, 1, 1) + 1", "Date(2009, 1, 1)"),
("Date(2008, 1, 1) - (0,0,1)", "Date(2007, 12, 31)"),
("Date(2008, 1, 1) - (0,0,2)", "Date(2007, 12, 30)"),
("Date(2008) - (0,0,1)", "Date(2007, 12, 31)"),
("Date(2008) - 1", "Date(2007, 1, 1)"),
("Date(2008, 12, 31) + (0, 0, 1)", "Date(2009, 1, 1)"),
("Date(2000,1,1) - (0,11,0)", "Date(1999,02,01)"),
("Date(2000,1,1) - (0,1,0)", "Date(1999, 12, 1)"),
("Date(2008, 1, 1) + (0, 0, 32)", "Date(2008, 02, 02)"),
("Date(2008, 2, 1) + (0, 0, 32)", "Date(2008, 03, 04)"),
("Date(2000) - (0, 1, 0)", "Date(1999, 12, 1)"),
("Date(2000) + (0, 1, 0)", "Date(2000, 1, 0)"), # Ok?
("Date(2000, 1, 1) - (0, 1, 0)", "Date(1999, 12, 1)"),
("Date(2000, 1, 1) - 1", "Date(1999, 1, 1)"),
("Date(2000) - 1", "Date(1999)"),
("Date(2000) + 1", "Date(2001)"),
#My great great grandfather died on 1876-05-07.
#He died at an age of 65 years, 5 month 17 days according to the books:
#> Date(1876,5,7)-(65,5,17)
#1811-12-21
#> Date(1876,5,7)-Date(1811,12,21)
#(64, 4, 17)
#But his correct birth date is 1810-11-20:
#("Date(1876,5,7)-Date(1810,11,20)", "(65, 5, 18)")
("Date(1876,5,7) - Date(1876,5,1)", "(0, 0, 6)"),
("Date(1876,5,7) - Date(1876,4,30)", "(0, 0, 7)"),
("Date(2000,1,1) - Date(1999,2,1)", "(0, 11, 0)"),
("Date(2000,1,1) - Date(1999,12,1)", "(0, 1, 0)"),
# Date +/- Date -> tuple
("Date(2007, 12, 23) - Date(1963, 12, 4)", "(44, 0, 19)"),
]
suite = unittest.TestSuite()
count = 1
for (exp1, exp2) in tests:
suite.addTest(Assert('test_assert%04d' % count, 1, exp1, exp2))
count += 1
return suite
if __name__ == "__main__":
unittest.TextTestRunner().run(suite())
unittest.TextTestRunner().run(suite2())