Почему следующий простой код Python 3 strptime () работает на OSX, но не на Linux? - PullRequest
2 голосов
/ 06 ноября 2019

Следующий код для чтения и проверки даты в формате ISO8601 работает, как и ожидалось, в python 3.7.4 OSX. В Linux возникает ошибка

Python 3.6.8 (default, Oct 14 2019, 21:22:53) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> format_string = '%Y-%m-%dT%H:%M:%S%z'
>>> from datetime import datetime
>>> d = datetime.strptime('2019-11-05T00:00:00Z', format_string)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python3.6/_strptime.py", line 565, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/usr/lib64/python3.6/_strptime.py", line 362, in _strptime
    (data_string, format))
ValueError: time data '2019-11-05T00:00:00Z' does not match format '%Y-%m-%dT%H:%M:%S%z'

Под OSX:

Python 3.7.4 (default, Jul  9 2019, 18:15:00) 
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> format_string = '%Y-%m-%dT%H:%M:%S%z'
>>> from datetime import datetime
>>> d = datetime.strptime('2019-11-05T00:00:00Z', format_string)
>>> print(d)
2019-11-05 00:00:00+00:00

Я посмотрел эту статью , которая относится к вызовам библиотеки C, но, безусловно, Python должен бытьportable?

Два дистрибутива, которые я пробовал (Red Hat и EC2 Linux), имеют 3.6.8 из yum, и оба выдают ошибку. Конечно, это не может быть разница версий?

Ответы [ 2 ]

2 голосов
/ 07 ноября 2019

Я тестировал этот OSX в средах Conda на Python 3.6.8 и Python 3.7.4. Кажется, это несоответствие между версиями Python.

Это связано с тем, что в Python 3.7 была добавлена ​​поддержка использования 'Z' в конце форматированных строк даты и времени. 'Z' является псевдонимом для смещения UTC "+00: 00", и поддержка разделителей двоеточий в смещениях UTC не добавлялась в директиву '%z' до Python 3.7.

Для решения, которое будет работать с Python 3.6 и 3.7, вместо 'Z' используйте '+0000', поэтому строка даты и времени станет '2019-11-05T00:00:00+0000'.

format_string = '%Y-%m-%dT%H:%M:%S%z'
d = datetime.strptime('2019-11-05T00:00:00+0000', format_string)

. в обеих версиях.

Для более подробной информации, проверьте документы Python 3.7 datetime .

1 голос
/ 08 ноября 2019

Обходной путь для различного поведения видел. Эта функция предназначена для использования с argparse, следовательно, с последней строкой.

def iso8601_tzoffset(timestamp):
    """
    Validate time string, which includes Seconds and (optional) timezone offset.
    Beautiful idea made ugly by strptime() timzone offset syntax varying between Python 3.6 and 3.7?
    :param timestamp: str
    :return: datetime
    """
    format_string = '%Y-%m-%dT%H:%M:%S%z'
    try:
        d = datetime.strptime(timestamp, format_string)
        return d
    except ValueError as e:
        # We want to accept "Z", but strptime doesn't on all platforms, so fix it up here
        if timestamp.endswith('Z'):
            timestamp = timestamp.rstrip('Z') + '+0000'
        else:
            # We want to accept timezone HH:MM with separator, but strptime <3.7 requires HHMM, fix it up here
            sep = max(timestamp.rfind('+'), timestamp.rfind('-'))
            if sep < 0:
                raise argparse.ArgumentTypeError(e)
            else:
                tz = timestamp[sep:]
                ymdhms = timestamp[:sep]
                tz = tz.replace(':', '')
                timestamp = ymdhms + tz
        try:
            d = datetime.strptime(timestamp, format_string)
            return d
        except:
            raise argparse.ArgumentTypeError(e)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...