[Checkins] SVN: DateTime/trunk/ Reordered some calculations in `_calcIndependentSecondEtc` to preserve more floating point precision. Optimized the pickled data, by only storing a tuple of `_micros` and time zone information - this reduces the pickle size from an average of 300 bytes to just 60 bytes.

Hanno Schlichting hannosch at hannosch.eu
Fri May 6 14:02:15 EDT 2011


Log message for revision 121562:
  Reordered some calculations in `_calcIndependentSecondEtc` to preserve more floating point precision. Optimized the pickled data, by only storing a tuple of `_micros` and time zone information - this reduces the pickle size from an average of 300 bytes to just 60 bytes.
  

Changed:
  U   DateTime/trunk/CHANGES.txt
  U   DateTime/trunk/src/DateTime/DateTime.py
  U   DateTime/trunk/src/DateTime/tests/testDateTime.py

-=-
Modified: DateTime/trunk/CHANGES.txt
===================================================================
--- DateTime/trunk/CHANGES.txt	2011-05-06 18:01:13 UTC (rev 121561)
+++ DateTime/trunk/CHANGES.txt	2011-05-06 18:02:15 UTC (rev 121562)
@@ -4,6 +4,13 @@
 2.13.0 (unreleased)
 -------------------
 
+- Reordered some calculations in `_calcIndependentSecondEtc` to preserve more
+  floating point precision.
+
+- Optimized the pickled data, by only storing a tuple of `_micros` and time
+  zone information - this reduces the pickle size from an average of 300 bytes
+  to just 60 bytes.
+
 - Optimized un-pickling, by avoiding the creation of an intermediate DateTime
   value representing the current time.
 

Modified: DateTime/trunk/src/DateTime/DateTime.py
===================================================================
--- DateTime/trunk/src/DateTime/DateTime.py	2011-05-06 18:01:13 UTC (rev 121561)
+++ DateTime/trunk/src/DateTime/DateTime.py	2011-05-06 18:02:15 UTC (rev 121562)
@@ -161,9 +161,8 @@
     # nearTime is now within an hour of being correct.
     # Recalculate t according to DST.
     fset = long(_tzoffset(tz, nearTime))
-    x_adjusted = x - fset + ms
-    d = x_adjusted / 86400.0
-    t = x_adjusted - long(EPOCH) + 86400L
+    d = (x - fset) / 86400.0 + (ms / 86400.0)
+    t = x - fset - long(EPOCH) + 86400L + ms
     micros = (x + 86400 - fset) * 1000000 + \
              long(round(ms * 1000000.0)) - long(EPOCH * 1000000.0)
     s = d - math.floor(d)
@@ -349,9 +348,22 @@
         except Exception:
             raise SyntaxError('Unable to parse %s, %s' % (args, kw))
 
-    def __getinitargs__(self):
-        return (None, )
+    def __getstate__(self):
+        state = self.__dict__
+        return (state['_micros'] / 1000000.0,
+            state.get('_timezone_naive', False),
+            state['_tz'])
 
+    def __setstate__(self, value):
+        state = self.__dict__
+        if isinstance(value, tuple):
+            self._parse_args(value[0], value[2])
+            state['_micros'] = long(value[0] * 1000000)
+            state['_timezone_naive'] = value[1]
+        else:
+            state.clear()
+            state.update(value)
+
     def _parse_args(self, *args, **kw):
         """Return a new date-time object.
 

Modified: DateTime/trunk/src/DateTime/tests/testDateTime.py
===================================================================
--- DateTime/trunk/src/DateTime/tests/testDateTime.py	2011-05-06 18:01:13 UTC (rev 121561)
+++ DateTime/trunk/src/DateTime/tests/testDateTime.py	2011-05-06 18:02:15 UTC (rev 121562)
@@ -12,6 +12,7 @@
 #
 ##############################################################################
 
+import cPickle
 import math
 import os
 import time
@@ -55,18 +56,15 @@
 
 class DateTimeTests(unittest.TestCase):
 
-    def _compare(self, dt1, dt2, ms=1):
+    def _compare(self, dt1, dt2):
         '''Compares the internal representation of dt1 with
         the representation in dt2.  Allows sub-millisecond variations.
         Primarily for testing.'''
-        if ms:
-            self.assertEqual(dt1.millis(), dt2.millis())
-        self.assertEqual(math.floor(dt1._t * 1000.0),
-                         math.floor(dt2._t * 1000.0))
-        self.assertEqual(math.floor(dt1._d * 86400000.0),
-                         math.floor(dt2._d * 86400000.0))
-        self.assertEqual(math.floor(dt1.time * 86400000.0),
-                         math.floor(dt2.time * 86400000.0))
+        self.assertEqual(round(dt1._t, 3), round(dt2._t, 3))
+        self.assertEqual(round(dt1._d, 9), round(dt2._d, 9))
+        self.assertEqual(round(dt1.time, 9), round(dt2.time, 9))
+        self.assertEqual(dt1.millis(), dt2.millis())
+        self.assertEqual(dt1._micros, dt2._micros)
 
     def testBug1203(self):
         # 01:59:60 occurred in old DateTime
@@ -201,17 +199,40 @@
         self.failUnless(not dt.equalTo(dt1))
 
     def test_pickle(self):
-        import cPickle
         dt = DateTime()
         data = cPickle.dumps(dt, 1)
         new = cPickle.loads(data)
         self.assertEqual(dt.__dict__, new.__dict__)
 
-        dt = DateTime('2002/5/2 8:00am GMT+0')
+    def test_pickle_with_tz(self):
+        dt = DateTime('2002/5/2 8:00am GMT+8')
         data = cPickle.dumps(dt, 1)
         new = cPickle.loads(data)
         self.assertEqual(dt.__dict__, new.__dict__)
 
+    def test_pickle_with_micros(self):
+        dt = DateTime('2002/5/2 8:00:14.123 GMT+8')
+        data = cPickle.dumps(dt, 1)
+        new = cPickle.loads(data)
+        self.assertEqual(dt.__dict__, new.__dict__)
+
+    def test_pickle_old(self):
+        dt = DateTime('2002/5/2 8:00am GMT+0')
+        data = ('(cDateTime.DateTime\nDateTime\nq\x01Noq\x02}q\x03(U\x05_amonq'
+            '\x04U\x03Mayq\x05U\x05_adayq\x06U\x03Thuq\x07U\x05_pmonq\x08h'
+            '\x05U\x05_hourq\tK\x08U\x05_fmonq\nh\x05U\x05_pdayq\x0bU\x04T'
+            'hu.q\x0cU\x05_fdayq\rU\x08Thursdayq\x0eU\x03_pmq\x0fU\x02amq'
+            '\x10U\x02_tq\x11GA\xcehy\x00\x00\x00\x00U\x07_minuteq\x12K\x00U'
+            '\x07_microsq\x13L1020326400000000L\nU\x02_dq\x14G@\xe2\x12j\xaa'
+            '\xaa\xaa\xabU\x07_secondq\x15G\x00\x00\x00\x00\x00\x00\x00\x00U'
+            '\x03_tzq\x16U\x05GMT+0q\x17U\x06_monthq\x18K\x05U'
+            '\x0f_timezone_naiveq\x19I00\nU\x04_dayq\x1aK\x02U\x05_yearq'
+            '\x1bM\xd2\x07U\x08_nearsecq\x1cG\x00\x00\x00\x00\x00\x00\x00'
+            '\x00U\x07_pmhourq\x1dK\x08U\n_dayoffsetq\x1eK\x04U\x04timeq'
+            '\x1fG?\xd5UUUV\x00\x00ub.')
+        new = cPickle.loads(data)
+        self.assertEqual(dt.__dict__, new.__dict__)
+
     def testTZ2(self):
         # Time zone manipulation test 2
         dt = DateTime()



More information about the checkins mailing list