I am attempting to convert the following date (2012-12-25T08:52:00-05:00) to a datetime object in python. However, I cannot figure out what the -05:00 part of the date is referencing. I am simply trying to perform the following:
datetime.datetime.strptime('2012-12-25T08:52:00-05:00','%Y-%m-%dT%H:%M:%S')
But this comes up with an expected 'ValueError: unconverted data remains'. I'm just trying to figure out what the last part of the date is used for so that I can convert that string to a proper datetime object in python.
Happy Holidays!
Your date seems to be in the ISO 8601 format, I don't think datetime handles the timezone information at the end of the string format.
You can use pip install python-dateutil, its parser can return a datetime object :
import dateutil.parser
datestr = '2012-12-25T08:52:00-05:00'
dateutil.parser.parse(datestr)
>>> datetime.datetime(2012, 12, 25, 8, 52, tzinfo=tzoffset(None, -18000))
The -05:00 indicates the timezone offset from UTC, i.e. %z would be the correct strptime argument to parse it.
If the time is UTC the offset might be indicated using Z, e.g. 2012-12-25T08:52:00Z. Not sure if %z would actually accept this...
Related
I have a two variables that i want to compare. When printed, this is what they look like:
2020-05-20 13:01:30
2020-05-20 14:49:03
However, one is a string type, and the other a datetime type.
If I want to convert the string one into date type so I can compare them, is the only way to use strptime? Because this seems a little redundant to me, since the string already has the exact format I want it to have. Basically, is there a function that does the same as strptime, but without re-formating it? As you can imagine, googling this problem is impossible, as all I'm getting is people trying to format any kind of string into datetime, so all the answers are just pointing at strptime.
If you work with Python 3.7+, for ISO 8601 compatible strings, use datetime.fromisoformat() as this is considerably more efficient than strptime or dateutil's parser. Ex:
from datetime import datetime
dtobj = datetime.fromisoformat('2020-05-20 13:01:30')
print(repr(dtobj))
# datetime.datetime(2020, 5, 20, 13, 1, 30)
You can find a benchmark vs. strptime etc. here or here.
You can use parser provided by dateutil
from dateutil import parser
date_object = parser.parse("2020-05-20 13:01:30")
print(repr(date_object))
# datetime.datetime(2020, 5, 20, 13, 1, 30)
print(type(date_object))
# <class 'datetime.datetime'>
print(date_object)
# 2020-05-20 13:01:30
From the docs:
This module offers a generic date/time string parser which is able to parse most known formats to represent a date and/or time.
Documentation: https://dateutil.readthedocs.io/en/stable/parser.html
I'm using an API that sends a date in a wierd format "YYYY-MM-DDTHH:MM:SSZ".
So the date comes out as 2018-04-27T23:59:18Z, I have never seen a date and time formatted like this. Its a string and I would like to format it as MM-DD-YYYY HH:MM:SS. I can't even wrap my head around removing the T and Z. Any help would be appreciated! Thanks in advance!
Create datetime.datetime object from your string via datetime.strptime, then turn it back into a string with its strftime method.
>>> from datetime import datetime
>>> s = "2018-04-27T23:59:18Z"
>>> datetime.strptime(s, '%Y-%m-%dT%XZ').strftime('%m-%d-%Y %X')
>>> '04-27-2018 23:59:18'
strptime and strftime behavior
(Depending on you locale you might have to use %H, %M and %S instead of %X.)
That looks like the ISO 8601 time format.
For reasons that I really don't understand, there's no standard library function that parses ISO 8601 correctly. The dateutil package that you can find on PyPI will parse it for you though.
Use this pattern:
import datetime
d = '2018-04-27T23:59:18Z'
myDate = datetime.datetime.strptime(d, '%Y-%m-%dT%H:%M:%SZ')
# datetime.datetime(2018, 4, 27, 23, 59, 18)
Then to get a datetime string use strftime:
myDate_str = myDate.strftime('%Y-%m-%d %H:%M:%S')
# '2018-04-27 23:59:18'
In a Django app of mine, I have a datetime object that I need to serialize and then deserialize. When I try it, I get the error:
ValueError: time data '2016-05-31T18:57:17.280939+00:00' does not
match format '%Y-%m-%d %H:%M:%S.%f'
My code to serialize and deserialize is:
timestring = time.isoformat() #where timestring is DateTimeField type object, instantiated in Django
timeobj = datetime.strptime(timestring, "%Y-%m-%d %H:%M:%S.%f")
What am I doing wrong and how do I get over the hump? Your guidance is greatly appreciated.
timeobj = datetime.strptime(timestring, "%Y-%m-%dT%H:%M:%S.%f+00:00")
(adds a T as the date/time separator, and hard codes the utc offset string part)
will resolve your problem ... and I guess its reasonably safe ... personally I always go with
from dateutil.parser import parse as date_parse
dt_obj = date_parse(timestring)
that pretty much always works and does not require me to hardcode the datestring you may need pip install python-dateutil
So there are two things going on here:
Your format string has a space between %d and %H but the test string has a T.
Python's datetime.datetime.strptime does not work with timezone names/offsets. From the relevant docs:
classmethod datetime.strptime(date_string, format)
Return a datetime corresponding to date_string, parsed according to
format. This is equivalent to datetime(*(time.strptime(date_string,
format)[0:6])).
So you can extract year, month, day, hour, minute, second and microsecond but the %z directive is for strftime only, not strptime.
So, in summary:
In [18]: datetime.strptime(datetime.today().isoformat(), '%Y-%m-%dT%H:%M:%S.%f')
Out[18]: datetime.datetime(2016, 5, 31, 15, 20, 20, 581261)
but
In [22]: datetime.strptime(datetime.today().isoformat()+'+00:00', '%Y-%m-%dT%H:%M:%S.%f%z')
---------------------------------------------------------------------------
ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%M:%S.%f%z'
Here is how the timestamp looks -
2015-07-17 06:01:51.066141+00:00
I'm looking around to convert this to unix date time.
datetime.strptime("2015-07-17 06:01:51.066141+00:00", "%Y-%m-%d %H:%M:%S.%f%z").strftime("%s")
ValueError: 'z' is a bad directive in format '%Y-%m-%d %H:%M:%S.%f%z'
throws error for me, probably because of wrong format being used.
PS: my virtualenv is on python 2.7
ideas please ?
python 2.7 strptime() does not support z directive, either you can use python 3.2+ or some other 3rd party library like dateutil.
For Python 2.7 use arrow:
import arrow
date_str = "2015-07-17 06:01:51.066141+00:00"
unix_time = arrow.get(date_str).timestamp
On PY3 (verified on 3.4), using only standard libs
The date string you show will not be parsed by the standard python datetime library since it has a colon in the timezone (see here). The colon can be easily removed since it's always in the same position (or use rfind to find its index starting from the right). Your simplest solution is:
import datetime
date_str = "2015-07-17 06:01:51.066141+00:00"
date_str_no_colon = date_str[:-3]+date_str[-2:] # remove last colon
dt_obj = datetime.datetime.strptime(date_str_no_colon, "%Y-%m-%d %H:%M:%S.%f%z")
unix_time = dt_obj.timestamp()
Note that arrow should still work with PY3, and is a better solution in general- you don't want to get into datetime parsing wars with python. It will win.
The way to parse the date is not right. You'll either need to parse it by hand, find another library (for example the dateutil.parser.parse method that will parse your string directly without supplying format string) that supports that format or make the timestamp in another format. Even with newer versions of python the %z directive does not accept TZ offsets in the +/-HH:MM format (with colon).
As the source of the timestamp is django.DateTimeField maybe this question can help?
For converting to unix timestamp you seem to have to do some work since there does not seem to be a direct method for that:
(t - datetime.utcfromtimestamp(0)).total_seconds()
where t is the datetime (assuming it's in UTC and there is no tzinfo) you want to convert to POSIX timestamp. If the assumption is not correct you need to put tzinfo in the zero timestamp you subtract as shown below where the assumption does not hold.
If you want to use dateutil.parser the complete solution would be:
(dateutil.parser.parse(timestamp) - datetime.utcfromtimestamp(0).replace(tzinfo=utc()).total_seconds()
strptime() has no support for timezones.
So, you can make the conversion ignoring the timezone in the following way:
datetime.strptime("2015-07-17 06:01:51.066141", "%Y-%m-%d %I:%M:%S.%f").strftime("%s")
'1437102111'
Or in order to avoid using %s, as suggested below in the commments :
from datetime import datetime
(datetime.strptime("2015-07-17 06:01:51.066141", "%Y-%m-%d %I:%M:%S.%f") - datetime(1970, 1, 1)).total_seconds()
1437112911.066141
Notice this is a working version for Python 2, you can also check solutions for other versions here
Otherwise, you will have to use other libraries (django.utils or email.utils) that support timezones, or implement the timezone parsing on your own.
P.S. :
strptime docs appear to have support for timezone, but in fact it has not been implemented. Try :
datetime.strptime("2015-07-17 06:01:51.066141+00:00", "%Y-%m-%d %I:%M:%S.%f%z").strftime("%s")
and you will see that it is not supported. You can also verify it by searching more about strptime()
There are two parts:
to convert "2015-07-17 06:01:51.066141+00:00" into a datetime object that represents UTC time, see Convert timestamps with offset to datetime obj using strptime. Or If you know that the utc offset is always +0000:
from datetime import datetime
utc_time = datetime.strptime(time_string, "%Y-%m-%d %H:%M:%S.%f+00:00")
to convert the UTC time to POSIX timestamp (unix time), see Converting datetime.date to UTC timestamp in Python:
from datetime import datetime
timestamp = (utc_time - datetime(1970, 1, 1)).total_seconds()
I have to deal in python with strings representing iso8601 timestamps.
My timestamps string are therefore in the following form:
timestamp = "2011-08-18T10:29:47+03:00"
Currently I'm converting them in python using:
timestamp = timestamp[:-6]
timestamp = datetime.datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S")
But in this way I lose all the information about the time zone.
I have seen many examples here on s-o about timestamps and python, unfortunately no one was preserving the timezone as well, or just recover the time zone delay using:
delay = timestamp[-6:]
I have also tried:
timestamp = "2011-08-18T10:29:47+03:00"
timestamp = datetime.datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S%z")
but it returned
ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%M:%S%z'
Can you give some insight?
The python iso8601 module is built with a wonderful parse_date method that can handle timezone info :
>>> import iso8601
>>> iso8601.parse_date("2007-01-25T12:00:00Z")
datetime.datetime(2007, 1, 25, 12, 0, tzinfo=<iso8601.iso8601.Utc ...>)
>>> iso8601.parse_date("2011-08-18T10:29:47+03:00")
datetime.datetime(2011, 8, 18, 10, 29, 47, tzinfo=<FixedOffset '+03:00'>)
If you want to convert it in another timezone, use the astimezone(tz) method
If you need to get the UTC datetime you can use the utctimetuple() method.
You'll need to add an external module that provides timezone support; the pytz module provides you with the necessary timezone database.
You'll either need to parse the timezone by hand to construct a pytz timezone, or use a package like zc.iso8601 or iso8601 to do the parsing for you:
from zc.iso8601.parse import datetimetz
datetimetz(timestamp)