[Zope3-checkins] CVS: Zope3/lib/python/datetime - _datetime.py:1.14 doc.txt:1.2
Tim Peters
tim.one@comcast.net
Sat, 21 Dec 2002 21:02:52 -0500
Update of /cvs-repository/Zope3/lib/python/datetime
In directory cvs.zope.org:/tmp/cvs-serv20490/lib/python/datetime
Modified Files:
_datetime.py doc.txt
Log Message:
Relatively massive changes to implement a Wiki suggestion:
{timetz,datetimetz}.{utcoffset,dst}() now return a timetuple (or None)
instead of an int (or None).
tzinfo.{utcoffset,dst)() can now return a timetuple (or an int, or None).
The change is so invasive primarily because the *internals* don't want to
work with timetuples at all, so every internal use of utcoffset() and
dst() had to change.
=== Zope3/lib/python/datetime/_datetime.py 1.13 => 1.14 ===
--- Zope3/lib/python/datetime/_datetime.py:1.13 Sat Dec 21 12:42:02 2002
+++ Zope3/lib/python/datetime/_datetime.py Sat Dec 21 21:02:20 2002
@@ -164,7 +164,7 @@
# Correctly substitute for %z and %Z escapes in strftime formats.
def _wrap_strftime(object, format, timetuple):
- # Don't call utcoffset() or tzname() unless actually needed.
+ # Don't call _utcoffset() or tzname() unless actually needed.
zreplace = None # the string to use for %z
Zreplace = None # the string to use for %Z
@@ -182,8 +182,8 @@
if ch == 'z':
if zreplace is None:
zreplace = ""
- if hasattr(object, "utcoffset"):
- offset = object.utcoffset()
+ if hasattr(object, "_utcoffset"):
+ offset = object._utcoffset()
if offset is not None:
sign = '+'
if offset < 0:
@@ -217,20 +217,40 @@
return None
return getattr(tzinfo, methname)(self)
+# Just raise TypeError if the arg isn't None or a string.
+def _check_tzname(name):
+ if name is not None and not isinstance(name, str):
+ raise TypeError("tzinfo.tzname() must return None or string, "
+ "not '%s'" % type(name))
+
+# 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.
+# If it is, its integer value is returned. Else ValueError is raised.
def _check_utc_offset(name, offset):
+ assert name in ("utcoffset", "dst")
if offset is None:
- return
+ 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
+ return offset
raise ValueError("%s()=%d, must be in -1439..1439" % (name, offset))
-def _check_tzname(name):
- if name is not None and not isinstance(name, str):
- raise TypeError("tzinfo.tzname() must return None or string, "
- "not '%s'" % type(name))
# This is a start at a struct tm workalike. Goals:
#
@@ -1007,8 +1027,8 @@
ottz = other.__tzinfo
if mytz is ottz:
return supercmp(other)
- myoff = self.utcoffset()
- otoff = other.utcoffset()
+ myoff = self._utcoffset()
+ otoff = other._utcoffset()
if myoff == otoff:
return supercmp(other)
if myoff is None or otoff is None:
@@ -1020,7 +1040,7 @@
def __hash__(self):
"""Hash."""
- tzoff = self.utcoffset()
+ tzoff = self._utcoffset()
if not tzoff: # zero or None!
return super(timetz, self).__hash__()
h, m = divmod(self.hour * 60 + self.minute - tzoff, 60)
@@ -1034,7 +1054,7 @@
def _tzstr(self, sep=":"):
"""Return formatted timezone offset (+xx:xx) or None."""
- off = self.utcoffset()
+ off = self._utcoffset()
if off is not None:
if off < 0:
sign = "-"
@@ -1042,8 +1062,7 @@
else:
sign = "+"
hh, mm = divmod(off, 60)
- if hh >= 24:
- raise ValueError("utcoffset must be in -1439 .. 1439")
+ assert 0 <= hh < 24
off = "%s%02d%s%02d" % (sign, hh, sep, mm)
return off
@@ -1074,7 +1093,15 @@
"""Return the timezone offset in minutes east of UTC (negative west of
UTC)."""
offset = _call_tzinfo_method(self, self.__tzinfo, "utcoffset")
- _check_utc_offset("utcoffset", offset)
+ offset = _check_utc_offset("utcoffset", offset)
+ if offset is not None:
+ offset = timedelta(minutes=offset)
+ return offset
+
+ # Return an integer (or None) instead of a timedelta (or None).
+ def _utcoffset(self):
+ offset = _call_tzinfo_method(self, self.__tzinfo, "utcoffset")
+ offset = _check_utc_offset("utcoffset", offset)
return offset
def tzname(self):
@@ -1098,13 +1125,21 @@
info.
"""
offset = _call_tzinfo_method(self, self.__tzinfo, "dst")
- _check_utc_offset("dst", offset)
+ offset = _check_utc_offset("dst", offset)
+ if offset is not None:
+ offset = timedelta(minutes=offset)
+ return offset
+
+ # Return an integer (or None) instead of a timedelta (or None).
+ def _dst(self):
+ offset = _call_tzinfo_method(self, self.__tzinfo, "dst")
+ offset = _check_utc_offset("dst", offset)
return offset
def __nonzero__(self):
if self.second or self.microsecond:
return 1
- offset = self.utcoffset() or 0
+ offset = self._utcoffset() or 0
return self.hour * 60 + self.minute - offset != 0
# Pickle support.
@@ -1429,7 +1464,7 @@
def timetuple(self):
"Return local time tuple compatible with time.localtime()."
- dst = self.dst()
+ dst = self._dst()
if dst is None:
dst = -1
elif dst:
@@ -1442,7 +1477,7 @@
"Return UTC time tuple compatible with time.gmtime()."
y, m, d = self.year, self.month, self.day
hh, mm, ss = self.hour, self.minute, self.second
- offset = self.utcoffset()
+ offset = self._utcoffset()
if offset: # neither None nor 0
tm = tmxxx(y, m, d, hh, mm - offset)
y, m, d = tm.year, tm.month, tm.day
@@ -1456,7 +1491,7 @@
def isoformat(self, sep='T'):
s = super(datetimetz, self).isoformat(sep)
- off = self.utcoffset()
+ off = self._utcoffset()
if off is not None:
if off < 0:
sign = "-"
@@ -1478,7 +1513,15 @@
"""Return the timezone offset in minutes east of UTC (negative west of
UTC)."""
offset = _call_tzinfo_method(self, self.__tzinfo, "utcoffset")
- _check_utc_offset("utcoffset", offset)
+ offset = _check_utc_offset("utcoffset", offset)
+ if offset is not None:
+ offset = timedelta(minutes=offset)
+ return offset
+
+ # Return an integer (or None) instead of a timedelta (or None).
+ def _utcoffset(self):
+ offset = _call_tzinfo_method(self, self.__tzinfo, "utcoffset")
+ offset = _check_utc_offset("utcoffset", offset)
return offset
def tzname(self):
@@ -1502,7 +1545,15 @@
info.
"""
offset = _call_tzinfo_method(self, self.__tzinfo, "dst")
- _check_utc_offset("dst", offset)
+ offset = _check_utc_offset("dst", offset)
+ if offset is not None:
+ offset = timedelta(minutes=offset)
+ return offset
+
+ # Return an integer (or None) instead of a timedelta (or None).1573
+ def _dst(self):
+ offset = _call_tzinfo_method(self, self.__tzinfo, "dst")
+ offset = _check_utc_offset("dst", offset)
return offset
def __add__(self, other):
@@ -1523,8 +1574,8 @@
ottz = other.__tzinfo
if mytz is ottz:
return supersub(other)
- myoff = self.utcoffset()
- otoff = other.utcoffset()
+ myoff = self._utcoffset()
+ otoff = other._utcoffset()
if myoff == otoff:
return supersub(other)
if myoff is None or otoff is None:
@@ -1537,10 +1588,10 @@
type(other).__name__)
superself = super(datetimetz, self)
supercmp = superself.__cmp__
- myoff = self.utcoffset()
+ myoff = self._utcoffset()
otoff = None
if isinstance(other, datetimetz):
- otoff = other.utcoffset()
+ otoff = other._utcoffset()
if myoff == otoff:
return supercmp(other)
if myoff is None or otoff is None:
@@ -1554,7 +1605,7 @@
return 1
def __hash__(self):
- tzoff = self.utcoffset()
+ tzoff = self._utcoffset()
if tzoff is None:
return super(datetimetz, self).__hash__()
days = _ymd2ord(self.year, self.month, self.day)
=== Zope3/lib/python/datetime/doc.txt 1.1 => 1.2 ===
--- Zope3/lib/python/datetime/doc.txt:1.1 Sat Dec 21 00:10:43 2002
+++ Zope3/lib/python/datetime/doc.txt Sat Dec 21 21:02:21 2002
@@ -759,9 +759,10 @@
is intended to be the total offset from UTC; for example, if a
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 (or long), in
- the range -1439 to 1439 inclusive (1440 = 24*60; the magnitude of
- the offset must be less than one day).
+ 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).
- tzname(dt)
Return the timezone name corresponding to the datetime represented
@@ -777,13 +778,14 @@
- dst(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 (or long), in the range
- -1439 to 1439 inclusive. 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.
+ 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.
Example tzinfo classes:
@@ -923,19 +925,19 @@
format string. See the section on strftime() behavior.
- utcoffset()
- If self.tzinfo is None, returns None, else self.tzinfo.utcoffset(self).
+ If self.tzinfo is None, returns None, else self.tzinfo.utcoffset(self),
+ converted a timedelta object.
- tzname():
If self.tzinfo is None, returns None, else self.tzinfo.tzname(self).
- dst()
- If self.tzinfo is None, returns None, else self.tzinfo.dst(self).
+ If self.tzinfo is None, returns None, else self.tzinfo.dst(self),
+ converted to a timedelta object.
class datetimetz
================
-XXX I think this is *still* missing some methods from the
-XXX Python implementation.
A datetimetz object is a single object containing all the information
from a date object and a timetz object.
@@ -1072,12 +1074,14 @@
- utcoffset()
If self.tzinfo is None, returns None, else self.tzinfo.utcoffset(self).
+ converted to a timedelta object.
- tzname():
If self.tzinfo is None, returns None, else self.tzinfo.tzname(self).
- dst()
- If self.tzinfo is None, returns None, else self.tzinfo.dst(self).
+ If self.tzinfo is None, returns None, else self.tzinfo.dst(self),
+ converted to a timedelta object.
- timetuple()
Like datetime.timetuple(), but sets the tm_isdst flag according to