Преобразование строки в дату и время

У меня есть огромный список таких дат в виде строк:

Jun 1 2005  1:33PM
Aug 28 1999 12:00AM

Я собираюсь засунуть их обратно в соответствующие поля datetime в базе данных, поэтому мне нужно превратить их в реальные объекты datetime.

Это происходит через ORM Django, поэтому я не могу использовать SQL для преобразования при вставке.

Если вы не уверены, что один формат обрабатывает каждую дату и время (нет '', нет NaN, нет неполных данных, нет несоответствий формата, нет конечных символов, часовых поясов, микросекундных временных меток или другого текста ...), счастье-исключение strptime() сведет вас с ума, если вы его не завернете. Смотрите мой ответ, основанный на Или Вайс ответит на это

smci 15.12.2017 06:00

Самый ленивый и наиболее широко используемый подход, который я знаю, - это анализатор дат (проверьте blog.scrapinghub.com/2015/11/09/…). Он работает даже с выражениями времени на естественном языке на нескольких языках из коробки. Я думаю, это может быть медленным.

Armando 01.11.2019 20:23

Здесь есть полезная ссылка: stackabuse.com/converting-strings-to-datetime-in-python

GoingMyWay 04.01.2020 17:37
datetime.strptime, как упоминали другие. Для тех, кто предпочитает видеообъяснение, глянь сюда.
Ben 03.02.2021 08:03
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2 393
4
3 301 798
23
Перейти к ответу Данный вопрос помечен как решенный

Ответы 23

Проверьте strptime в модуле время. Это обратное strftime.

$ python
>>> import time
>>> my_time = time.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')
time.struct_time(tm_year=2005, tm_mon=6, tm_mday=1,
                 tm_hour=13, tm_min=33, tm_sec=0,
                 tm_wday=2, tm_yday=152, tm_isdst=-1)

timestamp = time.mktime(my_time)
# convert time object to datetime
from datetime import datetime
my_datetime = datetime.fromtimestamp(timestamp)
# convert time object to date
from datetime import date
my_date = date.fromtimestamp(timestamp)

Насколько я понимаю, этот ответ выводит только объекты времени, а не объекты datetime, поэтому ответ будет похоронен по сравнению с ответом Патрика.

Alexander Bird 07.09.2010 17:08

Есть ли способ установить формат даты и времени по умолчанию для DateTimeField?

kingpin 22.01.2013 19:50

Как сказал Александр, это возвращает struct_time, а не datetime. Конечно, вы можете преобразовать его в datetime, но ответ Патрика более прямолинейный, если вам нужен объект datetime в конце.

Leandro Alves 09.03.2013 19:20

В стандартной библиотеке Python нет ничего лучше strtotime, но у dateutil есть синтаксический анализатор, который распознает множество форматов даты наилучшего качества.

Geoff Gerrietts 15.11.2013 09:47

@BenBlank: «% b», «% p» может не работать в неанглийской локали.

jfs 29.04.2014 14:54

ВНИМАНИЕ !! Я обнаружил, что очень сложно манипулировать данными времени в объекте time.struct_time. например, если вы хотите добавить к этому объекту определенные дни, вам необходимо преобразовать объект time.struct_time в объект datetime.datetime. нет другого пути

Chenming Zhang 16.06.2014 04:55
Ответ принят как подходящий

datetime.strptime - это основная процедура для разбора строк на даты и время. Он может обрабатывать всевозможные форматы, причем формат определяется строкой формата, которую вы ему указываете:

from datetime import datetime

datetime_object = datetime.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')

Результирующий объект datetime не зависит от часовых поясов.

Ссылки:

  • Документация Python для strptime: Python 2, Python 3

  • Документация Python для строк формата strptime / strftime: Python 2, Python 3

  • strftime.org также является отличным справочником по strftime.

Заметки:

  • strptime = "время синтаксического анализа строки"
  • strftime = "время в строковом формате"
  • Произнесите это вслух сегодня, и вам не придется искать его снова через 6 месяцев.

"% b", "% p" может завершиться ошибкой в ​​неанглийской локали.

jfs 29.04.2014 14:55

Что за строка не успевает, просто «25 апреля 2014 года»

User 30.04.2014 05:56

@User Вам нужно будет заранее знать, чтобы исключить эту часть строки формата, но если вы хотите date вместо datetime, проход через datetime справится с этим хорошо: datetime.strptime('Jun 1 2005', '%b %d %Y').date() == date(2005, 6, 1)

Izkata 11.11.2014 23:02

Чтобы проанализировать выходные данные команды unix 'date' по умолчанию, в которой есть часовой пояс, например «Sun Oct 4 07:48:48 UTC 2015» можно использовать datetime.strptime (currentDateStr, «% a% b% d% H:% M:% S% Z% Y»).

gaoithe 07.10.2015 13:28

Обратите внимание, что эта функция была добавлена ​​где-то между python 2.4.3 и python 2.6.

Mitch 20.09.2016 20:25

угадывание strptime - всегда сложная задача, требующая много времени, для этого я создал одну службу помощи. проверить percepty.com/…

Gagandeep Singh 04.12.2016 15:33

Если вы знаете, что строка представляет дату и время в формате UTC, вы можете получить объект datetime с учетом часового пояса, добавив эту строку в Python 3: from datetime import timezone; datetime_object = datetime_object.replace(tzinfo=timezone.utc)

Flimm 08.12.2016 13:28

Любая идея, как получить datetime с учетом часового пояса в python до 3?

TheJKFever 22.03.2017 22:07

Искал "%Y-%m-%d %H:%M:%S"

Martin Thoma 07.12.2017 16:56

Получил вот эту ошибку AttributeError: 'module' object has no attribute 'strptime'

Aminah Nuraini 20.10.2018 09:41

@AminahNuraini Я обошел аналогичную проблему, сделав from datetime import datetime вместо import datetime.

Max Strater 13.11.2018 00:02

Сообщество Python не делает себе никаких одолжений, используя соглашения об именах, такие как strptime и strftime, которые заставляют пользователей переходить к документам, а не находить решение интерактивно в списках поддерживаемых функций объекта.

geotheory 12.05.2019 22:37

+1 За заметки о значении strptime и strftime. Мне всегда приходилось искать, какой из них я должен использовать, эта заметка позволяет легко запомнить.

amiabl 24.07.2019 15:50

вот я ищу его через 6 месяцев, и я уже проголосовал за этот ответ раньше :(

cryanbhu 27.08.2019 05:51

Искал "%Y-%m-%d %H:%M:%S.%f"

fabda01 21.01.2020 05:42

Используйте стороннюю библиотеку dateutil:

from dateutil import parser
parser.parse("Aug 28 1999 12:00AM")  # datetime.datetime(1999, 8, 28, 0, 0)

Он может обрабатывать большинство форматов даты, включая тот, который вам нужно проанализировать. Это удобнее, чем strptime, так как большую часть времени может угадывать правильный формат.

Это очень полезно для написания тестов, где удобочитаемость важнее производительности.

Вы можете установить его с помощью:

pip install python-dateutil

Имейте в виду, что для больших объемов данных это может быть не самый оптимальный способ решения проблемы. Угадывать формат каждый раз может быть ужасно медленным.

Paweł Polewicz 03.07.2011 04:08

Это хорошо, но было бы неплохо иметь встроенное решение, а не обращаться к третьему лицу.

brian buck 13.10.2011 00:33

Когда я пытаюсь разобрать «32nd jan», он возвращает мне «2032-01-06» .. что неверно. есть ли способ проверить, является ли строка действительной датой или нет

Kartik Domadiya 06.03.2013 10:11

@Reef: в 5 раз медленнее, согласно моему быстрому и грязному тесту. Не так, ужасно медленный, как я ожидал.

Antony Hatchkins 30.04.2013 22:19

Обратите внимание, что текущая версия dateutil, версия 2.2, зависит от библиотеки six, которая является библиотекой совместимости Python 2/3. Это позволяет dateutil 2.2 работать как с Python 2.x, так и с Python 3.x.

Simon Tewsi 29.11.2013 01:11

Есть свои проблемы - например, незаметное удаление информации о часовом поясе из раз: попробуйте parser.parse ('15: 55EST ') и сравните с parser.parse ('15 .55CST') в качестве примера.

F1Rumors 18.05.2015 18:42

У этого есть очень неудачная привычка путать между американскими и британскими форматами dmy и mdy .. Но это удобно, когда вы ленитесь или вам приходится манипулировать многими форматами.

Oli 12.04.2016 10:20

Отличный ответ - хороший модуль (я сам боялся писать что-то подобное!) Есть ли способ побудить dateutil предпочесть британский стиль дат американскому? Что-то, что я мог бы использовать, подтолкнуть его так или иначе при разных обстоятельствах? edit - похоже, что документы покрывает это с помощью ключевого слова dayfirst

Thomas Kimber 10.02.2018 03:06
Принимает, но игнорирует дробную часть секунды.% F (как в 12:55:01.00123).
Tom Hundt 18.02.2020 05:04

То, что здесь не упомянуто и полезно: добавление суффикса к дню. Я отделил логику суффикса, чтобы вы могли использовать ее для любого числа, которое вам нравится, а не только для дат.

import time

def num_suffix(n):
    '''
    Returns the suffix for any given int
    '''
    suf = ('th','st', 'nd', 'rd')
    n = abs(n) # wise guy
    tens = int(str(n)[-2:])
    units = n % 10
    if tens > 10 and tens < 20:
        return suf[0] # teens with 'th'
    elif units <= 3:
        return suf[units]
    else:
        return suf[0] # 'th'

def day_suffix(t):
    '''
    Returns the suffix of the given struct_time day
    '''
    return num_suffix(t.tm_mday)

# Examples
print num_suffix(123)
print num_suffix(3431)
print num_suffix(1234)
print ''
print day_suffix(time.strptime("1 Dec 00", "%d %b %y"))
print day_suffix(time.strptime("2 Nov 01", "%d %b %y"))
print day_suffix(time.strptime("3 Oct 02", "%d %b %y"))
print day_suffix(time.strptime("4 Sep 03", "%d %b %y"))
print day_suffix(time.strptime("13 Nov 90", "%d %b %y"))
print day_suffix(time.strptime("14 Oct 10", "%d %b %y"))​​​​​​​

Я собрал проект, который может преобразовывать некоторые действительно изящные выражения. Проверьте временная строка.

Вот несколько примеров ниже:

pip install timestring
>>> import timestring
>>> timestring.Date('monday, aug 15th 2015 at 8:40 pm')
<timestring.Date 2015-08-15 20:40:00 4491909392>
>>> timestring.Date('monday, aug 15th 2015 at 8:40 pm').date
datetime.datetime(2015, 8, 15, 20, 40)
>>> timestring.Range('next week')
<timestring.Range From 03/10/14 00:00:00 to 03/03/14 00:00:00 4496004880>
>>> (timestring.Range('next week').start.date, timestring.Range('next week').end.date)
(datetime.datetime(2014, 3, 10, 0, 0), datetime.datetime(2014, 3, 14, 0, 0))

Ух ты. Ух ты. Ух ты. Ух ты. Это так просто. У меня есть строка даты и времени, и я просто хочу вывести год. Очень просто: import timestringtimestring.Date('27 Mar 2014 12:32:29 GMT').year Эта библиотека сделала это НАСТОЛЬКО ЛЕГКО! Спасибо.

brandonjp 11.04.2014 09:09

Добро пожаловать. Я хотел бы получить ваши комментарии и идеи по улучшению этого пакета. Дайте мне знать, используйте проблемы с github. Спасибо!

Steve Peak 14.04.2014 18:30

Привет, Стив, модуль отличный. Было бы неплохо иметь также строковый атрибут дня недели. В противном случае не уверен, начнете ли вы с понедельника или воскресенья.

Anake 23.10.2014 14:00

@Anake, вы можете создать проблему, чтобы запросить это добавление на github.com/stevepeak/timestring, спасибо!

Steve Peak 26.10.2014 01:22

Выглядит очень интересно ... было бы еще лучше, если бы он включал синтаксический анализатор dateutil (и, возможно, некоторые другие полезности). Хотя хорошая работа (:

drevicko 07.11.2014 03:09

Это отличный пакет. Диапазон безумно мощный. Как бы вы преобразовали объект timestring в datetime? Я бы хотел сократить время, но .date() недоступен.

Ben Keating 10.02.2015 22:53

Да. timestring.Range('this week').start и timestring.Range('this week').end

Steve Peak 11.02.2015 01:18

Этот модуль очень удобен в использовании. Однако помните о не очень хорошей производительности. Результат профилирования на ноутбуке i7: Python\Python27\site-packages\timestring\Date.py.__init__:20 2458 1.42 0.41 (ncall ttot tsub) Для выполнения 2400 вызовов timestring.Date('19:36:23 06/05/2015').to_unixtime() требуется более 1,4 секунды

Mr. Girgitt 07.06.2015 01:15

Возможность распознавать все типы ввода здесь действительно фантастическая. Отличным дополнением является то, что он также может распознавать менее формальные временные диапазоны, такие как «17-18 часов». И тогда еще лучше была бы возможность распознавать стиль временных диапазонов, часто используемый в текстовых сообщениях, например «5:30 вечера-6» (без необходимости наличия двоеточий или am / pm для обоих раз).

Patrick 05.11.2016 01:27

ПРЕДУПРЕЖДЕНИЕ: timestring еще не обрабатывает субсекундное время правильно: timestring.Date('Aug 28 1999 12:53:45.123 AM').date дает datetime.datetime (1999, 8, 28, 0, 53, 45, 0), но dateutil.parser.parse('Aug 28 1999 12:53:45.123 AM') правильно дает datetime.datetime (1999, 8, 28, 0, 53, 45, 123)

hobs 07.06.2017 02:44

Он не преобразует должным образом, например, «5 февраля 2017 года» и «5 февраля 2017 года» (которые являются форматами, популярными в некоторых кругах, а IMO - одними из лучших форматов даты для ясности и удобочитаемости). Он хранит их как 2017-02-01. То же самое для 5 февраля 2017 г. (правда, 5 февраля 2017 г.); Насколько мне известно, ни один из этих двух последних форматов не использовался, но я подумал, что все равно укажу на него.

Brōtsyorfuzthrāx 10.08.2017 13:13
ПРЕДУПРЕЖДЕНИЕ: Этот пакет, похоже, не поддерживался или не улучшался за последние 5 лет и регулярно анализирует заведомо неверные даты. Например, создание экземпляра Date("20180912") каким-то образом анализирует значение 2018-11-21. Используйте на свой риск.
bsplosion 21.11.2019 20:52

Многие временные метки подразумевают часовой пояс. Чтобы гарантировать, что ваш код будет работать в каждом часовом поясе, вы должны использовать UTC внутренне и прикреплять часовой пояс каждый раз, когда посторонний объект входит в систему.

Python 3.2+:

>>> datetime.datetime.strptime(
...     "March 5, 2014, 20:13:50", "%B %d, %Y, %H:%M:%S"
... ).replace(tzinfo=datetime.timezone(datetime.timedelta(hours=-3)))

Почему вы используете уродливый, а иногда и неправильный (mktime() во время перехода на летнее время) 1-й метод, если вы знаете 2-й метод (datetime.strptime())? Если вы хотите избежать исключения во время дополнительной секунды (второй метод не работает), вы можете вместо этого использовать calendar.timegm: (datetime(1970,1,1)+timedelta(seconds=timegm(time.strptime(.‌​.)))).replace(tzinfo‌​=timezone(timedelta(‌​-3)))

jfs 14.09.2014 21:36

Пример объекта datetime, учитывающего часовой пояс Django.

import datetime
from django.utils.timezone import get_current_timezone
tz = get_current_timezone()

format = '%b %d %Y %I:%M%p'
date_object = datetime.datetime.strptime('Jun 1 2005  1:33PM', format)
date_obj = tz.localize(date_object)

Это преобразование очень важно для Django и Python, когда у вас есть USE_TZ = True:

RuntimeWarning: DateTimeField MyModel.created received a naive datetime (2016-03-04 00:00:00) while time zone support is active.

Помните об этом, и вам не нужно снова запутываться при преобразовании даты и времени.

Строка для объекта datetime = strptime

объект datetime в другие форматы = strftime

Jun 1 2005 1:33PM

равно

%b %d %Y %I:%M%p

%b Month as locale’s abbreviated name(Jun)

%d Day of the month as a zero-padded decimal number(1)

%Y Year with century as a decimal number(2015)

%I Hour (12-hour clock) as a zero-padded decimal number(01)

%M Minute as a zero-padded decimal number(33)

%p Locale’s equivalent of either AM or PM(PM)

поэтому вам нужно strptime i-e, конвертирующий string в

>>> dates = []
>>> dates.append('Jun 1 2005  1:33PM')
>>> dates.append('Aug 28 1999 12:00AM')
>>> from datetime import datetime
>>> for d in dates:
...     date = datetime.strptime(d, '%b %d %Y %I:%M%p')
...     print type(date)
...     print date
... 

Выход

<type 'datetime.datetime'>
2005-06-01 13:33:00
<type 'datetime.datetime'>
1999-08-28 00:00:00

Что делать, если у вас другой формат дат, вы можете использовать panda или dateutil.parse

>>> import dateutil
>>> dates = []
>>> dates.append('12 1 2017')
>>> dates.append('1 1 2017')
>>> dates.append('1 12 2017')
>>> dates.append('June 1 2017 1:30:00AM')
>>> [parser.parse(x) for x in dates]

Выход

[datetime.datetime(2017, 12, 1, 0, 0), datetime.datetime(2017, 1, 1, 0, 0), datetime.datetime(2017, 1, 12, 0, 0), datetime.datetime(2017, 6, 1, 1, 30)]

% S для секунд в десятичном формате

optimist 09.06.2017 08:42

Не сломается ли %b, если вы проанализируете дату на английском языке на машине, на которой нет английского языка?

bfontaine 08.05.2018 12:44

Вы можете использовать easy_date, чтобы упростить:

import date_converter
converted_date = date_converter.string_to_datetime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')

Вот два решения с использованием Pandas для преобразования дат, отформатированных как строки, в объекты datetime.date.

import pandas as pd

dates = ['2015-12-25', '2015-12-26']

# 1) Use a list comprehension.
>>> [d.date() for d in pd.to_datetime(dates)]
[datetime.date(2015, 12, 25), datetime.date(2015, 12, 26)]

# 2) Convert the dates to a DatetimeIndex and extract the python dates.
>>> pd.DatetimeIndex(dates).date.tolist()
[datetime.date(2015, 12, 25), datetime.date(2015, 12, 26)]

Сроки

dates = pd.DatetimeIndex(start='2000-1-1', end='2010-1-1', freq='d').date.tolist()

>>> %timeit [d.date() for d in pd.to_datetime(dates)]
# 100 loops, best of 3: 3.11 ms per loop

>>> %timeit pd.DatetimeIndex(dates).date.tolist()
# 100 loops, best of 3: 6.85 ms per loop

И вот как преобразовать исходные примеры даты и времени OP:

datetimes = ['Jun 1 2005  1:33PM', 'Aug 28 1999 12:00AM']

>>> pd.to_datetime(datetimes).to_pydatetime().tolist()
[datetime.datetime(2005, 6, 1, 13, 33), 
 datetime.datetime(1999, 8, 28, 0, 0)]

Существует множество вариантов преобразования строк в метки времени Pandas с использованием to_datetime, поэтому проверьте документы, если вам нужно что-то особенное.

Точно так же метки времени имеют много свойства и методы, к которым можно получить доступ в дополнение к .date.

In [34]: import datetime

In [35]: _now = datetime.datetime.now()

In [36]: _now
Out[36]: datetime.datetime(2016, 1, 19, 9, 47, 0, 432000)

In [37]: print _now
2016-01-19 09:47:00.432000

In [38]: _parsed = datetime.datetime.strptime(str(_now),"%Y-%m-%d %H:%M:%S.%f")

In [39]: _parsed
Out[39]: datetime.datetime(2016, 1, 19, 9, 47, 0, 432000)

In [40]: assert _now == _parsed

Создайте небольшую служебную функцию, например:

def date(datestr = "", format = "%Y-%m-%d"):
    from datetime import datetime
    if not datestr:
        return datetime.today().date()
    return datetime.strptime(datestr, format).date()

Это достаточно универсально:

  • Если вы не передадите никаких аргументов, он вернет сегодняшнюю дату.
  • По умолчанию используется формат даты, который вы можете изменить.
  • Вы можете легко изменить его, чтобы он возвращал дату и время.
format - это зарезервированное слово в Python, которое не должно использоваться в качестве имени переменной.
shredding 10.01.2017 12:30

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

>>> import arrow
>>> dateStrings = [ 'Jun 1  2005 1:33PM', 'Aug 28 1999 12:00AM' ]
>>> for dateString in dateStrings:
...     dateString
...     arrow.get(dateString.replace('  ',' '), 'MMM D YYYY H:mmA').datetime
...     arrow.get(dateString.replace('  ',' '), 'MMM D YYYY H:mmA').format('ddd, Do MMM YYYY HH:mm')
...     arrow.get(dateString.replace('  ',' '), 'MMM D YYYY H:mmA').humanize(locale='de')
...
'Jun 1  2005 1:33PM'
datetime.datetime(2005, 6, 1, 13, 33, tzinfo=tzutc())
'Wed, 1st Jun 2005 13:33'
'vor 11 Jahren'
'Aug 28 1999 12:00AM'
datetime.datetime(1999, 8, 28, 0, 0, tzinfo=tzutc())
'Sat, 28th Aug 1999 00:00'
'vor 17 Jahren'

Подробнее см. http://arrow.readthedocs.io/en/latest/.

См. мой ответ.

В реальных данных это настоящая проблема: множественные, несовпадающие, неполные, несовместимые и многоязычные / региональные форматы даты, часто свободно смешанные в одном наборе данных. Это не нормально, когда производственный код терпит неудачу, не говоря уже о том, чтобы быть довольным исключениями, как лиса.

Нам нужно попробовать ... поймать несколько форматов даты и времени fmt1, fmt2, ..., fmtn и подавить / обработать исключения (из strptime()) для всех тех, которые не соответствуют (и, в частности, избежать нужды в нелепой лестнице с глубоким отступом n). try..catch clauses). От мое решение

def try_strptime(s, fmts=['%d-%b-%y','%m/%d/%Y']):
    for fmt in fmts:
        try:
            return datetime.strptime(s, fmt)
        except:
            continue

    return None # or reraise the ValueError if no format matched, if you prefer

В вопросе ничего не говорилось о «множественных, несовпадающих, неполных, несовместимых и многоязычных / региональных форматах даты» и т. д. Это может быть реальной проблемой, но здесь не актуально.

RoG 02.10.2018 15:28

@RoG: Он никогда не говорил, что это не так, и подразумевал, что они были: "огромный список ... база данных". Практически в каждой базе данных / файле журнала, с которым я работал (даже небольшого размера), было несколько форматов даты, идентификаторы часовых поясов, MM-DD и т. д. он не получает ожидаемого формата (даже возврат None или "" более приемлем). Отсюда необходимость в нескольких форматах. Следовательно, это действительно отвечает на заданный вопрос, и я потратил немного времени на выяснение самого Pythonic способа обработки ошибок из нескольких форматов.

smci 02.10.2018 22:38

«огромный список ... база данных» просто означает, что их много, а не то, что все они разных форматов. Вполне допустимо написать код, который читает один формат, если вы знаете, что на входе есть один формат. В этом случае произойдет сбой, если будет передано что-то не в правильном формате.

RoG 03.10.2018 10:28

@RoG: недопустимо писать производственный код, который дает сбой из-за неправильного формата / искаженного Unicode / усеченного / отсутствующего / данных, NaN, M / D / Y против формата D / M / Y, YY против YYYY и т. д. Как я показал, исключения можно избежать с помощью семистрочного решения. Большинство реальных «огромных баз данных» таковы. Просто потому, что OP явно не сказал, что это не типичный контекст. Я не собираюсь ссориться с тобой. С какими наборами данных вы работаете и почему вы думаете, что эти предположения разумны? Если только мы не говорим только об игрушечном коде, который требует постоянного вмешательства.

smci 25.06.2019 22:36

Хорошо, я сказал «сбой» вместо «вызвать исключение», но в остальном я придерживаюсь своей точки зрения. Есть много случаев, когда используется / требуется единый негибкий формат, иначе вы получите ошибки (6 июля или 7 июня?). Если ввод не соответствует формату, решение - не гадать. Если вам нужен конкретный пример, чтение текстовых журналов с отметками времени, где журналы были созданы компьютером. Ваше мнение о реальных данных, нуждающихся в очистке, имеет место, но я не думаю, что оно имеет место в контексте этого вопроса.

RoG 03.07.2019 16:43

Кажется немного глупым предполагать с полной уверенностью, что OP должен иметь данные, которые никогда не имеют несоответствий. Да, такие данные могут быть, но нет, мы не можем предположить, что здесь так. Я подумал, что этот ответ был полезен, особенно для меня, который искал похожие ответы на очень похожий вопрос, где несоответствия определенно являются проблемой.

Paul Miller 14.02.2020 19:52

Если вам нужен только формат даты, вы можете вручную преобразовать его, передав свои отдельные поля, например:

>>> import datetime
>>> date = datetime.date(int('2017'),int('12'),int('21'))
>>> date
datetime.date(2017, 12, 21)
>>> type(date)
<type 'datetime.date'>

Вы можете передать значения разделенной строки, чтобы преобразовать их в тип даты, например:

selected_month_rec = '2017-09-01'
date_formate = datetime.date(int(selected_month_rec.split('-')[0]),int(selected_month_rec.split('-')[1]),int(selected_month_rec.split('-')[2]))

Вы получите результат в формате даты.

Мне лично нравится решение, использующее модуль parser, который является вторым ответом на этот вопрос и красивым, поскольку вам не нужно создавать какие-либо строковые литералы, чтобы заставить его работать. НО, один недостаток в том, что это На 90% медленнее, чем принятый ответ с strptime.

from dateutil import parser
from datetime import datetime
import timeit

def dt():
    dt = parser.parse("Jun 1 2005  1:33PM")
def strptime():
    datetime_object = datetime.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')

print(timeit.timeit(stmt=dt, number=10**5))
print(timeit.timeit(stmt=strptime, number=10**5))
>10.70296801342902
>1.3627995655316933

Пока вы не делаете это миллион раз за разом, я все же думаю, что метод parser более удобен и будет обрабатывать большую часть форматов времени автоматически.

Это было бы полезно для преобразования строки в datetime, а также с часовым поясом

def convert_string_to_time(date_string, timezone):
    from datetime import datetime
    import pytz
    date_time_obj = datetime.strptime(date_string[:26], '%Y-%m-%d %H:%M:%S.%f')
    date_time_obj_timezone = pytz.timezone(timezone).localize(date_time_obj)

    return date_time_obj_timezone

date = '2018-08-14 13:09:24.543953+00:00'
TIME_ZONE = 'UTC'
date_time_obj_timezone = convert_string_to_time(date, TIME_ZONE)
emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv")
emp.info()

он показывает столбец «Дата начала» и «Время последнего входа в систему», оба являются «объект = строки» во фрейме данных.

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 8 columns):
First Name           933 non-null object
Gender               855 non-null object
Start Date           1000 non-null object

Last Login Time      1000 non-null object
Salary               1000 non-null int64
Bonus %              1000 non-null float64
Senior Management    933 non-null object
Team                 957 non-null object
dtypes: float64(1), int64(1), object(6)
memory usage: 62.6+ KB

Используя опцию parse_dates в read_csv, вы можете преобразовать строку datetime в формат даты и времени pandas.

emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv", parse_dates=["Start Date", "Last Login Time"])
emp.info()


<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 8 columns):
First Name           933 non-null object
Gender               855 non-null object
Start Date           1000 non-null datetime64[ns]
Last Login Time      1000 non-null datetime64[ns]
Salary               1000 non-null int64
Bonus %              1000 non-null float64
Senior Management    933 non-null object
Team                 957 non-null object
dtypes: datetime64[ns](2), float64(1), int64(1), object(4)
memory usage: 62.6+ KB

питон> = 3,7

для преобразования строки ГГГГ-ММ-ДД в объект datetime можно использовать datetime.fromisoformat.

from datetime import datetime

date_string = "2012-12-12 10:10:10"
print (datetime.fromisoformat(date_string))
2012-12-12 10:10:10

Вы также можете проверить dateparser

dateparser provides modules to easily parse localized dates in almost any string formats commonly found on web pages.

Установить:

$ pip install dateparser

Думаю, это самый простой способ разбирать даты.

The most straightforward way is to use the dateparser.parse function, that wraps around most of the functionality in the module.

Образец кода:

import dateparser

t1 = 'Jun 1 2005  1:33PM'
t2 = 'Aug 28 1999 12:00AM'

dt1 = dateparser.parse(t1)
dt2 = dateparser.parse(t2)

print(dt1)
print(dt2)

Выход:

2005-06-01 13:33:00
1999-08-28 00:00:00

Кажется, использование метка времени панды - самый быстрый

import pandas as pd 

N = 1000

l = ['Jun 1 2005  1:33PM'] * N

list(pd.to_datetime(l, format=format))

%timeit _ = list(pd.to_datetime(l, format=format))
1.58 ms ± 21.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Другие решения

from datetime import datetime
%timeit _ = list(map(lambda x: datetime.strptime(x, format), l))
9.41 ms ± 95.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

from dateutil.parser import parse
%timeit _ = list(map(lambda x: parse(x), l))
73.8 ms ± 1.14 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Если строка является строкой ISO8601, используйте csio8601

import ciso8601

l = ['2014-01-09'] * N

%timeit _ = list(map(lambda x: ciso8601.parse_datetime(x), l))
186 µs ± 4.13 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Если ваша строка имеет формат ISO8601 и у вас установлен Python 3.7+, вы можете использовать следующий простой код:

import datetime.date

aDate = datetime.date.fromisoformat('2020-10-04')

для свиданий и

import datetime.datetime

aDateTime = datetime.datetime.fromisoformat('2020-10-04 22:47:00')

для строк, содержащих дату и время. Если временные метки включены, функция datetime.datetime.isoformat() поддерживает следующий формат

YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]]

где * соответствует любому одиночному символу. См. Также здесь и здесь.

Краткий пример сопоставления строки даты yyyy-mm-dd с объектом datetime.date:

from datetime import date
date_from_yyyy_mm_dd = lambda δ : date(*[int(_) for _ in δ.split('-')])
date_object = date_from_yyyy_mm_dd('2021-02-15')

Другие вопросы по теме