[Zope3-checkins] CVS: Zope3/src/datetime - _datetime.py:1.7 doc.txt:1.5

Tim Peters tim.one@comcast.net
Mon, 30 Dec 2002 14:46:24 -0500


Update of /cvs-repository/Zope3/src/datetime
In directory cvs.zope.org:/tmp/cvs-serv5072/src/datetime

Modified Files:
	_datetime.py doc.txt 
Log Message:
A step on the way to making tzinfo classes writable by mortals:  get rid
of the timetz case.  A tzinfo method will always see a datetimetz arg,
or None, now.  In the former case, it's still possible that it will get
a datetimetz argument belonging to a different timezone.  That will get
fixed next (but I have to pause to bring the 2.3 C implementation into
synch with this change first).


=== Zope3/src/datetime/_datetime.py 1.6 => 1.7 ===
--- Zope3/src/datetime/_datetime.py:1.6	Fri Dec 27 16:34:51 2002
+++ Zope3/src/datetime/_datetime.py	Mon Dec 30 14:45:53 2002
@@ -216,10 +216,10 @@
     newformat = "".join(newformat)
     return _time.strftime(newformat, timetuple)
 
-def _call_tzinfo_method(self, tzinfo, methname):
+def _call_tzinfo_method(tzinfo, methname, tzinfoarg):
     if tzinfo is None:
         return None
-    return getattr(tzinfo, methname)(self)
+    return getattr(tzinfo, methname)(tzinfoarg)
 
 # Just raise TypeError if the arg isn't None or a string.
 def _check_tzname(name):
@@ -1128,7 +1128,7 @@
     def utcoffset(self):
         """Return the timezone offset in minutes east of UTC (negative west of
         UTC)."""
-        offset = _call_tzinfo_method(self, self._tzinfo, "utcoffset")
+        offset = _call_tzinfo_method(self._tzinfo, "utcoffset", None)
         offset = _check_utc_offset("utcoffset", offset)
         if offset is not None:
             offset = timedelta(minutes=offset)
@@ -1136,7 +1136,7 @@
 
     # Return an integer (or None) instead of a timedelta (or None).
     def _utcoffset(self):
-        offset = _call_tzinfo_method(self, self._tzinfo, "utcoffset")
+        offset = _call_tzinfo_method(self._tzinfo, "utcoffset", None)
         offset = _check_utc_offset("utcoffset", offset)
         return offset
 
@@ -1147,7 +1147,7 @@
         it mean anything in particular. For example, "GMT", "UTC", "-500",
         "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
         """
-        name = _call_tzinfo_method(self, self._tzinfo, "tzname")
+        name = _call_tzinfo_method(self._tzinfo, "tzname", None)
         _check_tzname(name)
         return name
 
@@ -1160,7 +1160,7 @@
         need to consult dst() unless you're interested in displaying the DST
         info.
         """
-        offset = _call_tzinfo_method(self, self._tzinfo, "dst")
+        offset = _call_tzinfo_method(self._tzinfo, "dst", None)
         offset = _check_utc_offset("dst", offset)
         if offset is not None:
             offset = timedelta(minutes=offset)
@@ -1185,7 +1185,7 @@
 
     # Return an integer (or None) instead of a timedelta (or None).
     def _dst(self):
-        offset = _call_tzinfo_method(self, self._tzinfo, "dst")
+        offset = _call_tzinfo_method(self._tzinfo, "dst", None)
         offset = _check_utc_offset("dst", offset)
         return offset
 
@@ -1649,7 +1649,7 @@
     def utcoffset(self):
         """Return the timezone offset in minutes east of UTC (negative west of
         UTC)."""
-        offset = _call_tzinfo_method(self, self._tzinfo, "utcoffset")
+        offset = _call_tzinfo_method(self._tzinfo, "utcoffset", self)
         offset = _check_utc_offset("utcoffset", offset)
         if offset is not None:
             offset = timedelta(minutes=offset)
@@ -1657,7 +1657,7 @@
 
     # Return an integer (or None) instead of a timedelta (or None).
     def _utcoffset(self):
-        offset = _call_tzinfo_method(self, self._tzinfo, "utcoffset")
+        offset = _call_tzinfo_method(self._tzinfo, "utcoffset", self)
         offset = _check_utc_offset("utcoffset", offset)
         return offset
 
@@ -1668,7 +1668,7 @@
         it mean anything in particular. For example, "GMT", "UTC", "-500",
         "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
         """
-        name = _call_tzinfo_method(self, self._tzinfo, "tzname")
+        name = _call_tzinfo_method(self._tzinfo, "tzname", self)
         _check_tzname(name)
         return name
 
@@ -1681,7 +1681,7 @@
         need to consult dst() unless you're interested in displaying the DST
         info.
         """
-        offset = _call_tzinfo_method(self, self._tzinfo, "dst")
+        offset = _call_tzinfo_method(self._tzinfo, "dst", self)
         offset = _check_utc_offset("dst", offset)
         if offset is not None:
             offset = timedelta(minutes=offset)
@@ -1689,7 +1689,7 @@
 
     # Return an integer (or None) instead of a timedelta (or None).1573
     def _dst(self):
-        offset = _call_tzinfo_method(self, self._tzinfo, "dst")
+        offset = _call_tzinfo_method(self._tzinfo, "dst", self)
         offset = _check_utc_offset("dst", offset)
         return offset
 


=== Zope3/src/datetime/doc.txt 1.4 => 1.5 ===
--- Zope3/src/datetime/doc.txt:1.4	Fri Dec 27 16:34:51 2002
+++ Zope3/src/datetime/doc.txt	Mon Dec 30 14:45:53 2002
@@ -759,7 +759,7 @@
 tzinfo is an abstract base clase, meaning that objects directly of this
 class should not be instantiated.  You need to derive a concrete
 subclass, and (at least) supply implementations of the standard tzinfo
-methods needed by the datetime methods you use. The datetime module does
+methods needed by the datetime methods you use.  The datetime module does
 not supply any concrete subclasses of tzinfo.
 
 An instance of (a concrete subclass of) tzinfo can be passed to the
@@ -776,12 +776,9 @@
 
 A concrete subclass of tzinfo may need to implement the following
 methods.  Exactly which methods are needed depends on the uses made
-of aware datetime objects; if in doubt, simply implement all of them.
-The methods are called by a datetimetz or timetz object, passing itself
-as the argument.  A tzinfo subclass's methods should be prepared to
-accept an argument of type None, timetz, or datetimetz.
+of aware datetime objects.  If in doubt, simply implement all of them.
 
-  - utcoffset(dt)
+  - utcoffset(self, dt)
     Return offset of local time from UTC, in minutes east of UTC.  If
     local time is west of UTC, this should be negative.  Note that this
     is intended to be the total offset from UTC; for example, if a
@@ -790,9 +787,13 @@
     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).
+    a whole number of minutes).  Most implementations of utcoffset()
+    will probably look like:
 
-  - tzname(dt)
+        return CONSTANT  # fixed-offset class
+        return CONSTANT + self.dst(dt)  # daylight-aware class
+
+  - tzname(self, dt)
     Return the timezone name corresponding to the datetime represented
     by dt, as a string.  Nothing about string names is defined by the
     datetime module, and there's no requirement that it mean anything
@@ -803,7 +804,7 @@
     will wish to return different names depending on the specific value
     of dt passed, especially if the tzinfo class is accounting for DST.
 
-  - dst(dt)
+  - dst(self, dt)
     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
@@ -814,6 +815,27 @@
     separately.  For example, datetimetz.timetuple() calls its
     tzinfo object's dst() method to determine how the tm_isdst flag
     should be set.
+
+These methods are called by a datetimetz or timetz object, in response to
+their methods of the same names.  A datetimetz object passes itself as the
+argument, and a timetz object passes None as the argument.  A tzinfo
+subclass's methods should therefore be prepared to accept a dt argument of
+None, or of class datetimetz.
+
+When None is passed, it's up to the class designer to decide the best
+response.  For example, returning None is appropriate if the class wishes
+to say that timetz objects don't participate in the tzinfo protocol.  In
+other applications, it may be more useful for utcoffset(None} to return the
+standard UTC offset.
+
+When a datetimetz object is passed in response to a datetimetz method,
+dt.tzinfo is the same object as self.  tzinfo methods can rely on this,
+unless user code calls tzinfo methods directly.  The intent is that the
+tzinfo methods interpret dt as being in local time, and not need to worry
+about objects in other timezones.
+XXX That isn't always true yet:  datetimetz.astimezone(tz) can pass
+XXX a datetimetz with a "foreign" tzinfo to a self.tzinfo method.  This
+XXX needs to be repaired.
 
 Example tzinfo classes: