Converting a readable date & time string to a datetime object in Python - python

I am trying to convert a date and time string such as "Mar 15, 2016 10:47:15" into a Python datetime object using strptime. I believe I have the formatting correct however I still get a ValueError exception when I run the below:
>>> s = "Mar 15, 2016 10:47:15"
>>> datetime.datetime.strptime(s,"%b %m, %Y %H:%M:%S")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/_strptime.py", line 325, in _strptime
(data_string, format))
ValueError: time data 'Mar 15, 2016 10:47:15' does not match format '%b %m, %Y %H:%M:%S'
Any ideas as to what may be wrong with my format string?

The second item in the format string (%m) refers to month. Changing it to %d will make your code work.
datetime.datetime.strptime(s,"%b %d, %Y %H:%M:%S")
Here are the relevant parts from strptime documentation:
%d Day of the month as a zero-padded decimal number. 01, 02, ..., 31
%m Month as a zero-padded decimal number. 01, 02, ..., 12

Month name is locale-specific. If you want to use english months names set for application English-based locale like en_US.
$ env LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 python
>>> import datetime
>>> s = "Mar 15, 2016 10:47:15"
>>> datetime.datetime.strptime(s,"%b %d, %Y %H:%M:%S")
datetime.datetime(2016, 3, 15, 10, 47, 15)
P.S. %m replaced with %d, which means day.

Related

How to convert a string into date-format in python?

I have a string like 23 July 1914 and want to convert it to 23/07/1914 date format.
But my code gives error.
from datetime import datetime
datetime_object = datetime.strptime('1 June 2005','%d %m %Y')
print datetime_object
Your error is in the format you are using to strip your string. You use %m as the format specifier for month, but this expects a 0 padded integer representing the month of the year (e.g. 06 for your example). What you want to use is %B, which expects an month of the year written out fully (e.g. June in your example).
For a full explanation of the datetime format specifiers please consult the documentation, and if you have any other issues please check there first.
Here is what you should be doing:
from datetime import datetime
datetime_object = datetime.strptime('1 June 2005','%d %B %Y')
s = datetime_object.strftime("%d/%m/%y")
print(s)
Output:
>>> 01/06/05
You see your strptime requires two parameters.
strptime(string[, format])
And the string will be converted to a datetime object according to a format you specify.
There are various formats
%a - abbreviated weekday name
%A - full weekday name
%b - abbreviated month name
%B - full month name
%c - preferred date and time representation
%C - century number (the year divided by 100, range 00 to 99)
%d - day of the month (01 to 31)
%D - same as %m/%d/%y
%e - day of the month (1 to 31)
%g - like %G, but without the century
%G - 4-digit year corresponding to the ISO week number (see %V).
%h - same as %b
%H - hour, using a 24-hour clock (00 to 23)
The above are some examples. Take a look here for formats
Take a goood look at these two!
%b - abbreviated month name
%B - full month name
It should be in a similar pattern to the string you provide. Confusing take a look at these examples.
>>> datetime.strptime('1 jul 2009','%d %b %Y')
datetime.datetime(2009, 7, 1, 0, 0)
>>> datetime.strptime('1 Jul 2009','%d %b %Y')
datetime.datetime(2009, 7, 1, 0, 0)
>>> datetime.strptime('jul 21 1996','%b %d %Y')
datetime.datetime(1996, 7, 21, 0, 0)
As you can see based on the format the string is turned into a datetime object. Now take a look!
>>> datetime.strptime('1 July 2009','%d %b %Y')
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
datetime.strptime('1 July 2009','%d %b %Y')
File "/usr/lib/python3.5/_strptime.py", line 510, in _strptime_datetime
tt, fraction = _strptime(data_string, format)
File "/usr/lib/python3.5/_strptime.py", line 343, in _strptime
(data_string, format))
ValueError: time data '1 July 2009' does not match format '%d %b %Y'
Why error because jun or Jun (short form) stands for %b. When you supply a June it gets confused. Now what to do? Changed the format.
>>> datetime.strptime('1 July 2009','%d %B %Y')
datetime.datetime(2009, 7, 1, 0, 0)
Simple now converting the datetime object is simple enough.
>>> s = datetime.strptime('1 July 2009','%d %B %Y')
>>> s.strftime('%d/%m/%Y')
'01/07/2009
Again the %m is the format for displaying it in months (numbers) read more about them.
The placeholder for "Month as locale’s full name." would be %B not %m:
>>> from datetime import datetime
>>> datetime_object = datetime.strptime('1 June 2005','%d %B %Y')
>>> print(datetime_object)
2005-06-01 00:00:00
>>> print(datetime_object.strftime("%d/%m/%Y"))
01/06/2005
This should work:
from datetime import datetime
print(datetime.strptime('1 June 2005', '%d %B %Y').strftime('%d/%m/%Y'))
print(datetime.strptime('23 July 1914', '%d %B %Y').strftime('%d/%m/%Y'))
For more info you can read about strftime-strptime-behavior
%d means "Day of the month as a zero-padded decimal number."
%m means "Month as a zero-padded decimal number."
Neither day or month are supplied what you tell it to expect. What you need it %B for month (only if your locale is en_US), and %-d for day.

Parsing string into datetime in Python

I have a date with this format
October 14, 2014 1:35PM PDT
I have this in my python script
import time
u_date = 'October 14, 2014 1:35PM PDT'
print time.strptime(u_date,"%b %d, %y %I:%M%p %Z")
I got this error as a result
ValueError: time data u'October 14, 2014 1:35PM PDT' does not match format '%b %d, %y %I:%M%p %Z'
Can anyone explain to me why is this happening? I'm new to python and any help will be appreciated.
Your format is incorrect; %b takes an abbreviated month, but you have a full month, requiring %B, and you have a full 4-digit year, so use %Y, not %y.
The time library cannot parse timezones, however, you'll have to drop the %Z part here and remove the last characters for this to work at all:
>>> time.strptime(u_date[:-4], "%B %d, %Y %I:%M%p")
time.struct_time(tm_year=2014, tm_mon=10, tm_mday=14, tm_hour=13, tm_min=35, tm_sec=0, tm_wday=1, tm_yday=287, tm_isdst=-1)
You could use the dateutil library instead to parse the full string, it'll produce a datetime.datetime object rather than a time struct:
>>> from dateutil import parser
>>> parser.parse(u_date)
datetime.datetime(2014, 10, 14, 13, 35)

Date Format incorrect using strptime [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Python strptime() and timezones?
'Saturday, December 22, 2012 1:22:24 PM EST' does not match format '%A, %B %d, %Y %I:%M:%S %p %Z'
Maybe I'm missing something but can anyone spot why this doesn't validate properly?
The strptime() function cannot handle %Z timezone parsing very well. Only UTC and GMT are really supported, and the current value of time.tzname. See the strptime documenation:
Support for the %Z directive is based on the values contained in tzname and whether daylight is true. Because of this, it is platform-specific except for recognizing UTC and GMT which are always known (and are considered to be non-daylight savings timezones).
Removing the EST part of your input and the %Z part of your format string makes things work:
>>> import time
>>> time.strptime('Saturday, December 22, 2012 1:22:24 PM EST', '%A, %B %d, %Y %I:%M:%S %p %Z')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/_strptime.py", line 454, in _strptime_time
return _strptime(data_string, format)[0]
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/_strptime.py", line 325, in _strptime
(data_string, format))
ValueError: time data 'Saturday, December 22, 2012 1:22:24 PM EST' does not match format '%A, %B %d, %Y %I:%M:%S %p %Z'
>>> time.strptime('Saturday, December 22, 2012 1:22:24 PM', '%A, %B %d, %Y %I:%M:%S %p')
time.struct_time(tm_year=2012, tm_mon=12, tm_mday=22, tm_hour=13, tm_min=22, tm_sec=24, tm_wday=5, tm_yday=357, tm_isdst=-1)
or replacing the timezone EST with GMT:
>>> time.strptime('Saturday, December 22, 2012 1:22:24 PM GMT', '%A, %B %d, %Y %I:%M:%S %p %Z')
time.struct_time(tm_year=2012, tm_mon=12, tm_mday=22, tm_hour=13, tm_min=22, tm_sec=24, tm_wday=5, tm_yday=357, tm_isdst=0)
To parse strings with a timezone other than time.tzname, GMT or UTC, use a different date parsing library. The dateutil library has an excellent parse function that handles timezones properly:
>>> from dateutil.parser import parse
>>> parse('Saturday, December 22, 2012 1:22:24 PM EST', tzinfos={'EST': -18000})
datetime.datetime(2012, 12, 22, 13, 22, 24, tzinfo=tzoffset(u'EST', -18000))
When using dateutil.parser.parse() you do have to provide your own timezone offsets for your format though.
You can save yourself a lot of trouble and use dateutil.
In [1]: from dateutil import parser
In [2]: parser.parse('Saturday, December 22, 2012 1:22:24 PM EST')
Out[2]: datetime.datetime(2012, 12, 22, 13, 22, 24)
As for the ambiguity pointed out by eumiro, you could add a tzinfo argument:
In [3]: parser.parse('Saturday, December 22, 2012 1:22:24 PM EST',tzinfos={'EST':-5*3600})
Out[3]: datetime.datetime(2012, 12, 22, 13, 22, 24, tzinfo=tzoffset('EST', -18000))
As #root suggested dateutil.parser is the robust way to parse date, but just to clarify about the issue here
I just saw the code in _strptime.py and it seems the supported time zones are
["utc", "gmt", time.tzname[0].lower()]
and in case, the current locale timezone supports daylight saving, it would append
time.tzname[0].lower() to the above list.
So when using strptime, ensure that the timezone on which you are parsing the date supports the source timezone
Here is the code for reference
def __calc_timezone(self):
# Set self.timezone by using time.tzname.
# Do not worry about possibility of time.tzname[0] == timetzname[1]
# and time.daylight; handle that in strptime .
try:
time.tzset()
except AttributeError:
pass
no_saving = frozenset(["utc", "gmt", time.tzname[0].lower()])
if time.daylight:
has_saving = frozenset([time.tzname[1].lower()])
else:
has_saving = frozenset()
self.timezone = (no_saving, has_saving)
Most likely your locale timezone is empty, e.g. %Z evaluates to ''
You can test this by:
>>> fmt = '%A, %B %d, %Y %I:%M:%S %p %Z'
>>> datetime.strptime(datetime.strftime(datetime.now(), fmt), fmt)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/_strptime.py", line 325, in _strptime
(data_string, format))
ValueError: time data 'Friday, December 28, 2012 11:34:35 AM ' does not match format '%A, %B %d, %Y %I:%M:%S %p %Z'

Text to datetime in Python [duplicate]

This question already has answers here:
Python time to age
(6 answers)
Closed 8 years ago.
Following on from my previous question, Python time to age, I have now come across a problem regarding the timezone, and it turns out that it's not always going to be "+0200". So when strptime tries to parse it as such, it throws up an exception.
I thought about just chopping off the +0200 with [:-6] or whatever, but is there a real way to do this with strptime?
I am using Python 2.5.2 if it matters.
>>> from datetime import datetime
>>> fmt = "%a, %d %b %Y %H:%M:%S +0200"
>>> datetime.strptime("Tue, 22 Jul 2008 08:17:41 +0200", fmt)
datetime.datetime(2008, 7, 22, 8, 17, 41)
>>> datetime.strptime("Tue, 22 Jul 2008 08:17:41 +0300", fmt)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.5/_strptime.py", line 330, in strptime
(data_string, format))
ValueError: time data did not match format: data=Tue, 22 Jul 2008 08:17:41 +0300 fmt=%a, %d %b %Y %H:%M:%S +0200
is there a real way to do this with strptime?
No, but since your format appears to be an RFC822-family date, you can read it much more easily using the email library instead:
>>> import email.utils
>>> email.utils.parsedate_tz('Tue, 22 Jul 2008 08:17:41 +0200')
(2008, 7, 22, 8, 17, 41, 0, 1, 0, 7200)
(7200 = timezone offset from UTC in seconds)
New in version 2.6.
For a naive object, the %z and %Z
format codes are replaced by empty
strings.
It looks like this is implemented only in >= 2.6, and I think you have to manually parse it.
I can't see another solution than to remove the time zone data:
from datetime import timedelta,datetime
try:
offset = int("Tue, 22 Jul 2008 08:17:41 +0300"[-5:])
except:
print "Error"
delta = timedelta(hours = offset / 100)
fmt = "%a, %d %b %Y %H:%M:%S"
time = datetime.strptime("Tue, 22 Jul 2008 08:17:41 +0200"[:-6], fmt)
time -= delta
You can use the dateutil library which is very useful:
from datetime import datetime
from dateutil.parser import parse
dt = parse("Tue, 22 Jul 2008 08:17:41 +0200")
## datetime.datetime(2008, 7, 22, 8, 17, 41, tzinfo=tzoffset(None, 7200)) <- dt
print dt
2008-07-22 08:17:41+02:00
As far as I know, strptime() doesn't recognize numeric time zone codes. If you know that the string is always going to end with a time zone specification of that form (+ or - followed by 4 digits), just chopping it off and parsing it manually seems like a perfectly reasonable thing to do.
It seems that %Z corresponds to time zone names, not offsets.
For example, given:
>>> format = '%a, %d %b %Y %H:%M:%S %Z'
I can parse:
>>> datetime.datetime.strptime('Tue, 22 Jul 2008 08:17:41 GMT', format)
datetime.datetime(2008, 7, 22, 8, 17, 41)
Although it seems that it doesn't do anything with the time zone, merely observing that it exists and is valid:
>>> datetime.datetime.strptime('Tue, 22 Jul 2008 08:17:41 NZDT', format)
datetime.datetime(2008, 7, 22, 8, 17, 41)
I suppose if you wished, you could locate a mapping of offsets to names, convert your input, and then parse it. It might be simpler to just truncate your input, though.

Python time to age, part 2: timezones [duplicate]

This question already has answers here:
Python time to age
(6 answers)
Closed 8 years ago.
Following on from my previous question, Python time to age, I have now come across a problem regarding the timezone, and it turns out that it's not always going to be "+0200". So when strptime tries to parse it as such, it throws up an exception.
I thought about just chopping off the +0200 with [:-6] or whatever, but is there a real way to do this with strptime?
I am using Python 2.5.2 if it matters.
>>> from datetime import datetime
>>> fmt = "%a, %d %b %Y %H:%M:%S +0200"
>>> datetime.strptime("Tue, 22 Jul 2008 08:17:41 +0200", fmt)
datetime.datetime(2008, 7, 22, 8, 17, 41)
>>> datetime.strptime("Tue, 22 Jul 2008 08:17:41 +0300", fmt)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.5/_strptime.py", line 330, in strptime
(data_string, format))
ValueError: time data did not match format: data=Tue, 22 Jul 2008 08:17:41 +0300 fmt=%a, %d %b %Y %H:%M:%S +0200
is there a real way to do this with strptime?
No, but since your format appears to be an RFC822-family date, you can read it much more easily using the email library instead:
>>> import email.utils
>>> email.utils.parsedate_tz('Tue, 22 Jul 2008 08:17:41 +0200')
(2008, 7, 22, 8, 17, 41, 0, 1, 0, 7200)
(7200 = timezone offset from UTC in seconds)
New in version 2.6.
For a naive object, the %z and %Z
format codes are replaced by empty
strings.
It looks like this is implemented only in >= 2.6, and I think you have to manually parse it.
I can't see another solution than to remove the time zone data:
from datetime import timedelta,datetime
try:
offset = int("Tue, 22 Jul 2008 08:17:41 +0300"[-5:])
except:
print "Error"
delta = timedelta(hours = offset / 100)
fmt = "%a, %d %b %Y %H:%M:%S"
time = datetime.strptime("Tue, 22 Jul 2008 08:17:41 +0200"[:-6], fmt)
time -= delta
You can use the dateutil library which is very useful:
from datetime import datetime
from dateutil.parser import parse
dt = parse("Tue, 22 Jul 2008 08:17:41 +0200")
## datetime.datetime(2008, 7, 22, 8, 17, 41, tzinfo=tzoffset(None, 7200)) <- dt
print dt
2008-07-22 08:17:41+02:00
As far as I know, strptime() doesn't recognize numeric time zone codes. If you know that the string is always going to end with a time zone specification of that form (+ or - followed by 4 digits), just chopping it off and parsing it manually seems like a perfectly reasonable thing to do.
It seems that %Z corresponds to time zone names, not offsets.
For example, given:
>>> format = '%a, %d %b %Y %H:%M:%S %Z'
I can parse:
>>> datetime.datetime.strptime('Tue, 22 Jul 2008 08:17:41 GMT', format)
datetime.datetime(2008, 7, 22, 8, 17, 41)
Although it seems that it doesn't do anything with the time zone, merely observing that it exists and is valid:
>>> datetime.datetime.strptime('Tue, 22 Jul 2008 08:17:41 NZDT', format)
datetime.datetime(2008, 7, 22, 8, 17, 41)
I suppose if you wished, you could locate a mapping of offsets to names, convert your input, and then parse it. It might be simpler to just truncate your input, though.

Categories

Resources