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

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

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

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

2343
Oli 21 Янв 2009 в 21:00

20 ответов

Лучший ответ

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

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 месяцев.
3332
user2357112 supports Monica 28 Апр 2018 в 06:17

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

>>> 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/.

8
Peter Mortensen 23 Май 2018 в 23:02

Вот два решения, использующие 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

А вот как конвертировать оригинальные примеры даты и времени ОП:

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, поэтому проверьте docs, если вам нужно что-то особенное.

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

27
Alexander 2 Дек 2017 в 07:08

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

import date_converter
converted_date = date_converter.string_to_datetime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')
6
Raphael Amoedo 1 Июн 2015 в 15:15

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

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)
11
Kanish Mathew 30 Авг 2018 в 05:49

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

dateparser предоставляет модули для простого анализа локализованных дат практически любые строковые форматы, обычно встречающиеся на веб-страницах.

< EM> Установка:

$ pip install dateparser

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

Самый простой способ - использовать функцию dateparser.parse, это охватывает большую часть функциональности в модуле.

Пример кода:

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
0
Bilesh Ganguly 12 Янв 2020 в 17:55

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

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"))​​​​​​​
23
Aram Kocharyan 14 Окт 2011 в 00:28

Многие временные метки имеют подразумеваемый часовой пояс. Чтобы ваш код работал в каждом часовом поясе, вы должны использовать 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)))
31
Janus Troelsen 5 Июн 2015 в 12:34

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

>>> 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]))

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

3
Peter Mortensen 23 Май 2018 в 23:04

Пример объекта с датой и временем в 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.
15
Tarek Kalaji 3 Мар 2016 в 13:44

Посетите strptime в time. Это обратное 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)
482
Ramast 7 Фев 2020 в 22:11

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

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

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))
107
Bruno Bronosky 29 Дек 2016 в 19:33
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 datetime format.

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
0
Riz.Khan 1 Янв 2019 в 12:17

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

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

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

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
0
smci 5 Сен 2018 в 15:52

В Python> = 3.7.0,

Чтобы преобразовать строку YYYY-MM-DD в объект 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
40
SuperNova 22 Фев 2019 в 15:35

Мне лично нравится решение, использующее модуль 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 более удобен и будет обрабатывать большинство форматов времени автоматически.

24
user1767754 1 Янв 2019 в 01:50

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

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

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

  • Если вы не передадите аргументы, будет возвращена сегодняшняя дата.
  • По умолчанию есть формат даты, который вы можете переопределить.
  • Вы можете легко изменить его, чтобы вернуть дату и время.
11
Peter Mortensen 23 Май 2018 в 23:00

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

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

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

Jun 1 2005 1:33PM

Равно

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

% b Месяц как сокращенное название локали (июнь)

% d День месяца в виде десятичного числа с нулем (1)

% Y Год с веком в виде десятичного числа (2015)

% I час (12-часовые часы) как десятичное число с нулем (01)

% M Минута как десятичное число с добавлением нуля (33)

% p Локальный эквивалент AM или PM (PM)

Так что вам нужно strptime я-е преобразование 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)]
50
Rizwan Mumtaz 30 Янв 2017 в 07:20

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

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

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

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

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

pip install python-dateutil
793
Boris 8 Окт 2019 в 23:20
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
15
guneysus 19 Янв 2016 в 07:48