Update of /cvsroot/python/python/nondist/sandbox/datetime In directory sc8-pr-cvs1:/tmp/cvs-serv30286 Modified Files: US.py datetime.py doc.txt test_datetime.py 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). Index: US.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/US.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** US.py 28 Dec 2002 18:16:46 -0000 1.12 --- US.py 30 Dec 2002 19:43:21 -0000 1.13 *************** *** 68,72 **** def dst(self, dt): ! if dt is None or isinstance(dt, time) or dt.tzinfo is None: # An exception instead may be sensible here, in one or more of # the cases. --- 68,72 ---- def dst(self, dt): ! if dt is None or dt.tzinfo is None: # An exception instead may be sensible here, in one or more of # the cases. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.128 retrieving revision 1.129 diff -C2 -d -r1.128 -r1.129 *** datetime.py 27 Dec 2002 21:31:40 -0000 1.128 --- datetime.py 30 Dec 2002 19:43:21 -0000 1.129 *************** *** 217,224 **** return _time.strftime(newformat, timetuple) ! def _call_tzinfo_method(self, tzinfo, methname): if tzinfo is None: return None ! return getattr(tzinfo, methname)(self) # Just raise TypeError if the arg isn't None or a string. --- 217,224 ---- return _time.strftime(newformat, timetuple) ! def _call_tzinfo_method(tzinfo, methname, tzinfoarg): if tzinfo is None: return None ! return getattr(tzinfo, methname)(tzinfoarg) # Just raise TypeError if the arg isn't None or a string. *************** *** 1129,1133 **** """Return the timezone offset in minutes east of UTC (negative west of UTC).""" ! offset = _call_tzinfo_method(self, self._tzinfo, "utcoffset") offset = _check_utc_offset("utcoffset", offset) if offset is not None: --- 1129,1133 ---- """Return the timezone offset in minutes east of UTC (negative west of UTC).""" ! offset = _call_tzinfo_method(self._tzinfo, "utcoffset", None) offset = _check_utc_offset("utcoffset", offset) if offset is not None: *************** *** 1137,1141 **** # 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 --- 1137,1141 ---- # Return an integer (or None) instead of a timedelta (or None). def _utcoffset(self): ! offset = _call_tzinfo_method(self._tzinfo, "utcoffset", None) offset = _check_utc_offset("utcoffset", offset) return offset *************** *** 1148,1152 **** "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies. """ ! name = _call_tzinfo_method(self, self._tzinfo, "tzname") _check_tzname(name) return name --- 1148,1152 ---- "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies. """ ! name = _call_tzinfo_method(self._tzinfo, "tzname", None) _check_tzname(name) return name *************** *** 1161,1165 **** info. """ ! offset = _call_tzinfo_method(self, self._tzinfo, "dst") offset = _check_utc_offset("dst", offset) if offset is not None: --- 1161,1165 ---- info. """ ! offset = _call_tzinfo_method(self._tzinfo, "dst", None) offset = _check_utc_offset("dst", offset) if offset is not None: *************** *** 1186,1190 **** # 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 --- 1186,1190 ---- # Return an integer (or None) instead of a timedelta (or None). def _dst(self): ! offset = _call_tzinfo_method(self._tzinfo, "dst", None) offset = _check_utc_offset("dst", offset) return offset *************** *** 1650,1654 **** """Return the timezone offset in minutes east of UTC (negative west of UTC).""" ! offset = _call_tzinfo_method(self, self._tzinfo, "utcoffset") offset = _check_utc_offset("utcoffset", offset) if offset is not None: --- 1650,1654 ---- """Return the timezone offset in minutes east of UTC (negative west of UTC).""" ! offset = _call_tzinfo_method(self._tzinfo, "utcoffset", self) offset = _check_utc_offset("utcoffset", offset) if offset is not None: *************** *** 1658,1662 **** # 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 --- 1658,1662 ---- # Return an integer (or None) instead of a timedelta (or None). def _utcoffset(self): ! offset = _call_tzinfo_method(self._tzinfo, "utcoffset", self) offset = _check_utc_offset("utcoffset", offset) return offset *************** *** 1669,1673 **** "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies. """ ! name = _call_tzinfo_method(self, self._tzinfo, "tzname") _check_tzname(name) return name --- 1669,1673 ---- "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies. """ ! name = _call_tzinfo_method(self._tzinfo, "tzname", self) _check_tzname(name) return name *************** *** 1682,1686 **** info. """ ! offset = _call_tzinfo_method(self, self._tzinfo, "dst") offset = _check_utc_offset("dst", offset) if offset is not None: --- 1682,1686 ---- info. """ ! offset = _call_tzinfo_method(self._tzinfo, "dst", self) offset = _check_utc_offset("dst", offset) if offset is not None: *************** *** 1690,1694 **** # 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 --- 1690,1694 ---- # Return an integer (or None) instead of a timedelta (or None).1573 def _dst(self): ! offset = _call_tzinfo_method(self._tzinfo, "dst", self) offset = _check_utc_offset("dst", offset) return offset Index: doc.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/doc.txt,v retrieving revision 1.74 retrieving revision 1.75 diff -C2 -d -r1.74 -r1.75 *** doc.txt 27 Dec 2002 21:31:40 -0000 1.74 --- doc.txt 30 Dec 2002 19:43:21 -0000 1.75 *************** *** 760,764 **** 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 not supply any concrete subclasses of tzinfo. --- 760,764 ---- 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 not supply any concrete subclasses of tzinfo. *************** *** 777,786 **** 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. ! - utcoffset(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 --- 777,783 ---- 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. ! - 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 *************** *** 791,797 **** 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 by dt, as a string. Nothing about string names is defined by the --- 788,798 ---- 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: ! 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 *************** *** 804,808 **** of dt passed, especially if the tzinfo class is accounting for DST. ! - 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. --- 805,809 ---- of dt passed, especially if the tzinfo class is accounting for DST. ! - 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. *************** *** 815,818 **** --- 816,840 ---- 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: Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.87 retrieving revision 1.88 diff -C2 -d -r1.87 -r1.88 *** test_datetime.py 30 Dec 2002 17:36:58 -0000 1.87 --- test_datetime.py 30 Dec 2002 19:43:21 -0000 1.88 *************** *** 1570,1573 **** --- 1570,1590 ---- class TZInfoBase(unittest.TestCase): + def test_argument_passing(self): + cls = self.theclass + # A datetimetz passes itself on, a timetz passes None. + 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 + + obj = cls(1, 2, 3, tzinfo=introspective()) + + expected = cls is timetz and "none" or "real" + self.assertEqual(obj.tzname(), expected) + + expected = timedelta(minutes=(cls is timetz and -42 or 42)) + self.assertEqual(obj.utcoffset(), expected) + self.assertEqual(obj.dst(), expected) + def test_bad_tzinfo_classes(self): cls = self.theclass *************** *** 1690,1709 **** # However, if they're different members, uctoffset is not ignored. ! d0 = base.replace(minute=3, tzinfo=OperandDependentOffset()) ! d1 = base.replace(minute=9, tzinfo=OperandDependentOffset()) ! d2 = base.replace(minute=11, tzinfo=OperandDependentOffset()) ! for x in d0, d1, d2: ! for y in d0, d1, d2: ! got = cmp(x, y) ! if (x is d0 or x is d1) and (y is d0 or y is d1): ! expected = 0 ! elif x is y is d2: ! expected = 0 ! elif x is d2: ! expected = -1 ! else: ! assert y is d2 ! expected = 1 ! self.assertEqual(got, expected) --- 1707,1730 ---- # However, if they're different members, uctoffset is not ignored. ! # Note that a timetz can't actually have an operand-depedent offset, ! # though (and timetz.utcoffset() passes None to tzinfo.utcoffset()), ! # so skip this test for timetz. ! if cls is not timetz: ! d0 = base.replace(minute=3, tzinfo=OperandDependentOffset()) ! d1 = base.replace(minute=9, tzinfo=OperandDependentOffset()) ! d2 = base.replace(minute=11, tzinfo=OperandDependentOffset()) ! for x in d0, d1, d2: ! for y in d0, d1, d2: ! got = cmp(x, y) ! if (x is d0 or x is d1) and (y is d0 or y is d1): ! expected = 0 ! elif x is y is d2: ! expected = 0 ! elif x is d2: ! expected = -1 ! else: ! assert y is d2 ! expected = 1 ! self.assertEqual(got, expected) *************** *** 2550,2554 **** def dst(self, dt): ! if dt is None or isinstance(dt, time) or dt.tzinfo is None: # An exception instead may be sensible here, in one or more of # the cases. --- 2571,2575 ---- def dst(self, dt): ! if dt is None or dt.tzinfo is None: # An exception instead may be sensible here, in one or more of # the cases.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4