[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()