[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