[Zope3-checkins] SVN: Zope3/trunk/src/pytz/ Make utc picklable and
efficiently unpicklable. Docs and tests. Stuart
Gary Poster
gary at zope.com
Tue Mar 1 10:49:14 EST 2005
Log message for revision 29360:
Make utc picklable and efficiently unpicklable. Docs and tests. Stuart
plans to move changes into sourceforge.
Changed:
U Zope3/trunk/src/pytz/README.txt
U Zope3/trunk/src/pytz/__init__.py
U Zope3/trunk/src/pytz/reference.py
U Zope3/trunk/src/pytz/tests.py
U Zope3/trunk/src/pytz/zoneinfo/UTC.py
-=-
Modified: Zope3/trunk/src/pytz/README.txt
===================================================================
--- Zope3/trunk/src/pytz/README.txt 2005-03-01 15:45:04 UTC (rev 29359)
+++ Zope3/trunk/src/pytz/README.txt 2005-03-01 15:49:14 UTC (rev 29360)
@@ -105,11 +105,40 @@
As you can see, the system has chosen one for you and there is a 50%
chance of it being out by one hour. For some applications, this does
not matter. However, if you are trying to schedule meetings with people
-in different timezones or analyze log files it is not acceptable. The
-best and simplest solution is to stick with using UTC. If you insist
-on working with local times, this library provides a facility for
-constructing them almost unambiguously
+in different timezones or analyze log files it is not acceptable.
+The best and simplest solution is to stick with using UTC. The pytz package
+encourages using UTC for internal timezone representation by including a
+special UTC implementation based on the standard Python reference
+implementation in the Python documentation. This timezone unpickles to be
+the same instance, and pickles to a relatively small size. The UTC
+implementation can be obtained as pytz.utc, pytz.UTC, or
+pytz.timezone('UTC'). Note that this instance is not the same
+instance (or implementation) as other timezones with the same meaning
+(GMT, Greenwich, Universal, etc.).
+
+>>> import pickle, pytz
+>>> dt = datetime(2005, 3, 1, 14, 13, 21, tzinfo=utc)
+>>> naive = dt.replace(tzinfo=None)
+>>> p = pickle.dumps(dt, 1)
+>>> naive_p = pickle.dumps(naive, 1)
+>>> len(p), len(naive_p), len(p) - len(naive_p)
+(60, 43, 17)
+>>> new = pickle.loads(p)
+>>> new == dt
+True
+>>> new is dt
+False
+>>> new.tzinfo is dt.tzinfo
+True
+>>> pytz.utc is pytz.UTC is pytz.timezone('UTC')
+True
+>>> utc is pytz.timezone('GMT')
+False
+
+If you insist on working with local times, this library provides a
+facility for constructing them almost unambiguously.
+
>>> loc_dt = datetime(2002, 10, 27, 1, 30, 00)
>>> est_dt = eastern.localize(loc_dt, is_dst=True)
>>> edt_dt = eastern.localize(loc_dt, is_dst=False)
@@ -125,7 +154,7 @@
that cannot be specified without referring to the timezone abbreviation
or the actual UTC offset.
-The 'Standard' Python way of handling all thee ambiguities is not to,
+The 'Standard' Python way of handling all these ambiguities is not to,
such as demonstrated in this example using the US/Eastern timezone
definition from the Python documentation:
Modified: Zope3/trunk/src/pytz/__init__.py
===================================================================
--- Zope3/trunk/src/pytz/__init__.py 2005-03-01 15:45:04 UTC (rev 29359)
+++ Zope3/trunk/src/pytz/__init__.py 2005-03-01 15:49:14 UTC (rev 29360)
@@ -21,12 +21,71 @@
OLSEN_VERSION = OLSON_VERSION # Old releases had this misspelling
-__all__ = ['timezone', 'all_timezones', 'common_timezones']
+__all__ = ['timezone', 'all_timezones', 'common_timezones', 'utc']
-import sys
+import sys, datetime
from tzinfo import AmbiguousTimeError
+ZERO = datetime.timedelta(0)
+HOUR = datetime.timedelta(hours=1)
+
+# A UTC class.
+
+class UTC(datetime.tzinfo):
+ """UTC
+
+ Identical to the reference UTC implementation given in Python docs except
+ that it unpickles using the single module global instance defined beneath
+ this class declaration.
+ """
+
+ def utcoffset(self, dt):
+ return ZERO
+
+ def tzname(self, dt):
+ return "UTC"
+
+ def dst(self, dt):
+ return ZERO
+
+ def __reduce__(self):
+ return _UTC, ()
+
+UTC = utc = UTC()
+
+def _UTC():
+ """Factory function for utc unpickling.
+
+ Makes sure that unpickling a utc instance always returns the same
+ module global.
+
+ These examples belong in the UTC class above, but it is obscured; or in
+ the README.txt, but we are not depending on Python 2.4 so integrating
+ the README.txt examples with the unit tests is not trivial.
+
+ >>> import datetime, pickle
+ >>> dt = datetime.datetime(2005, 3, 1, 14, 13, 21, tzinfo=utc)
+ >>> naive = dt.replace(tzinfo=None)
+ >>> p = pickle.dumps(dt, 1)
+ >>> naive_p = pickle.dumps(naive, 1)
+ >>> len(p), len(naive_p), len(p) - len(naive_p)
+ (60, 43, 17)
+ >>> new = pickle.loads(p)
+ >>> new == dt
+ True
+ >>> new is dt
+ False
+ >>> new.tzinfo is dt.tzinfo
+ True
+ >>> utc is UTC is timezone('UTC')
+ True
+ >>> utc is timezone('GMT')
+ False
+ """
+ return utc
+_UTC.__safe_for_unpickling__ = True
+
def timezone(zone):
''' Return a datetime.tzinfo implementation for the given timezone
Modified: Zope3/trunk/src/pytz/reference.py
===================================================================
--- Zope3/trunk/src/pytz/reference.py 2005-03-01 15:45:04 UTC (rev 29359)
+++ Zope3/trunk/src/pytz/reference.py 2005-03-01 15:49:14 UTC (rev 29360)
@@ -10,26 +10,8 @@
__version__ = '$Revision: 1.2 $'[11:-2]
from datetime import tzinfo, timedelta, datetime
+from pytz import utc, UTC, HOUR, ZERO
-ZERO = timedelta(0)
-HOUR = timedelta(hours=1)
-
-# A UTC class.
-
-class UTC(tzinfo):
- """UTC"""
-
- def utcoffset(self, dt):
- return ZERO
-
- def tzname(self, dt):
- return "UTC"
-
- def dst(self, dt):
- return ZERO
-
-UTC = utc = UTC()
-
# A class building tzinfo objects for fixed-offset time zones.
# Note that FixedOffset(0, "UTC") is a different way to build a
# UTC tzinfo object.
Modified: Zope3/trunk/src/pytz/tests.py
===================================================================
--- Zope3/trunk/src/pytz/tests.py 2005-03-01 15:45:04 UTC (rev 29359)
+++ Zope3/trunk/src/pytz/tests.py 2005-03-01 15:49:14 UTC (rev 29360)
@@ -18,18 +18,22 @@
NOTIME = timedelta(0)
+# GMT is a tzinfo.StaticTzInfo--the class we primarily want to test--while
+# UTC is reference implementation. They both have the same timezone meaning.
UTC = pytz.timezone('UTC')
-REF_UTC = reference.UTC
+GMT = pytz.timezone('GMT')
class BasicTest(unittest.TestCase):
- def testUTC(self):
- now = datetime.now(tz=UTC)
+
+ def testGMT(self):
+ now = datetime.now(tz=GMT)
self.failUnless(now.utcoffset() == NOTIME)
self.failUnless(now.dst() == NOTIME)
self.failUnless(now.timetuple() == now.utctimetuple())
+ self.failUnless(now==now.replace(tzinfo=UTC))
def testReferenceUTC(self):
- now = datetime.now(tz=REF_UTC)
+ now = datetime.now(tz=UTC)
self.failUnless(now.utcoffset() == NOTIME)
self.failUnless(now.dst() == NOTIME)
self.failUnless(now.timetuple() == now.utctimetuple())
Modified: Zope3/trunk/src/pytz/zoneinfo/UTC.py
===================================================================
--- Zope3/trunk/src/pytz/zoneinfo/UTC.py 2005-03-01 15:45:04 UTC (rev 29359)
+++ Zope3/trunk/src/pytz/zoneinfo/UTC.py 2005-03-01 15:49:14 UTC (rev 29360)
@@ -1,12 +1,3 @@
'''tzinfo timezone information for UTC.'''
-from pytz.tzinfo import StaticTzInfo
-from pytz.tzinfo import memorized_timedelta as timedelta
+from pytz import UTC
-class UTC(StaticTzInfo):
- '''UTC timezone definition. See datetime.tzinfo for details'''
- zone = 'UTC'
- _utcoffset = timedelta(seconds=0)
- _tzname = 'UTC'
-
-UTC = UTC()
-
More information about the Zope3-Checkins
mailing list