简体   繁体   中英

Convert ISO 8601 time format to UNIX timestamp (epoch) and back again without losing fractional seconds?

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?

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM