[Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.3,1.4 test_datetime.py,1.1,1.2
Tim Peters
tim_one@users.sourceforge.net
Fri, 01 Mar 2002 14:42:30 -0800
Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory usw-pr-cvs1:/tmp/cvs-serv1524
Modified Files:
datetime.py test_datetime.py
Log Message:
Incorporate a pile of utility functions from Demo/classes/Dates.py, which
also assumes the Gregorian calender indefinitely extended. In particular,
this gives us _date2num() and _num2date() utilities that establish a
bijection between datetime objects and a contiguous range of integers,
such that consecutive days are associated with consecutive integers.
Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** datetime.py 1 Mar 2002 22:19:41 -0000 1.3
--- datetime.py 1 Mar 2002 22:42:28 -0000 1.4
***************
*** 4,7 ****
--- 4,75 ----
MAXYEAR = 9999 # XXX The design doc says 65535
+ # Utility functions, adapted from Python's Demo/classes/Dates.py, which
+ # also assumes the current Gregorian calendar indefinitely extended in
+ # both directions.
+
+ _DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+ _DAYS_BEFORE_MONTH = []
+ dbm = 0
+ for dim in _DAYS_IN_MONTH:
+ _DAYS_BEFORE_MONTH.append(dbm)
+ dbm = dbm + dim
+ del dbm, dim
+
+ def _is_leap(year):
+ "year -> 1 if leap year, else 0."
+ return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
+
+ def _days_in_year(year):
+ "year -> number of days in year (366 if a leap year, else 365)."
+ return 365 + _is_leap(year)
+
+ def _days_before_year(year):
+ "year -> number of days before January 1st of year."
+ return year*365 + (year+3)//4 - (year+99)//100 + (year+399)//400
+
+ def _days_in_month(month, year):
+ "month, year -> number of days in that month in that year."
+ assert 1 <= month <= 12, month
+ if month == 2 and _is_leap(year):
+ return 29
+ return _DAYS_IN_MONTH[month-1]
+
+ def _days_before_month(month, year):
+ "month, year -> number of days in year preceeding first day of month."
+ return _DAYS_BEFORE_MONTH[month-1] + (month > 2 and _is_leap(year))
+
+ def _date2num(date):
+ "datetime object -> day ordinal, considering 01-Jan-0000 as day 1."
+ assert isinstance(date, datetime)
+ return (_days_before_year(date.year) +
+ _days_before_month(date.month, date.year) +
+ date.day)
+
+ _DI400Y = _days_before_year(400) # number of days in 400 years
+
+ def _num2date(n):
+ "day ordinal -> datetime object."
+
+ n400 = (n-1) // _DI400Y # number of 400-year blocks preceding
+ year = n400 * 400
+ n -= n400 * _DI400Y
+
+ more = n // 365
+ dby = _days_before_year(more)
+ if dby >= n:
+ more -= 1
+ dby -= _days_in_year(more)
+ year += more
+ n -= dby
+
+ month = min(n//29 + 1, 12)
+ dbm = _days_before_month(month, year)
+ if dbm >= n:
+ month -= 1
+ dbm -= _days_in_month(month, year)
+
+ return datetime(year, month, n-dbm)
+
class basetime(object):
"""Abstract date/time type.
Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** test_datetime.py 1 Mar 2002 21:00:49 -0000 1.1
--- test_datetime.py 1 Mar 2002 22:42:28 -0000 1.2
***************
*** 27,30 ****
--- 27,39 ----
self.assert_(dt2 > dt3)
+ def test_ordinal_conversions(self):
+ import datetime as _datetime
+ for year in range(_datetime.MINYEAR, _datetime.MAXYEAR + 1):
+ for month, day in (1, 1), (12, 31), (6, 17):
+ base = datetime(year, month, day)
+ ordinal = _datetime._date2num(base)
+ derived = _datetime._num2date(ordinal)
+ self.assertEqual(base, derived)
+
def test_suite():
s1 = unittest.makeSuite(TestDateTime, 'test')