[Python-checkins] python/nondist/sandbox/datetime US.py,1.14,1.15 datetime.py,1.139,1.140 doc.txt,1.78,1.79 test_datetime.py,1.93,1.94

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Thu, 02 Jan 2003 13:01:26 -0800


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

Modified Files:
	US.py datetime.py doc.txt test_datetime.py 
Log Message:
The tzinfo methods utcoffset() and dst() must return a timedelta object 
(or None) now.  In 2.3a1 they could also return an int or long, but that 
was an unhelpfully redundant leftover from an earlier version wherein 
they couldn't return a timedelta.  TOOWTDI.


Index: US.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/US.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -d -r1.14 -r1.15
*** US.py	31 Dec 2002 05:58:02 -0000	1.14
--- US.py	2 Jan 2003 21:01:19 -0000	1.15
***************
*** 130,140 ****
  Converting to UTC and subtracting, we get the "about an hour":
  
  >>> class UTC(tzinfo):
  ...     def utcoffset(self, dt):
! ...         return 0
  ...     def tzname(self, dt):
  ...         return "utc"
- ...     def dst(self, dt):
- ...         return 0
  
  >>> utc = UTC()
--- 130,140 ----
  Converting to UTC and subtracting, we get the "about an hour":
  
+ >>> ZERO = timedelta(0)
  >>> class UTC(tzinfo):
  ...     def utcoffset(self, dt):
! ...         return ZERO
! ...     dst = utcoffset
  ...     def tzname(self, dt):
  ...         return "utc"
  
  >>> utc = UTC()

Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.139
retrieving revision 1.140
diff -C2 -d -r1.139 -r1.140
*** datetime.py	2 Jan 2003 19:25:27 -0000	1.139
--- datetime.py	2 Jan 2003 21:01:19 -0000	1.140
***************
*** 237,241 ****
  # name is the offset-producing method, "utcoffset" or "dst".
  # offset is what it returned.
! # If offset isn't None, int, long, or timedelta, raises TypeError.
  # If offset is None, returns None.
  # Else offset is checked for being in range, and a whole # of minutes.
--- 237,241 ----
  # name is the offset-producing method, "utcoffset" or "dst".
  # offset is what it returned.
! # If offset isn't None or timedelta, raises TypeError.
  # If offset is None, returns None.
  # Else offset is checked for being in range, and a whole # of minutes.
***************
*** 245,262 ****
      if offset is None:
          return None
!     if not isinstance(offset, (int, long, timedelta)):
!         raise TypeError("tzinfo.%s() must return None, integer "
                          "or timedelta, not '%s'" % (name, type(offset)))
!     if isinstance(offset, timedelta):
!         days = offset.days
!         if days < -1 or days > 0:
!             offset = 1440  # trigger out-of-range
!         else:
!             seconds = days * 86400 + offset.seconds
!             minutes, seconds = divmod(seconds, 60)
!             if seconds or offset.microseconds:
!                 raise ValueError("tzinfo.%s() must return a whole number "
!                                  "of minutes" % name)
!             offset = minutes
      if -1440 < offset < 1440:
          return offset
--- 245,261 ----
      if offset is None:
          return None
!     if not isinstance(offset, timedelta):
!         raise TypeError("tzinfo.%s() must return None "
                          "or timedelta, not '%s'" % (name, type(offset)))
!     days = offset.days
!     if days < -1 or days > 0:
!         offset = 1440  # trigger out-of-range
!     else:
!         seconds = days * 86400 + offset.seconds
!         minutes, seconds = divmod(seconds, 60)
!         if seconds or offset.microseconds:
!             raise ValueError("tzinfo.%s() must return a whole number "
!                              "of minutes" % name)
!         offset = minutes
      if -1440 < offset < 1440:
          return offset

Index: doc.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/doc.txt,v
retrieving revision 1.78
retrieving revision 1.79
diff -C2 -d -r1.78 -r1.79
*** doc.txt	2 Jan 2003 19:25:27 -0000	1.78
--- doc.txt	2 Jan 2003 21:01:21 -0000	1.79
***************
*** 783,790 ****
      tzinfo object represents both time zone and DST adjustments,
      utcoffset() should return their sum.  If the UTC offset isn't known,
!     return None.  Else the value returned must be an int, long, or
!     timedelta object, in the range -1439 to 1439 inclusive (1440 = 24*60;
!     the magnitude of the offset must be less than one day, and must be
!     a whole number of minutes).  Most implementations of utcoffset()
      will probably look like:
  
--- 783,790 ----
      tzinfo object represents both time zone and DST adjustments,
      utcoffset() should return their sum.  If the UTC offset isn't known,
!     return None.  Else the value returned must be a timedelta object
!     specifying a whole number of minutes in the range -1439 to 1439
!     inclusive (1440 = 24*60; the magnitude of the offset must be less
!     than one day).  Most implementations of utcoffset()
      will probably look like:
  
***************
*** 798,809 ****
      Return the DST offset, in minutes east of UTC, or None if DST
      information isn't known.  Return 0 if DST is not in effect.
!     If DST is in effect, return an int, long, or timedelta object, in
!     the range -1439 to 1439 inclusive.  This must be a whole number of
!     minutes.  Note that DST offset, if applicable, has already been added
!     to the UTC offset returned by utcoffset(), so there's no need to
!     consult dst() unless you're interested in displaying DST info
!     separately.  For example, datetimetz.timetuple() calls its
!     tzinfo object's dst() method to determine how the tm_isdst flag
!     should be set.
  
      An instance tz of a tzinfo subclass that models both standard and
--- 798,809 ----
      Return the DST offset, in minutes east of UTC, or None if DST
      information isn't known.  Return 0 if DST is not in effect.
!     If DST is in effect, return the offset as a timedelta object (see
!     utcoffset() for details). Note that DST offset, if applicable, has
!     already been added to the UTC offset returned by utcoffset(), so
!     there's no need to consult dst() unless you're interested in
!     displaying DST info separately.  For example, datetimetz.timetuple()
!     calls its tzinfo object's dst() method to determine how the tm_isdst
!     flag should be set, and datetimetz.astimezone() calls dst() to
!     account for DST changes when crossing time zones.
  
      An instance tz of a tzinfo subclass that models both standard and
***************
*** 850,878 ****
  Example tzinfo classes:
  
!    class UTC(tzinfo):
!         "UTC"
          def utcoffset(self, dt):
!             return 0
          def tzname(self, dt):
              return "UTC"
          def dst(self, dt):
!             return 0
  
      class FixedOffset(tzinfo):
!         "Fixed offset in minutes east from UTC"
          def __init__(self, offset, name):
              self.__offset = offset
              self.__name = name
          def utcoffset(self, dt):
              return self.__offset
          def tzname(self, dt):
              return self.__name
          def dst(self, dt):
!             # It depends on more than we know in an example.
!             return None # Indicate we don't know
  
      import time
      class LocalTime(tzinfo):
!         "Local time as defined by the operating system"
          def _isdst(self, dt):
              t = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second,
--- 850,890 ----
  Example tzinfo classes:
  
!     from datetime import tzinfo, timedelta
! 
!     ZERO = timedelta(0)
! 
!     class UTC(tzinfo):
!         """UTC"""
! 
          def utcoffset(self, dt):
!             return ZERO
! 
          def tzname(self, dt):
              return "UTC"
+ 
          def dst(self, dt):
!             return ZERO
  
      class FixedOffset(tzinfo):
!         """Fixed offset in minutes east from UTC."""
! 
          def __init__(self, offset, name):
              self.__offset = offset
              self.__name = name
+ 
          def utcoffset(self, dt):
              return self.__offset
+ 
          def tzname(self, dt):
              return self.__name
+ 
          def dst(self, dt):
!             return ZERO
  
      import time
+ 
      class LocalTime(tzinfo):
!         """Local time as defined by the operating system."""
! 
          def _isdst(self, dt):
              t = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second,
***************
*** 881,889 ****
              t = time.localtime(time.mktime(t))
              return t.tm_isdst > 0
          def utcoffset(self, dt):
              if self._isdst(dt):
!                 return -time.timezone/60
              else:
!                 return -time.altzone/60
          def tzname(self, dt):
              return time.tzname[self._isdst(dt)]
--- 893,903 ----
              t = time.localtime(time.mktime(t))
              return t.tm_isdst > 0
+ 
          def utcoffset(self, dt):
              if self._isdst(dt):
!                 return timedelta(seconds=-time.timezone//60)
              else:
!                 return timedelta(seconds=-time.altzone//60)
! 
          def tzname(self, dt):
              return time.tzname[self._isdst(dt)]

Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v
retrieving revision 1.93
retrieving revision 1.94
diff -C2 -d -r1.93 -r1.94
*** test_datetime.py	2 Jan 2003 19:25:27 -0000	1.93
--- test_datetime.py	2 Jan 2003 21:01:22 -0000	1.94
***************
*** 44,47 ****
--- 44,51 ----
  class FixedOffset(tzinfo):
      def __init__(self, offset, name, dstoffset=42):
+         if isinstance(offset, int):
+             offset = timedelta(minutes=offset)
+         if isinstance(dstoffset, int):
+             dstoffset = timedelta(minutes=dstoffset)
          self.__offset = offset
          self.__name = name
***************
*** 90,96 ****
          self.failUnless(isinstance(fo, tzinfo))
          for dt in datetime.now(), None:
!             self.assertEqual(fo.utcoffset(dt), 3)
              self.assertEqual(fo.tzname(dt), "Three")
!             self.assertEqual(fo.dst(dt), 42)
  
      def test_pickling_base(self):
--- 94,100 ----
          self.failUnless(isinstance(fo, tzinfo))
          for dt in datetime.now(), None:
!             self.assertEqual(fo.utcoffset(dt), timedelta(minutes=3))
              self.assertEqual(fo.tzname(dt), "Three")
!             self.assertEqual(fo.dst(dt), timedelta(minutes=42))
  
      def test_pickling_base(self):
***************
*** 112,119 ****
  
          # Make sure we can pickle/unpickle an instance of a subclass.
!         orig = PicklableFixedOffset(-300, 'cookie')
          self.failUnless(isinstance(orig, tzinfo))
          self.failUnless(type(orig) is PicklableFixedOffset)
!         self.assertEqual(orig.utcoffset(None), -300)
          self.assertEqual(orig.tzname(None), 'cookie')
          for pickler in pickle, cPickle:
--- 116,124 ----
  
          # Make sure we can pickle/unpickle an instance of a subclass.
!         offset = timedelta(minutes=-300)
!         orig = PicklableFixedOffset(offset, 'cookie')
          self.failUnless(isinstance(orig, tzinfo))
          self.failUnless(type(orig) is PicklableFixedOffset)
!         self.assertEqual(orig.utcoffset(None), offset)
          self.assertEqual(orig.tzname(None), 'cookie')
          for pickler in pickle, cPickle:
***************
*** 123,127 ****
                  self.failUnless(isinstance(derived, tzinfo))
                  self.failUnless(type(derived) is PicklableFixedOffset)
!                 self.assertEqual(derived.utcoffset(None), -300)
                  self.assertEqual(derived.tzname(None), 'cookie')
  
--- 128,132 ----
                  self.failUnless(isinstance(derived, tzinfo))
                  self.failUnless(type(derived) is PicklableFixedOffset)
!                 self.assertEqual(derived.utcoffset(None), offset)
                  self.assertEqual(derived.tzname(None), 'cookie')
  
***************
*** 1575,1579 ****
          class introspective(tzinfo):
              def tzname(self, dt):    return dt and "real" or "none"
!             def utcoffset(self, dt): return dt and 42 or -42
              dst = utcoffset
  
--- 1580,1585 ----
          class introspective(tzinfo):
              def tzname(self, dt):    return dt and "real" or "none"
!             def utcoffset(self, dt):
!                 return timedelta(minutes = dt and 42 or -42)
              dst = utcoffset
  
***************
*** 1606,1610 ****
          class Edgy(tzinfo):
              def __init__(self, offset):
!                 self.offset = offset
              def utcoffset(self, dt):
                  return self.offset
--- 1612,1616 ----
          class Edgy(tzinfo):
              def __init__(self, offset):
!                 self.offset = timedelta(minutes=offset)
              def utcoffset(self, dt):
                  return self.offset
***************
*** 1642,1662 ****
              self.failUnless(t.tzname() is None)
  
-         class C2(tzinfo):
-             def utcoffset(self, dt): return -1439
-             def dst(self, dt): return 1439
-             def tzname(self, dt): return "aname"
          class C3(tzinfo):
              def utcoffset(self, dt): return timedelta(minutes=-1439)
              def dst(self, dt): return timedelta(minutes=1439)
              def tzname(self, dt): return "aname"
!         for t in cls(1, 1, 1, tzinfo=C2()), cls(1, 1, 1, tzinfo=C3()):
!             self.assertEqual(t.utcoffset(), timedelta(minutes=-1439))
!             self.assertEqual(t.dst(), timedelta(minutes=1439))
!             self.assertEqual(t.tzname(), "aname")
  
          # Wrong types.
          class C4(tzinfo):
              def utcoffset(self, dt): return "aname"
!             def dst(self, dt): return ()
              def tzname(self, dt): return 0
          t = cls(1, 1, 1, tzinfo=C4())
--- 1648,1664 ----
              self.failUnless(t.tzname() is None)
  
          class C3(tzinfo):
              def utcoffset(self, dt): return timedelta(minutes=-1439)
              def dst(self, dt): return timedelta(minutes=1439)
              def tzname(self, dt): return "aname"
!         t = cls(1, 1, 1, tzinfo=C3())
!         self.assertEqual(t.utcoffset(), timedelta(minutes=-1439))
!         self.assertEqual(t.dst(), timedelta(minutes=1439))
!         self.assertEqual(t.tzname(), "aname")
  
          # Wrong types.
          class C4(tzinfo):
              def utcoffset(self, dt): return "aname"
!             def dst(self, dt): return 7
              def tzname(self, dt): return 0
          t = cls(1, 1, 1, tzinfo=C4())
***************
*** 1666,1678 ****
  
          # Offset out of range.
-         class C5(tzinfo):
-             def utcoffset(self, dt): return -1440
-             def dst(self, dt): return 1440
          class C6(tzinfo):
              def utcoffset(self, dt): return timedelta(hours=-24)
              def dst(self, dt): return timedelta(hours=24)
!         for t in cls(1, 1, 1, tzinfo=C5()), cls(1, 1, 1, tzinfo=C6()):
!             self.assertRaises(ValueError, t.utcoffset)
!             self.assertRaises(ValueError, t.dst)
  
          # Not a whole number of minutes.
--- 1668,1677 ----
  
          # Offset out of range.
          class C6(tzinfo):
              def utcoffset(self, dt): return timedelta(hours=-24)
              def dst(self, dt): return timedelta(hours=24)
!         t = cls(1, 1, 1, tzinfo=C6())
!         self.assertRaises(ValueError, t.utcoffset)
!         self.assertRaises(ValueError, t.dst)
  
          # Not a whole number of minutes.
***************
*** 1692,1698 ****
              def utcoffset(self, t):
                  if t.minute < 10:
!                     return t.minute # d0 and d1 equal after adjustment
                  else:
!                     return 59       # d2 off in the weeds
  
          base = cls(8, 9, 10, tzinfo=OperandDependentOffset())
--- 1691,1699 ----
              def utcoffset(self, t):
                  if t.minute < 10:
!                     # d0 and d1 equal after adjustment
!                     return timedelta(minutes=t.minute)
                  else:
!                     # d2 off in the weeds
!                     return timedelta(minutes=59)
  
          base = cls(8, 9, 10, tzinfo=OperandDependentOffset())
***************
*** 1951,1957 ****
          class Varies(tzinfo):
              def __init__(self):
!                 self.offset = 22
              def utcoffset(self, t):
!                 self.offset += 1
                  return self.offset
  
--- 1952,1958 ----
          class Varies(tzinfo):
              def __init__(self):
!                 self.offset = timedelta(minutes=22)
              def utcoffset(self, t):
!                 self.offset += timedelta(minutes=1)
                  return self.offset
  
***************
*** 2042,2046 ****
          # Try a bogus uctoffset.
          class Bogus(tzinfo):
!             def utcoffset(self, dt): return 1440 # out of bounds
          t1 = self.theclass(2, 2, 2, tzinfo=Bogus())
          t2 = self.theclass(2, 2, 2, tzinfo=FixedOffset(0, ""))
--- 2043,2048 ----
          # Try a bogus uctoffset.
          class Bogus(tzinfo):
!             def utcoffset(self, dt):
!                 return timedelta(minutes=1440) # out of bounds
          t1 = self.theclass(2, 2, 2, tzinfo=Bogus())
          t2 = self.theclass(2, 2, 2, tzinfo=FixedOffset(0, ""))
***************
*** 2273,2276 ****
--- 2275,2280 ----
          class DST(tzinfo):
              def __init__(self, dstvalue):
+                 if isinstance(dstvalue, int):
+                     dstvalue = timedelta(minutes=dstvalue)
                  self.dstvalue = dstvalue
              def dst(self, dt):
***************
*** 2305,2308 ****
--- 2309,2314 ----
          class DST(tzinfo):
              def __init__(self, dstvalue):
+                 if isinstance(dstvalue, int):
+                     dstvalue = timedelta(minutes=dstvalue)
                  self.dstvalue = dstvalue
              def dst(self, dt):
***************
*** 2317,2321 ****
              def __init__(self, uofs, dofs=None):
                  DST.__init__(self, dofs)
!                 self.uofs = uofs
              def utcoffset(self, dt):
                  return self.uofs
--- 2323,2327 ----
              def __init__(self, uofs, dofs=None):
                  DST.__init__(self, dofs)
!                 self.uofs = timedelta(minutes=uofs)
              def utcoffset(self, dt):
                  return self.uofs
***************
*** 2468,2474 ****
              def utcoffset(self, t):
                  if t.minute < 10:
!                     return t.minute # d0 and d1 equal after adjustment
                  else:
!                     return 59       # d2 off in the weeds
  
          base = cls(8, 9, 10, 11, 12, 13, 14, tzinfo=OperandDependentOffset())
--- 2474,2482 ----
              def utcoffset(self, t):
                  if t.minute < 10:
!                     # d0 and d1 equal after adjustment
!                     return timedelta(minutes=t.minute)
                  else:
!                     # d2 off in the weeds
!                     return timedelta(minutes=59)
  
          base = cls(8, 9, 10, 11, 12, 13, 14, tzinfo=OperandDependentOffset())
***************
*** 2517,2523 ****
          class Varies(tzinfo):
              def __init__(self):
!                 self.offset = 22
              def utcoffset(self, t):
!                 self.offset += 1
                  return self.offset
  
--- 2525,2531 ----
          class Varies(tzinfo):
              def __init__(self):
!                 self.offset = timedelta(minutes=22)
              def utcoffset(self, t):
!                 self.offset += timedelta(minutes=1)
                  return self.offset