[Zope3-checkins] CVS: Zope3/lib/python/datetime - __init__.py:1.2 _datetime.py:1.2 test_datetime.py:1.2
Jim Fulton
jim@zope.com
Fri, 4 Oct 2002 14:05:20 -0400
Update of /cvs-repository/Zope3/lib/python/datetime
In directory cvs.zope.org:/tmp/cvs-serv18074/datetime
Added Files:
__init__.py _datetime.py test_datetime.py
Log Message:
Added the Python implementation of what will be the standard Python
type to be added in Python 2.3. The module was converted to a package
to ease handling in CVS.
=== Zope3/lib/python/datetime/__init__.py 1.1 => 1.2 ===
--- /dev/null Fri Oct 4 14:05:19 2002
+++ Zope3/lib/python/datetime/__init__.py Fri Oct 4 14:05:19 2002
@@ -0,0 +1,8 @@
+# Python datetime `prototype
+
+# This package contains the prototype datetime module that will be included
+# in Python 2.3. We've turned it into a package to make it easier to
+# deal with in CVS for now. This __init__ file makes the package look
+# like the eventual module.
+
+from _datetime import timedelta, date, datetime, datetimetz
=== Zope3/lib/python/datetime/_datetime.py 1.1 => 1.2 === (995/1095 lines abridged)
--- /dev/null Fri Oct 4 14:05:19 2002
+++ Zope3/lib/python/datetime/_datetime.py Fri Oct 4 14:05:19 2002
@@ -0,0 +1,1092 @@
+"""Concrete date/time and related types -- prototype implemented in Python.
+
+See http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
+
+See also http://dir.yahoo.com/Reference/calendars/
+"""
+
+import time as _time
+import math as _math
+
+MINYEAR = 1 # XXX The design doc says 0
+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. Difference: Dates.py calls January 1 of year 0 day
+# number 1. The code here calls January 1 of year 1 day number 1. This is
+# to match the definition of the "proleptic Gregorian" calendar in Dershowitz
+# and Reingold's "Calendrical Calculations", where it's the base calendar
+# for all computations. See the book for algorithms for converting between
+# proleptic Gregorian ordinals and many other calendar systems.
+
+_DAYS_IN_MONTH = [None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+_DAYS_BEFORE_MONTH = [None]
+dbm = 0
+for dim in _DAYS_IN_MONTH[1:]:
+ _DAYS_BEFORE_MONTH.append(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."
+ y = year - 1
+ return y*365 + y//4 - y//100 + y//400
+
+def _days_in_month(month, year):
+ "month, year -> number of days in that month in that year."
+ assert 1 <= month <= 12, month
[-=- -=- -=- 995 lines omitted -=- -=- -=-]
+ if mytz is not None:
+ myoff = mytz.utcoffset(self)
+ if ottz is not None:
+ otoff = ottz.utcoffset(other)
+ if myoff == otoff:
+ return supercmp(other)
+ if myoff is None or otoff is None:
+ raise ValueError, "cannot mix naive and timezone-aware time"
+ # XXX What follows could be done more efficiently...
+ diff = superself.__sub__(other) + timedelta(minutes=otoff-myoff)
+ if diff.days < 0:
+ return -1
+ if diff == timedelta():
+ return 0
+ return 1
+
+ def __hash__(self):
+ tz = self.__tzinfo
+ if tz == None:
+ return super(datetimetz, self).__hash__()
+ tzoff = tz.utcoffset(self)
+ if not tzoff: # zero or None!
+ return super(datetimetz, self).__hash__()
+ t = self - timedelta(minutes=tzoff)
+ return super(datetimetz, t).__hash__()
+
+
+datetimetz.min = datetimetz(1, 1, 1)
+datetimetz.max = datetimetz(9999, 12, 31, 23, 59, 59, 999999)
+datetimetz.resolution = timedelta(microseconds=1)
+
+
+def _isoweek1monday(year):
+ # Helper to calculate the day number of the Monday starting week 1
+ # XXX This could be done more efficiently
+ THURSDAY = 3
+ firstday = _ymd2ord(year, 1, 1)
+ firstweekday = (firstday + 6) % 7 # See weekday() above
+ week1monday = firstday - firstweekday
+ if firstweekday > THURSDAY:
+ week1monday += 7
+ return week1monday
+
+
+def _test():
+ import test_datetime
+ test_datetime.test_main()
+
+if __name__ == "__main__":
+ _test()
=== Zope3/lib/python/datetime/test_datetime.py 1.1 => 1.2 === (486/586 lines abridged)
--- /dev/null Fri Oct 4 14:05:19 2002
+++ Zope3/lib/python/datetime/test_datetime.py Fri Oct 4 14:05:19 2002
@@ -0,0 +1,583 @@
+"""Test date/time type.
+
+See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases
+"""
+
+import sys
+import unittest
+
+from datetime import date, datetime, datetimetz, timedelta, MINYEAR, MAXYEAR
+
+
+class TestTimeDelta(unittest.TestCase):
+
+ def test_timedelta(self):
+ a = timedelta(7) # One week
+ b = timedelta(0, 60) # One minute
+ c = timedelta(0, 0, 1000) # One millisecond
+ self.assertEqual(a+b+c, timedelta(7, 60, 1000))
+ self.assertEqual(a-b, timedelta(6, 24*3600 - 60))
+ self.assertEqual(-a, timedelta(-7))
+ self.assertEqual(+a, timedelta(7))
+ self.assertEqual(-b, timedelta(-1, 24*3600 - 60))
+ self.assertEqual(-c, timedelta(-1, 24*3600 - 1, 999000))
+ self.assertEqual(abs(a), a)
+ self.assertEqual(abs(-a), a)
+ self.assertEqual(timedelta(6, 24*3600), a)
+ self.assertEqual(timedelta(0, 0, 60*1000000), b)
+ self.assertEqual(a*10, timedelta(70))
+ self.assertEqual(a*10, 10*a)
+ self.assertEqual(a*10L, 10*a)
+ self.assertEqual(b*10, timedelta(0, 600))
+ self.assertEqual(10*b, timedelta(0, 600))
+ self.assertEqual(b*10L, timedelta(0, 600))
+ self.assertEqual(c*10, timedelta(0, 0, 10000))
+ self.assertEqual(10*c, timedelta(0, 0, 10000))
+ self.assertEqual(c*10L, timedelta(0, 0, 10000))
+ self.assertEqual(a*-1, -a)
+ self.assertEqual(b*-2, -b-b)
+ self.assertEqual(c*-2, -c+-c)
+ self.assertEqual(b*(60*24), (b*60)*24)
+ self.assertEqual(b*(60*24), (60*b)*24)
+ self.assertEqual(c*1000, timedelta(0, 1))
+ self.assertEqual(1000*c, timedelta(0, 1))
+ self.assertEqual(a//7, timedelta(1))
+ self.assertEqual(b//10, timedelta(0, 6))
+ self.assertEqual(c//1000, timedelta(0, 0, 1))
+ self.assertEqual(a//10, timedelta(0, 7*24*360))
[-=- -=- -=- 486 lines omitted -=- -=- -=-]
+
+ theclass = datetimetz
+
+ def test_zones(self):
+ est = FixedOffset(-300, "EST")
+ utc = FixedOffset(0, "UTC")
+ met = FixedOffset(60, "MET")
+ t1 = datetimetz(2002, 3, 19, 7, 47, tzinfo=est)
+ t2 = datetimetz(2002, 3, 19, 12, 47, tzinfo=utc)
+ t3 = datetimetz(2002, 3, 19, 13, 47, tzinfo=met)
+ self.assertEqual(t1.tzinfo, est)
+ self.assertEqual(t2.tzinfo, utc)
+ self.assertEqual(t3.tzinfo, met)
+ self.assertEqual(t1.utcoffset(), -300)
+ self.assertEqual(t2.utcoffset(), 0)
+ self.assertEqual(t3.utcoffset(), 60)
+ self.assertEqual(t1.tzname(), "EST")
+ self.assertEqual(t2.tzname(), "UTC")
+ self.assertEqual(t3.tzname(), "MET")
+ self.assertEqual(hash(t1), hash(t2))
+ self.assertEqual(hash(t1), hash(t3))
+ self.assertEqual(hash(t2), hash(t3))
+ self.assertEqual(t1, t2)
+ self.assertEqual(t1, t3)
+ self.assertEqual(t2, t3)
+ self.assertEqual(str(t1), "2002-03-19 07:47:00.000000-05:00")
+ self.assertEqual(str(t2), "2002-03-19 12:47:00.000000+00:00")
+ self.assertEqual(str(t3), "2002-03-19 13:47:00.000000+01:00")
+ self.assertEqual(repr(t1),
+ "datetimetz(2002, 3, 19, 7, 47, tzinfo=est)")
+ self.assertEqual(repr(t2),
+ "datetimetz(2002, 3, 19, 12, 47, tzinfo=utc)")
+ self.assertEqual(repr(t3),
+ "datetimetz(2002, 3, 19, 13, 47, tzinfo=met)")
+
+
+def test_suite():
+ s1 = unittest.makeSuite(TestTimeDelta, 'test')
+ s2 = unittest.makeSuite(TestDate, 'test')
+ s3 = unittest.makeSuite(TestDateTime, 'test')
+ s4 = unittest.makeSuite(TestDateTimeTZ, 'test')
+ return unittest.TestSuite([s1, s2, s3, s4])
+
+def test_main():
+ r = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)
+ s = test_suite()
+ r.run(s)
+
+if __name__ == "__main__":
+ test_main()