2

After considerable effort and reading, I came up with the following two functions, one of which is (or is intended to be) the exact inverse of the other. The first takes a Python datetime object (naive) and converts it to integer seconds since the epoch; the other does the reverse:

import datetime
import time
import calendar

def datetime2timestamp(dt):
''' Accepts a naive datetime object and converts it to a time in seconds since the start of 1970'''
    return(calendar.timegm(dt.timetuple())) 

def timestamp2datetime(ts):
''' Accepts a time in seconds since the start of 1970 and converts it to a naive datetime object'''
    return(datetime.datetime.fromtimestamp(time.mktime(time.gmtime(ts))))

>>> dt = datetime.datetime(1970, 1, 1, 0, 0, 1)
>>> print dt
1970-01-01 00:00:01
>>> ts = datetime2timestamp(dt)
>>> print ts
1
>>> dt = timestamp2datetime(ts)
>>> print dt
1970-01-01 00:00:01

Two questions:

1) Is there a way to accomplish the same thing (especially the second function) more simply and without requiring the importing of three different modules? Simpler solutions I had previously found had the defect that they were inconsistent about the distinction between the local time on my computer and UTC.

2) Is there a way to have the timestamp be a float instead of the integer number of seconds returned by calendar.timegm() ?

Grant Petty
  • 1,151
  • 1
  • 13
  • 27
  • http://stackoverflow.com/questions/9744775/how-to-convert-integer-timestamp-to-python-datetime – James Mills Jul 02 '14 at 23:31
  • Have you seen [this question](http://stackoverflow.com/questions/13260863/convert-a-unixtime-to-a-datetime-object-and-back-again-pair-of-time-conversion) yet? – dano Jul 02 '14 at 23:33
  • No, I hadn't seen that question before. I don't see anything in the answers to it that give me new insight, but maybe I haven't studied it carefully enough yet. In the second function, I'm using the three nested functions so as to cancel out the problem with timezones (mktime assumes local time as does fromtimestamp). – Grant Petty Jul 02 '14 at 23:41

1 Answers1

4

1) Is there a way to accomplish the same thing (especially the second function) more simply and without requiring the importing of three different modules? Simpler solutions I had previously found had the defect that they were inconsistent about the distinction between the local time on my computer and UTC.

2) Is there a way to have the timestamp be a float instead of the integer number of seconds returned by calendar.timegm() ?

calendar.timegm() works only with UTC time. A simpler version that returns a float is just:

seconds_since_epoch = (dt - datetime(1970, 1, 1)).total_seconds()

Both won't work if dt is a local time (you could use time.mktime() + dt.microsecond / 1e6 in this case. Keep in mind, local time may be ambiguous or non-existent (e.g., due to DST transitions)). Don't forget, you can lose precision if you work with floats.

To convert back:

dt = datetime(1970, 1, 1) + timedelta(seconds=seconds_since_epoch)

The result is dt -- a naive datetime object that represents time in UTC timezone.

If you want to get local time then you could use:

local_dt = datetime.fromtimestamp(seconds_since_epoch)

The latter and time.mktime() work correctly (accept/return POSIX timestamp) if time.gmtime(0) is 1970-01-01 00:00:00+00:00 (POSIX Epoch).

jfs
  • 399,953
  • 195
  • 994
  • 1,670