将字符串“Jun 1 2005 1:33PM”转换为日期时间
- 2024-11-18 08:40:00
- admin 原创
- 10
问题描述:
我有一个巨大的日期时间字符串列表,如下所示
["Jun 1 2005 1:33PM", "Aug 28 1999 12:00AM"]
我如何将它们转换成datetime
对象?
解决方案 1:
datetime.strptime
将用户指定格式的输入字符串解析为时区未知的 datetime
对象:
>>> from datetime import datetime
>>> datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p')
datetime.datetime(2005, 6, 1, 13, 33)
date
要使用现有对象获取对象datetime
,请使用以下命令进行转换.date()
:
>>> datetime.strptime('Jun 1 2005', '%b %d %Y').date()
date(2005, 6, 1)
链接:
strptime
文档:Python 2、Python 3strptime
/strftime
格式字符串文档:Python 2、Python 3strftime.org格式字符串备忘单
笔记:
strptime
=“字符串解析时间”strftime
=“字符串格式时间”
解决方案 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 。它是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)
解决方案 4:
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 字符串 - 它仅用作 的逆操作。第三方包 中提供了
datetime.isoformat()
功能更全面的 ISO 8601 解析器。dateutil.parser.isoparse
`dateutil`
解决方案 5:
我已经组织了一个可以转换一些非常简洁的表达式的项目。请查看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))
解决方案 6:
记住这一点,您就不必再对日期时间转换感到困惑。
字符串到日期时间对象 =strptime
datetime 对象转换为其他格式 =strftime
Jun 1 2005 1:33PM
等于
%b %d %Y %I:%M%p
%b 月份作为语言环境的缩写名称(Jun)
%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)]
解决方案 7:
许多时间戳都有隐含的时区。为了确保您的代码在每个时区都能正常工作,您应该在内部使用 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_time
datetime.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_time
datetime.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 分钟”来自芝加哥经度。我使用这个时间戳是因为它正好在芝加哥采用标准时间之前。
解决方案 8:
如果您的字符串是ISO 8601格式并且您拥有 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]]]]
匹配任意*
单个字符。另请参阅此处和此处。
解决方案 9:
我个人喜欢使用模块的解决方案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
方法更方便,并且会自动处理大多数时间格式。
解决方案 10:
这里有两种使用 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 Timestamps to_datetime
,因此如果您有任何特殊需要,请查看文档。
同样,时间戳除了具有以下属性和方法外,还具有许多可访问的属性和方法:.date
解决方案 11:
这里没有提到但很有用的东西:为日期添加后缀。我解耦了后缀逻辑,这样您就可以将其用于任何您喜欢的数字,而不仅仅是日期。
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"))
解决方案 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:
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.
解决方案 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:
这对于将字符串转换为日期时间以及时区很有帮助:
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)
解决方案 16:
arrow提供了许多有用的日期和时间函数。这段代码回答了这个问题,并表明 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:
您还可以查看dateparser
:
dateparser
提供模块来轻松解析网页上常见的几乎所有字符串格式的本地化日期。
安装:
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
解决方案 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:
与Javed 的回答类似,我只是想要从字符串中获取日期 - 因此结合Simon和 Javed 的逻辑,我们得到:
from dateutil import parser
import datetime
s = '2021-03-04'
parser.parse(s).date()
输出
datetime.date(2021, 3, 4)
解决方案 21:
似乎使用pandas Timestamp是最快的:
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)
如果字符串是ISO 8601字符串,请使用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)
解决方案 22:
如果您不想明确指定字符串相对于日期时间格式的格式,则可以使用此技巧来绕过该步骤:
from dateutil.parser import parse
# Function that'll guess the format and convert it into the python datetime format
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 formats
d = ['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 formats
d = ['06/07/2021 06:40:23.277000', '06/07/2021 06:40', '06/07/2021']
# Passing the dates one by one through the function
new = [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
尝试运行上述代码片段以获得更清晰的理解。
解决方案 23:
请参阅我的回答。
在实际数据中,这是一个真正的问题:多个、不匹配、不完整、不一致和多语言/地区日期格式,通常在一个数据集中自由混合。生产代码失败是不允许的,更不用说像狐狸一样出现异常。
我们需要尝试...捕获多个日期时间格式 fmt1、fmt2、...、fmtn,并抑制/处理strptime()
所有不匹配的异常(来自)(特别是,避免需要一个令人讨厌的 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
解决方案 24:
将 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')
解决方案 25:
使用:
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
,您可以将字符串日期时间转换为 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
解决方案 26:
您可以在https://strftime.org/查看所有可能的日期时间格式。
如果您有多个字符串需要转换为日期时间对象,则可以使用列表推导或 map datetime.strptime
。
from datetime import datetime
from itertools import repeat
from dateutil import parser
dates = ["Jun 1 2005 1:33PM", "Jun 3 2005 1:33PM"]
# use list comprehension
parsed_dates = [datetime.strptime(d, '%b %d %Y %I:%M%p') for d in dates]
# map the parser function
parsed_dates = list(map(datetime.strptime, dates, repeat('%b %d %Y %I:%M%p')))
# map parser.parse
parsed_dates = list(map(parser.parse, dates))
至少从 Python 3.10 开始,映射内置方法(例如)datetime.strptime
比列表推导更快。此外,值得一提的是,它dateutil.parser
比 慢约 7 倍,datetime.strptime
如果您需要解析许多日期时间字符串,这一点非常重要。
如果性能是一个问题,那么一个流行的第三方库pandas
提供了可以to_datetime
非常快速地解析日期时间字符串的函数。它比datetime.strptime
循环快 2 倍以上(即使您必须将 pandas 对象转换回 Python 列表)。它的一个好处是,在解析重复的日期字符串时,会缓存唯一的转换日期,因此速度会显著提高。在下面的示例中,包含重复日期时间字符串的列表的解析速度比包含唯一日期时间字符串的列表快 4 倍(因此比快 8 倍datetime.strptime
)。
import pandas as pd
dates = pd.date_range('2000', '2020', 1000000).strftime('%b %d %Y %I:%M%p').tolist()
%timeit _ = pd.to_datetime(dates, format='%b %d %Y %I:%M%p').tolist()
# 4.73 s ± 41.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit _ = [datetime.strptime(d, '%b %d %Y %I:%M%p') for d in dates]
# 9.73 s ± 48.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit _ = list(map(datetime.strptime, dates, repeat('%b %d %Y %I:%M%p')))
# 9.63 s ± 23.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# with duplicate dates, it's even faster
dates = pd.date_range('2000-1-1', '2000-1-2', 1000000).strftime('%b %d %Y %I:%M%p').tolist()
%timeit _ = pd.to_datetime(dates, format='%b %d %Y %I:%M%p').tolist()
# 1.16 s ± 8.11 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件