Преобразование строки в дату и время
У меня есть огромный список таких дат в виде строк:
Jun 1 2005 1:33PM
Aug 28 1999 12:00AM
Я собираюсь перенести их обратно в надлежащие поля даты и времени в базе данных, поэтому мне нужно преобразовать их в реальные объекты даты и времени.
Это происходит через Django ORM, поэтому я не могу использовать SQL для преобразования при вставке.
Ответы
Ответ 1
datetime.strptime
- основная процедура для разбора строк в datetime. Он может обрабатывать всевозможные форматы, формат которых определяется строкой формата, которую вы даете:
from datetime import datetime
datetime_object = datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p')
Результирующий объект datetime
является наименее часовым.
Ссылки:
Заметки:
-
strptime
= "время разбора строки" -
strftime
= "string format time" - Произносите его вслух сегодня, и вам не придется искать его снова через 6 месяцев.
Ответ 2
Используйте стороннюю библиотеку dateutil :
from dateutil import parser
parser.parse("Aug 28 1999 12:00AM") # datetime.datetime(1999, 8, 28, 0, 0)
Он может работать с большинством форматов дат, включая тот, который вам нужен для анализа. Это удобнее, чем strptime
, так как большую часть времени он может угадать правильный формат.
Это очень полезно для написания тестов, где удобочитаемость важнее производительности.
Вы можете установить его с помощью:
pip install python-dateutil
Ответ 3
Отметьте strptime в time. Это инверсия strftime.
$ python
>>> import 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)
Ответ 4
Я собрал проект, который может преобразовать некоторые действительно аккуратные выражения. Проверьте 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))
Ответ 5
Помните об этом, и вам не нужно было снова запутываться в преобразовании даты и времени.
String to datetime object = strptime
объект datetime для других форматов = strftime
Jun 1 2005 1:33PM
равно
%b %d %Y %I:%M%p
% b Месяц по сокращенному имени локалей (июнь)
% d День месяца как десятичное число с нулевым запасом (1)
% Y Год со столетием как десятичное число (2015)
% я Час (12-часовые часы) в виде десятичного числа с нулевой задержкой (01)
% M Минута как десятичное число с нулевым запасом (33)
% p Локальный эквивалент AM или PM (PM)
так что вам нужно преобразовать i-e 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)]
Ответ 6
У многих временных меток есть подразумеваемый часовой пояс. Чтобы ваш код работал в каждом часовом поясе, вы должны использовать 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)))
Ответ 7
Вот два решения, использующие 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
есть много свойств и методов, которые могут быть доступны в дополнение к .date
Ответ 8
В Python> = 3.7.0,
чтобы преобразовать строку ГГГГ-ММ-ДД в объект datetime.fromisoformat
можно использовать 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
Ответ 9
Что-то, что здесь не упоминается и полезно: добавление суффикса к дню. Я отделил логику суффиксов, чтобы вы могли использовать ее для любого числа, которое вам нравится, а не только для дат.
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"))
Ответ 10
Мне лично нравится решение, использующее модуль 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
более удобен и будет обрабатывать большинство форматов времени автоматически.
Ответ 11
Пример события datetime, связанного с часовым поясом Django Timezone.
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.
Ответ 12
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
Ответ 13
для формата unix/mysql 2018-10-15 20:59:29
from datetime import datetime
datetime_object = datetime.strptime('2018-10-15 20:59:29', '%Y-%m-%d %H:%M:%S')
Ответ 14
Создайте небольшую функцию полезности, например:
def date(datestr="", format="%Y-%m-%d"):
from datetime import datetime
if not datestr:
return datetime.today().date()
return datetime.strptime(datestr, format).date()
Это достаточно универсально:
- Если вы не пройдете никаких аргументов, она вернет сегодняшнюю дату.
- Есть формат даты по умолчанию, который вы можете переопределить.
- Вы можете легко изменить его, чтобы вернуть дату и время.
Ответ 15
Модуль Python datetime хорош для получения дат и преобразования форматов даты.
import datetime
new_date_format1 = datetime.datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p')
new_date_format2 = datetime.datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p').strftime('%Y/%m/%d %I:%M%p')
print new_date_format1
print new_date_format2
Вывод:
2005-06-01 13:33:00
2005/06/01 01:33PM
Ответ 16
arrow предлагает множество полезных функций для дат и времени. Этот бит кода дает ответ на вопрос и показывает, что стрелка также способна легко форматировать даты и отображать информацию для других локалей.
>>> 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/ для получения дополнительной информации.
Ответ 17
Это будет полезно для преобразования строки в дату и время, а также с часовым поясом
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)
Ответ 18
Вы можете использовать easy_date, чтобы упростить его:
import date_converter
converted_date = date_converter.string_to_datetime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p')
Ответ 19
Если вы хотите только формат даты, вы можете вручную преобразовать его, передав свои отдельные поля, например:
>>> 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]))
Вы получите итоговое значение в формате даты.
Ответ 20
(ММ ДД ГГГГ ЧЧ: ММ) Формат
import date_converter
converted_date = date_converter.string_to_datetime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p')
Ответ 21
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 в формат панд даты и времени.
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
Ответ 22
Вы также можете использовать утенка Facebook.
Попробуйте это онлайн здесь: https://duckling.wit.ai/
Для библиотеки есть оболочка python: pip install duckling
Он поддерживает гораздо больше, чем только разбор времени.
Ответ 23
См. Мой ответ.
В реальных данных это реальная проблема: множественные, несоответствующие, неполные, непоследовательные и многоязычные/региональные форматы даты, часто смешанные свободно в одном наборе данных. Это не нормально, когда производственный код терпит неудачу, не говоря уже о том, чтобы сделать исключение счастливым, как лиса.
Нам нужно попытаться... уловить несколько форматов datetime fmt1, fmt2,..., fmtn и подавить/обработать исключения (из strptime()
) для всех несоответствующих (и, в частности, избегать использования yukky n-deep indented лестница предложений 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