[Python-checkins] r82065 - sandbox/branches/py3k-datetime/datetime.py

alexander.belopolsky python-checkins at python.org
Fri Jun 18 03:18:47 CEST 2010


Author: alexander.belopolsky
Date: Fri Jun 18 03:18:47 2010
New Revision: 82065

Log:
Applied changes from PyPy. The result passes original tests.
See http://codespeak.net/pypy/dist/pypy/lib/datetime.py


Modified:
   sandbox/branches/py3k-datetime/datetime.py

Modified: sandbox/branches/py3k-datetime/datetime.py
==============================================================================
--- sandbox/branches/py3k-datetime/datetime.py	(original)
+++ sandbox/branches/py3k-datetime/datetime.py	Fri Jun 18 03:18:47 2010
@@ -12,6 +12,8 @@
 
 Sources for time zone and DST data: http://www.twinsun.com/tz/tz-link.htm
 
+This was originally copied from the sandbox of the CPython CVS repository.
+Thanks to Tim Peters for suggesting using it. 
 """
 
 import time as _time
@@ -575,9 +577,11 @@
 
     def __add__(self, other):
         if isinstance(other, timedelta):
-            return self.__class__(self.__days + other.__days,
-                                  self.__seconds + other.__seconds,
-                                  self.__microseconds + other.__microseconds)
+            # for CPython compatibility, we cannot use
+            # our __class__ here, but need a real timedelta
+            return timedelta(self.__days + other.__days,
+                             self.__seconds + other.__seconds,
+                             self.__microseconds + other.__microseconds)
         return NotImplemented
 
     __radd__ = __add__
@@ -593,9 +597,11 @@
         return NotImplemented
 
     def __neg__(self):
-        return self.__class__(-self.__days,
-                              -self.__seconds,
-                              -self.__microseconds)
+            # for CPython compatibility, we cannot use
+            # our __class__ here, but need a real timedelta
+            return timedelta(-self.__days,
+                             -self.__seconds,
+                             -self.__microseconds)
 
     def __pos__(self):
         return self
@@ -608,9 +614,11 @@
 
     def __mul__(self, other):
         if isinstance(other, (int, long)):
-            return self.__class__(self.__days * other,
-                                  self.__seconds * other,
-                                  self.__microseconds * other)
+            # for CPython compatibility, we cannot use
+            # our __class__ here, but need a real timedelta
+            return timedelta(self.__days * other,
+                             self.__seconds * other,
+                             self.__microseconds * other)
         return NotImplemented
 
     __rmul__ = __mul__
@@ -619,7 +627,7 @@
         if isinstance(other, (int, long)):
             usec = ((self.__days * (24*3600L) + self.__seconds) * 1000000 +
                     self.__microseconds)
-            return self.__class__(0, 0, usec // other)
+            return timedelta(0, 0, usec // other)
         return NotImplemented
 
     __floordiv__ = __div__
@@ -728,7 +736,7 @@
         if isinstance(year, str):
             # Pickle support
             self = object.__new__(cls)
-            self.__setstate((year,))
+            self.__setstate(year)
             return self
         _check_date_fields(year, month, day)
         self = object.__new__(cls)
@@ -901,7 +909,7 @@
                       self.__month,
                       self.__day + other.days)
             self._checkOverflow(t.year)
-            result = self.__class__(t.year, t.month, t.day)
+            result = date(t.year, t.month, t.day)
             return result
         raise TypeError
         # XXX Should be 'return NotImplemented', but there's a bug in 2.2...
@@ -964,10 +972,9 @@
         yhi, ylo = divmod(self.__year, 256)
         return ("%c%c%c%c" % (yhi, ylo, self.__month, self.__day), )
 
-    def __setstate(self, t):
-        assert isinstance(t, tuple) and len(t) == 1, `t`
-        string = t[0]
-        assert len(string) == 4
+    def __setstate(self, string):
+        if len(string) != 4 or not (1 <= ord(string[2]) <= 12):
+            raise TypeError("not enough arguments")
         yhi, ylo, self.__month, self.__day = map(ord, string)
         self.__year = yhi * 256 + ylo
 
@@ -1090,7 +1097,7 @@
         self = object.__new__(cls)
         if isinstance(hour, str):
             # Pickle support
-            self.__setstate((hour, minute or None))
+            self.__setstate(hour, minute or None)
             return self
         _check_tzinfo_arg(tzinfo)
         _check_time_fields(hour, minute, second, microsecond)
@@ -1328,21 +1335,16 @@
         else:
             return (basestate, self._tzinfo)
 
-    def __setstate(self, state):
-        assert isinstance(state, tuple)
-        assert 1 <= len(state) <= 2
-        string = state[0]
-        assert len(string) == 6
+    def __setstate(self, string, tzinfo):
+        if len(string) != 6 or ord(string[0]) >= 24:
+            raise TypeError("an integer is required")
         self.__hour, self.__minute, self.__second, us1, us2, us3 = \
                                                             map(ord, string)
         self.__microsecond = (((us1 << 8) | us2) << 8) | us3
-        if len(state) == 1:
-            self._tzinfo = None
-        else:
-            self._tzinfo = state[1]
+        self._tzinfo = tzinfo
 
     def __reduce__(self):
-        return (self.__class__, self.__getstate())
+        return (time, self.__getstate())
 
 _time_class = time  # so functions w/ args named "time" can get at the class
 
@@ -1360,7 +1362,7 @@
         if isinstance(year, str):
             # Pickle support
             self = date.__new__(cls, year[:4])
-            self.__setstate((year, month))
+            self.__setstate(year, month)
             return self
         _check_tzinfo_arg(tzinfo)
         _check_time_fields(hour, minute, second, microsecond)
@@ -1395,6 +1397,10 @@
             converter = _time.localtime
         else:
             converter = _time.gmtime
+        if 1 - (t % 1.0) < 0.000001:
+            t = float(int(t)) + 1
+        if t < 0:
+            t -= 1
         y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
         us = int((t % 1.0) * 1000000)
         ss = min(ss, 59)    # clamp out leap seconds if the platform has them
@@ -1406,6 +1412,10 @@
 
     def utcfromtimestamp(cls, t):
         "Construct a UTC datetime from a POSIX timestamp (like time.time())."
+        if 1 - (t % 1.0) < 0.000001:
+            t = float(int(t)) + 1
+        if t < 0:
+            t -= 1
         y, m, d, hh, mm, ss, weekday, jday, dst = _time.gmtime(t)
         us = int((t % 1.0) * 1000000)
         ss = min(ss, 59)    # clamp out leap seconds if the platform has them
@@ -1559,8 +1569,10 @@
         "Convert to formal string, for repr()."
         L = [self.__year, self.__month, self.__day, # These are never zero
              self.__hour, self.__minute, self.__second, self.__microsecond]
-        while L[-1] == 0:
+        if L[-1] == 0:
             del L[-1]
+        if L[-1] == 0:
+            del L[-1]            
         s = ", ".join(map(str, L))
         s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s)
         if self._tzinfo is not None:
@@ -1572,6 +1584,11 @@
         "Convert to string, for str()."
         return self.isoformat(sep=' ')
 
+    @classmethod
+    def strptime(cls, date_string, format):
+        'string, format -> new datetime parsed from a string (like time.strptime()).'
+        return cls(*_time.strptime(date_string, format)[0:6])
+
     def utcoffset(self):
         """Return the timezone offset in minutes east of UTC (negative west of
         UTC)."""
@@ -1624,7 +1641,7 @@
     def __eq__(self, other):
         if isinstance(other, datetime):
             return self.__cmp(other) == 0
-        elif hasattr(other, "timetuple"):
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
             return NotImplemented
         else:
             return False
@@ -1632,7 +1649,7 @@
     def __ne__(self, other):
         if isinstance(other, datetime):
             return self.__cmp(other) != 0
-        elif hasattr(other, "timetuple"):
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
             return NotImplemented
         else:
             return True
@@ -1640,7 +1657,7 @@
     def __le__(self, other):
         if isinstance(other, datetime):
             return self.__cmp(other) <= 0
-        elif hasattr(other, "timetuple"):
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
             return NotImplemented
         else:
             _cmperror(self, other)
@@ -1648,7 +1665,7 @@
     def __lt__(self, other):
         if isinstance(other, datetime):
             return self.__cmp(other) < 0
-        elif hasattr(other, "timetuple"):
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
             return NotImplemented
         else:
             _cmperror(self, other)
@@ -1656,7 +1673,7 @@
     def __ge__(self, other):
         if isinstance(other, datetime):
             return self.__cmp(other) >= 0
-        elif hasattr(other, "timetuple"):
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
             return NotImplemented
         else:
             _cmperror(self, other)
@@ -1664,7 +1681,7 @@
     def __gt__(self, other):
         if isinstance(other, datetime):
             return self.__cmp(other) > 0
-        elif hasattr(other, "timetuple"):
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
             return NotImplemented
         else:
             _cmperror(self, other)
@@ -1712,7 +1729,7 @@
                   self.__second + other.seconds,
                   self.__microsecond + other.microseconds)
         self._checkOverflow(t.year)
-        result = self.__class__(t.year, t.month, t.day,
+        result = datetime(t.year, t.month, t.day,
                                 t.hour, t.minute, t.second,
                                 t.microsecond, tzinfo=self._tzinfo)
         return result
@@ -1767,19 +1784,12 @@
         else:
             return (basestate, self._tzinfo)
 
-    def __setstate(self, state):
-        assert isinstance(state, tuple)
-        assert 1 <= len(state) <= 2
-        string = state[0]
-        assert len(string) == 10
+    def __setstate(self, string, tzinfo):
         (yhi, ylo, self.__month, self.__day, self.__hour,
          self.__minute, self.__second, us1, us2, us3) = map(ord, string)
         self.__year = yhi * 256 + ylo
         self.__microsecond = (((us1 << 8) | us2) << 8) | us3
-        if len(state) == 1:
-            self._tzinfo = None
-        else:
-            self._tzinfo = state[1]
+        self._tzinfo = tzinfo
 
     def __reduce__(self):
         return (self.__class__, self.__getstate())
@@ -1999,9 +2009,3 @@
 pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
 """
 
-def _test():
-    import test_datetime
-    test_datetime.test_main()
-
-if __name__ == "__main__":
-    _test()


More information about the Python-checkins mailing list