Whats wrong with my datetime.strptime format?

2019-02-25 18:31发布

问题:

With this function:

timestamp = datetime.strptime(date_str, date_fmt)

I am getting this error:

ValueError: time data 'Sun, 28 Oct 2018 07:33:13 -0400 (EDT)' does not match format '%a, %d %b %Y %H:%M:%S %z (%Z)'

Sun, 28 Oct 2018 07:33:13 -0400 (EDT)
%a, %d %b %Y %H:%M:%S %z (%Z)

I've looked over it a dozen times and I can't figure out what I am doing wrong.

My Python Version:

Python 3.7.0 (default, Jul 23 2018, 20:24:19) 

回答1:

There is no support for %Z on input for anything other than your current timezone. Only the strings in the time.tzname tuple plus 'UTC' and 'GMT' will ever be recognised:

>>> from datetime import datetime
>>> import time
>>> time.tzname
('GMT', 'BST')
>>> sample = 'Sun, 28 Oct 2018 07:33:13 -0400 (EDT)'
>>> datetime.strptime(sample.replace('EDT', time.tzname[0]), '%a, %d %b %Y %H:%M:%S %z (%Z)')
datetime.datetime(2018, 10, 28, 7, 33, 13, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000), 'GMT'))
>>> datetime.strptime(sample.replace('EDT', time.tzname[1]), '%a, %d %b %Y %H:%M:%S %z (%Z)')
datetime.datetime(2018, 10, 28, 7, 33, 13, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000), 'BST'))

Since you also have the offset from UTC in the string (the -0400 part), just remove the timezone name from your input and don't bother trying to parse it:

>>> datetime.strptime(sample.rpartition(' ')[0], '%a, %d %b %Y %H:%M:%S %z')
datetime.datetime(2018, 10, 28, 7, 33, 13, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000)))

I used str.rpartition() here to remove everything starting at the last space, but it depends on what kind of inputs that you have how to best remove the timezone name part in your application. Without it, the (%Z) section is not needed and you get a correct datetime object.

When debugging datetime.strptime() issues, you want to compartmentalise the issue. You can bisect the input and template parts to see where the issue lies, or try out the different components one by one. It could be a single directive that causes the issue, or multiple, so I usually go for single-step removing of directives until one works.