timeutil.datetime_to_timestamp: new function
authorMarko Kreen <markokr@gmail.com>
Sat, 23 Mar 2013 12:13:51 +0000 (14:13 +0200)
committerMarko Kreen <markokr@gmail.com>
Sat, 23 Mar 2013 12:13:51 +0000 (14:13 +0200)
converts datetime() to posix timestamp.

python/skytools/__init__.py
python/skytools/timeutil.py

index 048d41fbf33847e7325b724432a502a136c59f54..db5b2ba185e4f99605971e025097c407fdc63fe8 100644 (file)
@@ -135,6 +135,7 @@ _symbols = {
     'mk_update_sql': 'skytools.sqltools:mk_update_sql',
     # skytools.timeutil
     'FixedOffsetTimezone': 'skytools.timeutil:FixedOffsetTimezone',
+    'datetime_to_timestamp': 'skytools.timeutil:datetime_to_timestamp',
     'parse_iso_timestamp': 'skytools.timeutil:parse_iso_timestamp',
     # skytools.utf8
     'safe_utf8_decode': 'skytools.utf8:safe_utf8_decode',
index b6728bf27fe3b02a1c51eeef32c286dcb5720663..a29e050cbf5ba3977b5a05d937271728257d13b3 100644 (file)
@@ -1,23 +1,20 @@
 
-"""Module for parsing ISO 8601 format timestamps.
+"""Fill gaps in Python time API-s.
 
-Only fixed offset timezones are supported.
+parse_iso_timestamp:
+    Parse reasonable subset of ISO_8601 timestamp formats.
+    [ http://en.wikipedia.org/wiki/ISO_8601 ]
+
+datetime_to_timestamp:
+    Get POSIX timestamp from datetime() object.
 
-http://en.wikipedia.org/wiki/ISO_8601
 """
 
 import re
-
+import time
 from datetime import datetime, timedelta, tzinfo
 
-"""
-TODO:
-- support more combinations from ISO 8601 (only reasonable ones)
-- cache TZ objects
-- make it faster?
-"""
-
-__all__ = ['parse_iso_timestamp', 'FixedOffsetTimezone']
+__all__ = ['parse_iso_timestamp', 'FixedOffsetTimezone', 'datetime_to_timestamp']
 
 class FixedOffsetTimezone(tzinfo):
     """Fixed offset in minutes east from UTC."""
@@ -46,6 +43,17 @@ class FixedOffsetTimezone(tzinfo):
 
 ZERO = timedelta(0)
 
+#
+# Parse ISO_8601 timestamps.
+#
+
+"""
+TODO:
+- support more combinations from ISO 8601 (only reasonable ones)
+- cache TZ objects
+- make it faster?
+"""
+
 _iso_regex = r"""
     \s*
     (?P<year> \d\d\d\d) [-] (?P<month> \d\d) [-] (?P<day> \d\d) [ T]
@@ -67,6 +75,8 @@ def parse_iso_timestamp(s, default_tz = None):
     If the timezone offset is not present, use default_tz as tzinfo.
     By default its None, meaning the datetime object will be without tz.
 
+    Only fixed offset timezones are supported.
+
     >>> str(parse_iso_timestamp('2005-06-01 15:00'))
     '2005-06-01 15:00:00'
     >>> str(parse_iso_timestamp(' 2005-06-01T15:00 +02 '))
@@ -108,6 +118,47 @@ def parse_iso_timestamp(s, default_tz = None):
                 m.group('ss') and int(m.group('ss').ljust(6, '0')) or 0,
                 tz)
 
+#
+# POSIX timestamp from datetime()
+#
+
+UTC = FixedOffsetTimezone(0)
+TZ_EPOCH = datetime.fromtimestamp(0, UTC)
+UTC_NOTZ_EPOCH = datetime.utcfromtimestamp(0)
+
+def datetime_to_timestamp(dt, local_time=True):
+    """Get posix timestamp from datetime() object.
+
+    if dt is without timezone, then local_time specifies
+    whether it's UTC or local time.
+
+    Returns seconds since epoch as float.
+
+    >>> datetime_to_timestamp(parse_iso_timestamp("2005-06-01 15:00:59.33 +02"))
+    1117630859.33
+    >>> datetime_to_timestamp(datetime.fromtimestamp(1117630859.33, UTC))
+    1117630859.33
+    >>> datetime_to_timestamp(datetime.fromtimestamp(1117630859.33))
+    1117630859.33
+    >>> now = datetime.utcnow()
+    >>> now2 = datetime.utcfromtimestamp(datetime_to_timestamp(now, False))
+    >>> now == now2
+    True
+    >>> now = datetime.now()
+    >>> now2 = datetime.fromtimestamp(datetime_to_timestamp(now))
+    >>> now == now2
+    True
+    """
+    if dt.tzinfo:
+        delta = dt - TZ_EPOCH
+        return delta.total_seconds()
+    elif local_time:
+        s = time.mktime(dt.timetuple())
+        return s + (dt.microsecond / 1000000.0)
+    else:
+        delta = dt - UTC_NOTZ_EPOCH
+        return delta.total_seconds()
+
 if __name__ == '__main__':
     import doctest
     doctest.testmod()