I have a list of strings each of them represent a time with or without milliseconds, e.g.
l = ['03:18:45.2345', '03:19:23']
And I want to convert each string into a datetime object. Now I'm running:
>>> l = ['03:18:45.2345', '03:19:23']
>>> for item in l:
... print datetime.datetime.strptime(item, "%H:%M:%S.%f")
...
1900-01-01 03:18:45.234500
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/usr/lib/python2.7/_strptime.py", line 325, in _strptime
(data_string, format))
ValueError: time data '03:19:23' does not match format '%H:%M:%S.%f'
Hence, the question is: How do I iterate the list converting each element in a datetime object?
The first thought is to have a try..except..:
try:
print datetime.datetime.strptime(item, "%H:%M:%S.%f")
except:
print datetime.datetime.strptime(item, "%H:%M:%S")
Is there any way to do that without catching the ValueError?
l = ['03:18:45.2345', '03:19:23']
for item in l:
time_format = "%H:%M:%S.%f" if '.' in item else "%H:%M:%S"
print datetime.datetime.strptime(item, time_format)
If you are handling more complicated situation(the date string more complex). I recommend you to use dateutil instead of the datetime module.
dateutil.parser offers a generic date/time string parser which is able to parse most known formats to represent a date and/or time.
The prototype of this function is: parse(timestr)(you don't have to specify the format yourself).
DEMO
>>> parse("2003-09-25T10:49:41")
datetime.datetime(2003, 9, 25, 10, 49, 41)
>>> parse("2003-09-25T10:49")
datetime.datetime(2003, 9, 25, 10, 49)
Fuzzy parsing:
>>> s = "Today is 25 of September of 2003, exactly " \
... "at 10:49:41 with timezone -03:00."
>>> parse(s, fuzzy=True)
datetime.datetime(2003, 9, 25, 10, 49, 41,
tzinfo=tzoffset(None, -10800))
ValueError approach is fine but if you want to avoid try/except here:
#!/usr/bin/env python
from datetime import datetime
for time_string in ['03:18:45.2345', '03:19:23']:
time_string, dot, us = time_string.partition('.')
d = datetime.strptime(time_string, '%H:%M:%S')
if dot:
d = d.replace(microsecond=datetime.strptime(us, '%f').microsecond)
print(repr(d.time()))
Output
datetime.time(3, 18, 45, 234500)
datetime.time(3, 19, 23)
Related
I need to change with python a lot of strings with a Spanish date format (DDMMMYYYY, MMM abbreviated month in Spanish) in a other datetime format but I'm having problems because my locale Spanish settings has a "." (a dot) at the end of the string when it change this format in a abbreviated month format.
By default, python take the English version of the language but I can change the language with the locale library.
When I select 'esp' or 'es_ES.utf8' the dot at the end of the abbreviated month appears.
Does it depend on the regional settings of my Windows 10? (I check it and all seems OK) Does it depend on the LOCALE library settings?
The same code in UBUNTU runs OK (without the point)
How can I solve this problem?
I don't want to transform all the strings like that..
str_date = str_date[:5] + "." + str_date[5:]
Thanks a lot!!
Example (previously I change the language with locale):
>>> datetime.strptime('2021-01-18', '%Y-%m-%d').strftime('%b')
'ene.'
>>> print(datetime.strptime('18ene2021', '%d%b%Y'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\galonsoi\AppData\Local\Programs\Python\Python36\lib\_strptime.py", line 565, in _strptime_datetime
tt, fraction = _strptime(data_string, format)
File "C:\Users\galonsoi\AppData\Local\Programs\Python\Python36\lib\_strptime.py", line 362, in _strptime
(data_string, format))
ValueError: time data '18ene2021' does not match format '%d%b%Y'
>>> print(datetime.strptime('18ene.2021', '%d%b%Y'))
2021-01-18 00:00:00 ----> THIS IS OK BECAUSE I WRITE THE DOT AT THE END OF THE ABBREVIATED MONTH
Complete sequence of the Example
>>> import locale
>>> from datetime import datetime
>>>
>>> locale.getlocale()
(None, None)
>>> print (datetime.strptime('2021-01-18', '%Y-%m-%d').strftime('%b'))
Jan
>>> locale.setlocale(locale.LC_ALL, '')
`Spanish_Spain.1252`
>>> locale.getlocale()
(`es_ES`, `cp1252`)
#INCORRECT FORMAT, ADD A "." AT THE END
>>> print (datetime.strptime('2021-01-18', '%Y-%m-%d').strftime('%b'))
ene.
>>> locale.setlocale(locale.LC_ALL, 'es_ES.UTF-8')
`es_ES.UTF-8`
#FORMATO INCORRECTO, AÑADE UN "." a may
>>> print (datetime.strptime('2021-01-18', '%Y-%m-%d').strftime('%b'))
ene.
>>> print(datetime.strptime('18ene2021', '%d%b%Y'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\galonsoi\AppData\Local\Programs\Python\Python36\lib\_strptime.py", line 565, in _strptime_datetime
tt, fraction = _strptime(data_string, format)
File "C:\Users\galonsoi\AppData\Local\Programs\Python\Python36\lib\_strptime.py", line 362, in _strptime
(data_string, format))
ValueError: time data '18ene2021' does not match format '%d%b%Y'
>>> print(datetime.strptime('18ene.2021', '%d%b%Y'))
2021-01-18 00:00:00 ----> THIS IS OK BECAUSE I WROTE THE DOT AT THE END OF THE ABBREVIATED MONTH
You could make use of dateutil's parser, where you can set custom month names via the parser.parserinfo class. Ex:
import locale
locale.setlocale(locale.LC_ALL, 'Spanish_Spain.1252') # set locale for reproducibility
import calendar
from dateutil import parser
# subclass parser.parserinfo and set custom month names with dots stripped:
class LocaleParserInfo(parser.parserinfo):
MONTHS = [(ma.strip('.'), ml) for ma, ml in zip(calendar.month_abbr, calendar.month_name)][1:]
s = '18ene2021'
print(parser.parse(s, parserinfo=LocaleParserInfo()))
# 2021-01-18 00:00:00
This is very unexpected behavior...
I create a time string using the '%c' directive.
%c is the Locale’s appropriate date and time representation.
Then I try to parse the resulting time string, specifying the same '%c' as the string's format.
However this does not work as you can see from the error below. What am I missing?
I need to be able to store the time in a human-readable localized string, and then convert the string back into a struct_time so I can extract information from it.
(It is extremely important that the string be localized, and I of course don't want to write parsing algorithms for all locales around the world!)
# Ensure the locale is set.
import locale
locale.setlocale(locale.LC_ALL, '')
'en_US.UTF-8'
# 1. Create a localized time string using the '%c' directive.
import datetime
time_stamp = datetime.datetime.now().strftime('%c')
time_stamp
'Mon 21 Dec 2020 03:47:55 PM '
# 2. Try to parse the string using the same directive used to create it.
import time
time.strptime(time_stamp, '%c')
# 3. Unexpected error...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.8/_strptime.py", line 562, in _strptime_time
tt = _strptime(data_string, format)[0]
File "/usr/lib/python3.8/_strptime.py", line 349, in _strptime
raise ValueError("time data %r does not match format %r" %
ValueError: time data 'Mon 21 Dec 2020 03:47:55 PM ' does not match format '%c'
Your locale is probably not configuring .strftime("%c") the way you expect and .strptime is objecting to the postfixed %p (PM)
Use locale.nl_langinfo(locale.D_T_FMT) to build your format instead!
>>> locale.nl_langinfo(locale.D_T_FMT)
'%a %b %e %H:%M:%S %Y'
>>> locale.setlocale(locale.LC_ALL, '')
'en_US.UTF-8'
>>> locale.nl_langinfo(locale.D_T_FMT)
'%a %b %e %X %Y'
However, if you
.. know the exact structure of the output, filter exact matches with a regex and then parse
.. can control the format, don't bother to format it and directly use time.time()
.. or always work in UTC and format as ISO 8601, deriving a tz-aware object and reading back with a custom parser (refer to the Caution on .fromisoformat)
>>> datetime.datetime.now(tz=datetime.timezone.utc)
datetime.datetime(2020, 12, 22, 0, 4, 29, 537007, tzinfo=datetime.timezone.utc)
use pytz, which is much "smarter" than the datetime builtin lib and properly supports a huge variety of locales
Instead of using %c, you can specify how you want to format the date using %a, %b and other directives. For example:
import locale
locale.setlocale(locale.LC_ALL, 'en_US.utf-8')
import datetime
fmt = '%a %b %d %Y %H:%M:%S'
time_stamp = datetime.datetime.now().strftime(fmt)
print(time_stamp)
import time
print(time.strptime(time_stamp, fmt))
This produces an output that you are looking for:
Output:
Mon Dec 21 2020 21:27:50
time.struct_time(tm_year=2020, tm_mon=12, tm_mday=21, tm_hour=21, tm_min=27, tm_sec=50, tm_wday=0, tm_yday=356, tm_isdst=-1)
I am trying to convert these strings to timestamps:
python test.py
2015-02-15T14:25:54+00:00
2015-02-15T16:59:01+00:00
2015-02-15T18:44:13+00:00
2015-02-15T18:45:24+00:00
2015-02-15T18:52:11+00:00
2015-02-15T18:52:33+00:00
2015-02-15T18:59:00+00:00
2015-02-15T19:06:16+00:00
2015-02-15T19:07:02+00:00
I get this output on executing below code:
for member in members_dict['members']:
s = member['timestamp_signup']
print s
But when I try to get the timestamp:
for member in members_dict['members']:
s = member['timestamp_signup']
print s
print time.mktime(datetime.datetime.strptime(s, "%Y-%m-%dT%H:%M:%S+00:00").timetuple())
I get the error as:
Traceback (most recent call last):
File "test.py", line 20, in <module>
print datetime.strptime(s, '"%Y-%m-%dT%H:%M:%S+00:00"').date()
File "/usr/lib/python2.7/_strptime.py", line 325, in _strptime
(data_string, format))
ValueError: time data '' does not match format '"%Y-%m-%dT%H:%M:%S+00:00"'
What am I doing wrong here?
Your code to convert string to datetime is fine. For example:
>>> from datetime import datetime
>>> my_str = '2015-02-15T14:25:54+00:00'
>>> datetime.strptime(my_str, "%Y-%m-%dT%H:%M:%S+00:00")
datetime.datetime(2015, 2, 15, 14, 25, 54)
Error you are getting is due to empty string present in your file. I got to know about it based on your error message:
ValueError: time data '' does not match format
# empty string ^
Possibly there is empty line at the end of your file (or, somewhere else)
im using the following that works awesome for converting a UTC string to date times -- except when the milliseconds are LONGER than 6 digits. than it blows. urgh*&^*&
format = '%Y-%m-%dT%H:%M:%S'
if '.' in value:
format = format + '.%f'
if value.endswith('Z'):
format = format + 'Z'
return datetime.strptime(value, format)
here is the stacktrace
File "/usr/lib64/python2.6/_strptime.py", line 325, in _strptime
(data_string, format))
ValueError: time data '2013-07-19T13:02:53.8241899Z' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'
whats a method to restrict the milliseconds to 6 digits in length. ive used using '{:%Y-%m-%dT%H:%M:%S.6%f}'.format( datetime ) but that helps nonce/
so trying re.sub( ) to limit the decimals (if any) following the '.'character in the provided string. but am not very regex savvy.
im using python 2.6.* on the machine.
Sounds like a job for dateutil.
$ pip install python-dateutil
$ python
>>> import dateutil.parser
>>> d = dateutil.parser.parse('2013-07-19T13:02:53.8241899Z')
>>> print d
2013-07-19 13:02:53.824189+00:00
You could use .partition() method to parse the string:
from datetime import datetime
sz = '2013-07-19T13:02:53.8241899Z' # utc time in rfc3339 format (without offset)
sz = sz.rstrip('Z') # remove ending 'Z' if present
timestr, _, digits = sz.partition('.')
utc_dt = datetime.strptime(timestr, '%Y-%m-%dT%H:%M:%S')
if digits:
microseconds = int(digits, 10) * 10**(6 - len(digits))
utc_dt = utc_dt.replace(microsecond=int(microseconds + .5))
If you want to use re.sub and don't mind truncating the microseconds:
import re
from datetime import datetime
sz = '2013-07-19T13:02:53.8241899Z'
if '.' in sz:
sz = re.sub(r'(\.\d{,6})\d*Z?$', r'\1Z', sz) # truncate to 6 digits +Z
else: # no fractions
sz = sz.rstrip('Z') + '.0Z'
utc_dt = datetime.strptime(sz, '%Y-%m-%dT%H:%M:%S.%fZ')
If you wanted to do it with re.sub, here's a short example of one way to do that.
import re
from datetime import datetime
value = '2013-07-19T13:02:53.8241899Z'
regex = r"(\d{6,}\d+)"
if re.search(regex, value):
repl = lambda x: x.group(0)[:6]
value = re.sub(pattern=regex, repl=repl, string=value)
format = '%Y-%m-%dT%H:%M:%S'
if '.' in value:
format = format + '.%f'
if value.endswith('Z'):
format = format + 'Z'
print datetime.strptime(value, format)
i am trying to convert a date string to date format
>>> str = "04-18-2002 03:50PM"
>>> time.strptime(str, '%m-%d-%Y %H:%M%p')
time.struct_time(tm_year=2002, tm_mon=4, tm_mday=18, tm_hour=3, tm_min=50, tm_sec=0, tm_wday=3, tm_yday=108, tm_isdst=-1)
however when the year is in two digit it breaks
>>> str = "04-18-02 03:50PM"
>>> time.strptime(str, '%m-%d-%Y %H:%M%p')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/_strptime.py", line 454, in _strptime_time
return _strptime(data_string, format)[0]
File "/usr/lib/python2.7/_strptime.py", line 325, in _strptime
(data_string, format))
ValueError: time data '04-18-02 03:50' does not match format '%m-%d-%Y %H:%M'
any ideas??
%Y in the format string denotes a four-digit year, see the documentation. For a two-digit year, use %y instead. To support both formats, first try: one of the formats, and catch the ValueError and try the other one.
The correct format for a two-digit year is %y (lowercase y).
As a side note, please don't call the string variable str as it shadows the builtin.