将字符串转换为日期时间

我有大量的日期时间列表,例如字符串:

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

我将把它们推回到数据库中正确的日期时间字段中,因此我需要将它们魔术化为实际的日期时间对象。

这是通过 Django 的 ORM 进行的,因此我无法使用 SQL 进行插入时的转换。

答案

datetime.strptime是将字符串解析为日期时间的主要例程。它可以处理各种格式,格式由您为其指定的格式字符串确定:

from datetime import datetime

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

所得的datetime对象为时区纯文本。

链接:

笔记:

  • strptime =“字符串解析时间”
  • strftime =“字符串格式时间”
  • 今天大声发音,您将在 6 个月内无需再次搜索。

使用第三方dateutil库:

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

它可以处理大多数日期格式,包括您需要解析的格式。它比strptime更方便,因为它可以在大多数时间猜测正确的格式。

这对于编写测试非常有用,在测试中,可读性比性能更重要。

您可以使用以下方法安装它:

pip install python-dateutil

时间模块中strptime 。它与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)

我整理了一个可以转换一些真正简洁的表达式的项目。查看时间字符串

以下是一些示例:

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

记住这一点,您无需再次对日期时间转换感到困惑。

日期时间对象的字符串 = strptime

datetime 对象为其他格式 = strftime

Jun 1 2005 1:33PM

等于

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

%b 月作为语言环境的缩写名称(六月)

%d 月中的一天,以零填充的十进制数字(1)

%Y 以世纪为十进制数字的年份(2015)

%I 小时(12 小时制),为零填充的十进制数字(01)

%M 分钟,为零填充的十进制数字(33)

等同于 AM 或 PM(PM)的%p 语言环境

所以你需要 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)]

在 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

许多时间戳都有一个隐含的时区。为了确保您的代码在每个时区都能工作,您应该在内部使用 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)))

这是两个使用 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)]

使用to_datetime将字符串从字符串转换为 Pandas Timestamps 的选项很多,因此,如果需要任何特殊信息,请检查文档

同样,时间戳除了.date之外,还具有许多可访问的属性和方法。

这里没有提到但有用的东西:在一天中添加一个后缀。我解耦了后缀逻辑,以便您可以将其用于任何您喜欢的数字,而不仅仅是日期。

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"))​​​​​​​

我个人喜欢使用parser模块的解决方案,它是此问题的第二个答案,而且很漂亮,因为您不必构造任何字符串文字即可使其工作。 但是 ,缺点是它比strptime接受的答案慢 90%

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方法更加方便,会自动处理大部分的时间格式。