[Python-checkins] python/nondist/sandbox/datetime datetime.py,1.149,1.150 test_datetime.py,1.102,1.103

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Thu, 23 Jan 2003 13:22:19 -0800


Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory sc8-pr-cvs1:/tmp/cvs-serv22861

Modified Files:
	datetime.py test_datetime.py 
Log Message:
SF bug 660872: datetimetz constructors behave counterintuitively (2.3a1)
datetime .now() and .fromtimestamp():  The undocumented optional tzinfo=
argument is documented in the LaTeX docs now, and its name was changed
to tz= ("tzinfo" had enough meanings without this one).  These
constructors previously returned local time, and passively attached the
tzinfo argument to the result; "passively" == no conversion of date or
time members was done.  This was less than useful.  Now they convert
platform-local date and time to local time in tz's time zone, if tz is
specified.  If tz is not specified, they continue to return a naive
datetime object with platform-local date and time (as returned by the
platform C localtime() function).


Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.149
retrieving revision 1.150
diff -C2 -d -r1.149 -r1.150
*** datetime.py	22 Jan 2003 20:22:23 -0000	1.149
--- datetime.py	23 Jan 2003 21:22:13 -0000	1.150
***************
*** 1197,1209 ****
      tzinfo = property(lambda self: self._tzinfo, doc="timezone info object")
  
!     def fromtimestamp(cls, t, tzinfo=None):
          """Construct a datetime from a POSIX timestamp (like time.time()).
  
          A timezone info object may be passed in as well.
          """
!         y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
          us = int((t % 1.0) * 1000000)
          ss = min(ss, 59)    # clamp out leap seconds if the platform has them
!         return cls(y, m, d, hh, mm, ss, us, tzinfo)
      fromtimestamp = classmethod(fromtimestamp)
  
--- 1197,1218 ----
      tzinfo = property(lambda self: self._tzinfo, doc="timezone info object")
  
!     def fromtimestamp(cls, t, tz=None):
          """Construct a datetime from a POSIX timestamp (like time.time()).
  
          A timezone info object may be passed in as well.
          """
! 
!         _check_tzinfo_arg(tz)
!         if tz is None:
!             converter = _time.localtime
!         else:
!             converter = _time.gmtime
!         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
!         result = cls(y, m, d, hh, mm, ss, us, tz)
!         if tz is not None:
!             result = tz.fromutc(result)
!         return result
      fromtimestamp = classmethod(fromtimestamp)
  
***************
*** 1221,1228 ****
      # XXX available from Python.  So now() may return different results
      # XXX across the implementations.
!     def now(cls, tzinfo=None):
          "Construct a datetime from time.time() and optional time zone info."
          t = _time.time()
!         return cls.fromtimestamp(t, tzinfo)
      now = classmethod(now)
  
--- 1230,1237 ----
      # XXX available from Python.  So now() may return different results
      # XXX across the implementations.
!     def now(cls, tz=None):
          "Construct a datetime from time.time() and optional time zone info."
          t = _time.time()
!         return cls.fromtimestamp(t, tz)
      now = classmethod(now)
  

Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v
retrieving revision 1.102
retrieving revision 1.103
diff -C2 -d -r1.102 -r1.103
*** test_datetime.py	22 Jan 2003 20:49:21 -0000	1.102
--- test_datetime.py	23 Jan 2003 21:22:14 -0000	1.103
***************
*** 2227,2231 ****
          off42 = FixedOffset(42, "42")
          another = meth(off42)
!         again = meth(tzinfo=off42)
          self.failUnless(another.tzinfo is again.tzinfo)
          self.assertEqual(another.utcoffset(), timedelta(minutes=42))
--- 2227,2231 ----
          off42 = FixedOffset(42, "42")
          another = meth(off42)
!         again = meth(tz=off42)
          self.failUnless(another.tzinfo is again.tzinfo)
          self.assertEqual(another.utcoffset(), timedelta(minutes=42))
***************
*** 2238,2241 ****
--- 2238,2259 ----
          self.assertRaises(TypeError, meth, off42, off42)
  
+         # We don't know which time zone we're in, and don't have a tzinfo
+         # class to represent it, so seeing whether a tz argument actually
+         # does a conversion is tricky.
+         weirdtz = FixedOffset(timedelta(hours=15, minutes=58), "weirdtz", 0)
+         utc = FixedOffset(0, "utc", 0)
+         for dummy in range(3):
+             now = datetime.now(weirdtz)
+             self.failUnless(now.tzinfo is weirdtz)
+             utcnow = datetime.utcnow().replace(tzinfo=utc)
+             now2 = utcnow.astimezone(weirdtz)
+             if abs(now - now2) < timedelta(seconds=30):
+                 break
+             # Else the code is broken, or more than 30 seconds passed between
+             # calls; assuming the latter, just try again.
+         else:
+             # Three strikes and we're out.
+             self.fail("utcnow(), now(tz), or astimezone() may be broken")
+ 
      def test_tzinfo_fromtimestamp(self):
          import time
***************
*** 2247,2251 ****
          off42 = FixedOffset(42, "42")
          another = meth(ts, off42)
!         again = meth(ts, tzinfo=off42)
          self.failUnless(another.tzinfo is again.tzinfo)
          self.assertEqual(another.utcoffset(), timedelta(minutes=42))
--- 2265,2269 ----
          off42 = FixedOffset(42, "42")
          another = meth(ts, off42)
!         again = meth(ts, tz=off42)
          self.failUnless(another.tzinfo is again.tzinfo)
          self.assertEqual(another.utcoffset(), timedelta(minutes=42))
***************
*** 2260,2263 ****
--- 2278,2295 ----
          self.assertRaises(TypeError, meth)
  
+         # Try to make sure tz= actually does some conversion.
+         timestamp = 1000000000  #  2001-09-09 01:46:40 UTC, give or take
+         utc = FixedOffset(0, "utc", 0)
+         expected = datetime(2001, 9, 9, 1, 46, 40)
+         got = datetime.utcfromtimestamp(timestamp)
+         # We don't support leap seconds, but maybe the platfrom insists
+         # on using them, so don't demand exact equality).
+         self.failUnless(abs(got - expected) < timedelta(minutes=1))
+ 
+         est = FixedOffset(-5*60, "est", 0)
+         expected -= timedelta(hours=5)
+         got = datetime.fromtimestamp(timestamp, est).replace(tzinfo=None)
+         self.failUnless(abs(got - expected) < timedelta(minutes=1))
+ 
      def test_tzinfo_utcnow(self):
          meth = self.theclass.utcnow
***************
*** 2447,2451 ****
          fm5h = FixedOffset(-timedelta(hours=5), "m300")
  
!         dt = self.theclass.now(tzinfo=f44m)
          self.failUnless(dt.tzinfo is f44m)
          # Replacing with degenerate tzinfo raises an exception.
--- 2479,2483 ----
          fm5h = FixedOffset(-timedelta(hours=5), "m300")
  
!         dt = self.theclass.now(tz=f44m)
          self.failUnless(dt.tzinfo is f44m)
          # Replacing with degenerate tzinfo raises an exception.