I have the following string:
mytime = "2009-03-08T00:27:31.807Z"
How do I convert it to epoch in python?
I tried:
import time
p = '%Y-%m-%dT%H:%M:%S'
int(time.mktime(time.strptime(s, p)))
But it does not work with the 31.807Z.
There are two parts:
#!/usr/bin/env python
from datetime import datetime
utc_time = datetime.strptime("2009-03-08T00:27:31.807Z", "%Y-%m-%dT%H:%M:%S.%fZ")
epoch_time = (utc_time - datetime(1970, 1, 1)).total_seconds()
# -> 1236472051.807
If you are sure that you want to ignore fractions of a second and to get an integer result:
#!/usr/bin/env python
import time
from calendar import timegm
utc_time = time.strptime("2009-03-08T00:27:31.807Z", "%Y-%m-%dT%H:%M:%S.%fZ")
epoch_time = timegm(utc_time)
# -> 1236472051
To support timestamps that correspond to a leap second such as Wed July 1 2:59:60 MSK 2015, you could use a combination of time.strptime() and datetime (if you care about leap seconds you should take into account the microseconds too).
Z is the only allowed letter tools.ietf.org/html/rfc3339#section-5.6dateutil has recently been added back to python packages, it's an easy one liner that handles formatting on its own.
from dateutil import parser
strtime = '2009-03-08T00:27:31.807Z'
epoch = parser.parse(strtime).timestamp()
You are missing .%fZ from your format string.
p = '%Y-%m-%dT%H:%M:%S.%fZ'
The correct way to convert to epoch is to use datetime:
from datetime import datetime
p = '%Y-%m-%dT%H:%M:%S.%fZ'
mytime = "2009-03-08T00:27:31.807Z"
epoch = datetime(1970, 1, 1)
print((datetime.strptime(mytime, p) - epoch).total_seconds())
Or call int if you want to ignore fractions.
Z, I suppose you could always ignore Z and rstrip("Z")time.mktime() on UTC time!mktime(). "OP uses broken code in the question" is not a valid excuse for putting it in your answer. Personally, I add something like #XXX WRONG, DON'T USE at the top of a code fragment if I have to include the broken code. It is not enough to put a valid answer somewhere at the bottom.dateutil is the only library i have found that correctly deals with the timezone offset identitifier (Z)
pip install python-dateutil
then
from dateutil.parser import parse as date_parse
print date_parse("2009-03-08T00:27:31.807Z")
#get timestamp
import calendar
dt = date_parse("2009-03-08T00:27:31.807Z")
timestamp1 = calendar.timegm(dt.timetuple())
dateutil may accept too much.dateutil for that. You can parse the time string using only stdlib in both Python 2 and 3. timegm() is ok if you don't care about fractions of a second.Code:
import datetime
epoch = datetime.datetime(1970, 1, 1)
mytime = "2009-03-08T00:27:31.807Z"
myformat = "%Y-%m-%dT%H:%M:%S.%fZ"
mydt = datetime.datetime.strptime(mytime, myformat)
val = (mydt - epoch).total_seconds()
print(val)
> 1236472051.81
repr(val)
> '1236472051.807'
Notes:
time.strptime(), the returned time.struct_time does not support sub-second precision.%f format is for microseconds. When parsing it need not be the full 6 digits.This code works in Python 3.6 to convert a datetime string to epoch in UTC or local timezone.
from datetime import datetime, timedelta
from dateutil.tz import tzutc, tzlocal
mydate = '2020-09-25'
mytime = '06:00:00'
epoch1970 = datetime(1970, 1, 1, 0, 0, 0, tzinfo=tzutc())
myepochutc = int((datetime.strptime(mydate + ' ' + mytime, "%Y-%m-%d %H:%M:%S").replace(tzinfo=tzutc()) - epoch1970).total_seconds()*1000)
myepochlocal = int((datetime.strptime(mydate + ' ' + mytime, "%Y-%m-%d %H:%M:%S").replace(tzinfo=tzlocal()) - epoch1970).total_seconds()*1000)
#epoch will be in milliseconds
print(myepochutc) #if mydate/mytime was in utc
print(myepochlocal) #if mydate/mytime was in local timezone
Python 3.7+ The string format in question can be parsed by strptime:
from datetime import datetime
datetime.strptime("2009-03-08T00:27:31.807Z", '%Y-%m-%dT%H:%M:%S.%f%z')
>>> datetime.datetime(2009, 3, 8, 0, 27, 31, 807000, tzinfo=datetime.timezone.utc)
Another option using the built-in datetime.fromisoformat(): As mentioned in this thread linked by @jfs, fromisoformat() doesn't parse the 'Z' character to UTC although this is part of the RFC3339 definitions. A little work-around can make it work - some will consider this nasty but it's efficient after all.
from datetime import datetime
mytime = "2009-03-08T00:27:31.807Z"
datetime.fromisoformat(mytime.replace("Z", "+00:00")).timestamp()
>>> 1236472051.807
.807Z? %S shows as a decimal number