Reputation: 95
Python methods to convert ISO 8601 time format to UNIX timestamp (epoch) and back again without losing fractional seconds?
I found several examples, but all the examples seem to drop the fractional seconds at some point in the conversion. Example below...
The issue seems to be the initial conversion to UNIX timestamp (epoch). Code below.
def ISO8601ToEpoch(theString):
from datetime import datetime
import calendar
return calendar.timegm(datetime.strptime(theString, "%Y-%m-%dT%H:%M:%S.%f").timetuple())
def EpochToISO8601(theEpoch):
from datetime import datetime
return datetime.fromtimestamp(theEpoch).isoformat()
#
print 'Original Time {0}'.format('2018-04-27T04:19:51.050937')
theTime=ISO8601ToEpoch('2018-04-27T04:19:51.050937')
print 'Time {0}'.format(theTime)
print 'Original Time {0}'.format(EpochToISO8601(theTime)
This results as...
Original Time 2018-04-27T04:19:51.050937 Time 1524802791 Original Time 2018-04-27T04:19:51
Is there a way to get timetuple to not hack the fractional seconds?
Upvotes: 1
Views: 7049
Reputation: 95
I think this is correct... but if not I am sure someone will point out what I missed.
>>> import datetime as datetime
>>> import dateutil.parser
>>> import time
# Create a sample UNIX timestamp...
>>> t=time.time()
>>> t
1478266530.573583
# Convert the time stamp sample to ISO format...
>>> i=datetime.datetime.utcfromtimestamp(t).isoformat()
>>> i
'2016-11-04T13:35:30.573583'
# Convert ISO format to UNIX time stamp...
>>> d=dateutil.parser.parse(i)
>>> d
datetime.datetime(2016, 11, 4, 13, 35, 30, 573583)
>>> s=(time.mktime(d.timetuple())*1e3+d.microsecond/1e3)/1e3
>>> s
1478266530.5735831
It is not a perfect conversion given the number of fractional digits of the resulting timestamp but close enough for my need. I am sure the ISO format is a point of debate, but the format matches the typical format I expect to encounter, this is of course the lack of the 'Z' qualifier.
Upvotes: 1
Reputation: 366083
The problem here is that you're converting a datetime
—which understands microseconds—into a timetuple
—which doesn't.1
The obvious fix is just to not do that.
If you want to convert a datetime
object to a timestamp, just use the timestamp
method, the same way you already use the fromtimestamp
classmethod to go the other way.
1. You might be able to trick a timetuple
into holding a float
instead of an int
for seconds. But then you'd be breaking the invariants of the type. And, more importantly, defeating the entire purpose of the type, which is to be identical to a 1980s-style C struct tm
. And likely also breaking the timegm
function, which probably just calls the C function of the same name. (Most of the time
module is a thin wrapper around C's <time.h>
, as opposed to datetime
, which is a friendly module designed for Python.) And then timegm
is documented to return an integral type, so even if you got that far, it would all be for nothing.
Upvotes: 2