将字符串“June 1 2005 1:33PM”转换为datetime

如何将以下字符串转换为#0对象?

"Jun 1 2005  1:33PM"
4442661 次浏览

查看时间模块中的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 datetimefrom datetime import datetimemy_datetime = datetime.fromtimestamp(timestamp)# convert time object to datefrom datetime import datemy_date = date.fromtimestamp(timestamp)

#0将用户指定格式的输入字符串解析为时区错误#1对象:

>>> from datetime import datetime>>> datetime.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')datetime.datetime(2005, 6, 1, 13, 33)

要使用现有的datetime对象获取#0对象,请使用.date()进行转换:

>>> datetime.strptime('Jun 1 2005', '%b %d %Y').date()date(2005, 6, 1)

链接:

备注:

  • strptime="字符串解析时间"
  • strftime="字符串格式时间"

使用第三方#0库:

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

它可以处理大多数日期格式,并且比strptime更方便,因为它通常猜测正确的格式。它对于编写测试也非常有用,其中易读性比性能更重要。

安装它:

pip install python-dateutil

这里没有提到但很有用的东西:为day添加后缀。我解耦了后缀逻辑,因此您可以将其用于任何您喜欢的数字,而不仅仅是日期。

import time
def num_suffix(n):'''Returns the suffix for any given int'''suf = ('th','st', 'nd', 'rd')n = abs(n) # wise guytens = int(str(n)[-2:])units = n % 10if 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)
# Examplesprint 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').datedatetime.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))

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

这假设您知道偏移量。如果您不知道,但您知道例如位置,您可以使用pytz包向IANA时区数据库查询偏移量。我将在这里使用德黑兰作为示例,因为它有半小时偏移量:

>>> tehran = pytz.timezone("Asia/Tehran")>>> local_time = tehran.localize(...   datetime.datetime.strptime("March 5, 2014, 20:13:50",...                              "%B %d, %Y, %H:%M:%S")... )>>> local_timedatetime.datetime(2014, 3, 5, 20, 13, 50, tzinfo=<DstTzInfo 'Asia/Tehran' +0330+3:30:00 STD>)

如您所见,pytz已确定该特定日期的偏移量为+3:30。您现在可以将其转换为UTC时间,它将应用偏移量:

>>> utc_time = local_time.astimezone(pytz.utc)>>> utc_timedatetime.datetime(2014, 3, 5, 16, 43, 50, tzinfo=<UTC>)

请注意,采用时区之前的日期会给你奇怪的偏移。这是因为IANA决定使用当地平均时间

>>> chicago = pytz.timezone("America/Chicago")>>> weird_time = chicago.localize(...   datetime.datetime.strptime("November 18, 1883, 11:00:00",...                              "%B %d, %Y, %H:%M:%S")... )>>> weird_time.astimezone(pytz.utc)datetime.datetime(1883, 11, 18, 7, 34, tzinfo=<UTC>)

奇怪的“7小时34分钟”来自芝加哥的经度。我使用这个时间戳是因为它正好在芝加哥采用了标准时间之前。

Django时区感知日期时间对象示例。

import datetimefrom django.utils.timezone import get_current_timezonetz = 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)

当您有USE_TZ = True时,这种转换对于Django和Python非常重要:

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月作为区域设置的缩写名称(6月)

%d以填充零的十进制数表示的月份的日(1)

%Y年份,世纪为十进制数(2015)

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

%M分钟作为补零的十进制数(33)

%p Locale相当于AM或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

如果你有不同格式的日期,你可以使用熊猫或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)]

您可以使用easy_date使其更容易:

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

有许多选项可以使用to_datetime将字符串转换为熊猫时间戳,因此如果您需要任何特殊内容,请检查文档

同样,时间戳有许多性质和方法可以访问除了.date

In [34]: import datetime
In [35]: _now = datetime.datetime.now()
In [36]: _nowOut[36]: datetime.datetime(2016, 1, 19, 9, 47, 0, 432000)
In [37]: print _now2016-01-19 09:47:00.432000
In [38]: _parsed = datetime.datetime.strptime(str(_now),"%Y-%m-%d %H:%M:%S.%f")
In [39]: _parsedOut[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 datetimeif not datestr:return datetime.today().date()return datetime.strptime(datestr, format).date()

这是足够灵活的:

  • 如果您不传递任何参数,它将返回今天的日期。
  • 有一个默认的日期格式,你可以覆盖。
  • 您可以轻松修改它以返回日期时间。

箭头为日期和时间提供了许多有用的函数。这段代码提供了问题的答案,并表明箭头还能够轻松格式化日期并显示其他语言环境的信息。

>>> 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… cat子句)。从我的解决方案

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

如果您只想要日期格式,那么您可以通过传递您的各个字段手动转换它,例如:

>>> import datetime>>> date = datetime.date(int('2017'),int('12'),int('21'))>>> datedatetime.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模块的解决方案,这是这个问题的第二个答案,而且很漂亮,因为您不必构造任何字符串文字来使其工作。

from dateutil import parserfrom datetime import datetimeimport 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 datetimeimport 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 999Data columns (total 8 columns):First Name           933 non-null objectGender               855 non-null object
Start Date           1000 non-null object
Last Login Time      1000 non-null object
Salary               1000 non-null int64Bonus %              1000 non-null float64Senior Management    933 non-null objectTeam                 957 non-null objectdtypes: float64(1), int64(1), object(6)memory usage: 62.6+ KB

通过使用read_csv提及中的parse_dates选项,您可以将字符串日期时间转换为熊猫日期时间格式。

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 999Data columns (total 8 columns):First Name           933 non-null objectGender               855 non-null object
Start Date           1000 non-null datetime64[ns]Last Login Time      1000 non-null datetime64[ns]
Salary               1000 non-null int64Bonus %              1000 non-null float64Senior Management    933 non-null objectTeam                 957 non-null objectdtypes: datetime64[ns](2), float64(1), int64(1), object(4)memory usage: 62.6+ KB

Python>=3.7

要将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

留档注意事项:

这确实没有支持解析任意ISO 8601字符串-它仅用于#0的反向操作。第三方软件包#2中提供了功能更全面的ISO 8601解析器dateutil.parser.isoparse

您还可以查看#0

#0提供了模块来轻松解析本地化日期网页上常见的任何字符串格式。

安装:

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:001999-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
aDate = datetime.date.fromisoformat('2020-10-04')

的日期和

import 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 datedate_from_yyyy_mm_dd = lambda δ : date(*[int(_) for _ in δ.split('-')])date_object = date_from_yyyy_mm_dd('2021-02-15')

如果您不要想要显式指定您的字符串相对于日期时间格式的格式,您可以使用此hack通过该步骤:

from dateutil.parser import parse
# Function that'll guess the format and convert it into the python datetime formatdef update_event(start_datetime=None, end_datetime=None, description=None):if start_datetime is not None:new_start_time = parse(start_datetime)
return new_start_time
# Sample input dates in different formatsd = ['06/07/2021 06:40:23.277000', '06/07/2021 06:40', '06/07/2021']
new = [update_event(i) for i in d]
for date in new:print(date)# Sample output dates in Python datetime object#   2014-04-23 00:00:00#   2013-04-24 00:00:00#   2014-04-25 00:00:00

如果您想将其转换为其他日期时间格式,只需使用您喜欢的格式修改最后一行,例如date.strftime('%Y/%m/%d %H:%M:%S.%f')

from dateutil.parser import parse
def update_event(start_datetime=None, end_datetime=None, description=None):if start_datetime is not None:new_start_time = parse(start_datetime)
return new_start_time
# Sample input dates in different formatsd = ['06/07/2021 06:40:23.277000', '06/07/2021 06:40', '06/07/2021']
# Passing the dates one by one through the functionnew = [update_event(i) for i in d]
for date in new:print(date.strftime('%Y/%m/%d %H:%M:%S.%f'))# Sample output dates in required Python datetime object#   2021/06/07 06:40:23.277000#   2021/06/07 06:40:00.000000#   2021/06/07 00:00:00.000000

尝试运行上面的代码片段以获得更好的清晰度。

Javed的回答类似,我只是想要字符串中的日期-因此结合西蒙的和Javed的逻辑,我们得到:

from dateutil import parserimport datetime
s = '2021-03-04'
parser.parse(s).date()

产出

datetime.date(2021, 3, 4)

#Convert String to datetime>>> x=datetime.strptime('Jun 1 2005', '%b %d %Y').date()>>> print(x,type(x))2005-06-01 00:00:00 <class 'datetime.datetime'>

#Convert datetime to String (Reverse above process)>>> y=x.strftime('%b %d %Y')>>> print(y,type(y))Jun 01 2005 <class 'str'>