Подтвердить что ты не робот

Преобразование даты и времени - как извлечь выведенный формат?

Здесь массив значений даты и времени:

array = np.array(['2016-05-01T00:00:59.3+10:00', '2016-05-01T00:02:59.4+10:00',
                  '2016-05-01T00:03:59.4+10:00', '2016-05-01T00:13:00.1+10:00',
                  '2016-05-01T00:22:00.5+10:00', '2016-05-01T00:31:01.1+10:00'],
        dtype=object)

pd.to_datetime очень хорош для вывода форматов datetime.

array = pd.to_datetime(array)

print(array)
DatetimeIndex(['2016-04-30 14:00:59.300000', '2016-04-30 14:02:59.400000',
               '2016-04-30 14:03:59.400000', '2016-04-30 14:13:00.100000',
               '2016-04-30 14:22:00.500000', '2016-04-30 14:31:01.100000'],
              dtype='datetime64[ns]', freq=None)

Как я могу динамически определить, какой формат datetime pd.to_datetime выведен? Что-то вроде: %Y-%m-%dT... (извините, мое datetime foo действительно плохо).

4b9b3361

Ответ 1

Я не думаю, что это можно сделать в полной общности в pandas.

Как упоминалось в других комментариях и ответах, внутренняя функция _guess_datetime_format близка к тому, что вы просите, но имеет строгие критерии для того, что составляет допустимый формат, и поэтому он будет работать только для ограниченного класса строк datetime.

Эти критерии указаны в _guess_datetime_format на этих строках, и вы также можете увидеть некоторые примеры хороших и плохих форматов в test_parsing script.

Некоторые из основных моментов:

  • каждый год, месяц и день должны присутствовать и идентифицироваться
  • год должен иметь четыре цифры
  • ровно шесть цифр должны использоваться при использовании микросекунд
  • вы не можете указать часовой пояс

Это означает, что он не сможет угадать формат строк datetime в вопросе, несмотря на то, что он является допустимым ISO 8601:

>>> from pandas.core.tools.datetimes import _guess_datetime_format_for_array
>>> array = np.array(['2016-05-01T00:00:59.3+10:00'])
>>> _guess_datetime_format_for_array(array)
# returns None

В этом случае сбросить часовой пояс и отложить микросекунды до шести цифр достаточно, чтобы pandas распознал формат:

>>> array = np.array(['2016-05-01T00:00:59.300000']) # six digits, no tz
>>> _guess_datetime_format_for_array(array)
'%Y-%m-%dT%H:%M:%S.%f'

Это, вероятно, так же хорошо, как и получается.

Если pd.to_datetime не предлагается вывести формат массива или задать строку формата, чтобы попробовать, он просто попытается разобрать каждую строку отдельно и надеяться, что она будет успешной. Крайне важно, чтобы для этого не нужно было делать предварительный формат.

Сначала pandas анализирует строку, предполагая, что она (приблизительно) в формате ISO 8601. Это начинается при вызове _string_to_dts и в конечном итоге попадает на низкоуровневый parse_iso_8601_datetime, которая выполняет тяжелую работу.

Вы можете проверить, может ли ваша строка обрабатываться таким образом, используя функцию _test_parse_iso8601. Например:

from pandas._libs.tslib import _test_parse_iso8601

def is_iso8601(string):
    try:
        _test_parse_iso8601(string)
        return True
    except ValueError:
        return False

Даты в массиве, который вы даете, распознаются в этом формате:

>>> is_iso8601('2016-05-01T00:00:59.3+10:00')
True

Но это не дает то, о чем спрашивает вопрос, и я не вижу реалистичного способа восстановления точного формата, который распознается функцией parse_iso_8601_datetime.

Если разбор строки в формате ISO 8601 завершается неудачно, pandas возвращается к использованию функции parse() от стороннего dateutil library (называется parse_datetime_string). Это дает фантастический уровень гибкости синтаксического анализа, но, опять же, я не знаю, какой хороший способ извлечь признанный формат даты и времени из этой функции.

Если оба из этих парсеров терпят неудачу, pandas вызывает ошибку, игнорирует строку или значения по умолчанию NaT (в зависимости от того, что указывает пользователь). Не предпринимается дальнейшая попытка разобрать строку или угадать формат строки.

Ответ 2

Библиотека DateInfer (PyDateInfer) позволяет выводить даты на основе последовательности доступных дат:

github.com/wdm0006/dateinfer

Использование документов:

>>> import dateinfer
>>> dateinfer.infer(['Mon Jan 13 09:52:52 MST 2014', 'Tue Jan 21 15:30:00 EST 2014'])
'%a %b %d %H:%M:%S %Z %Y'
>>>

Отказ от ответственности: я использовал, а затем внес вклад в эту библиотеку

Ответ 3

Вы можете использовать _guess_datetime_format от core.tools, чтобы получить формат. т.е.

from pandas.core.tools import datetimes as tools
tools._guess_datetime_format(pd.to_datetime(array).format()[0][:10])

Выход:

'%Y-%m-%d'

Чтобы узнать больше об этом методе, вы можете увидеть здесь. Надеюсь, поможет.