在 Python 中处理日期和时间可能很麻烦。值得庆幸的是,有一种内置的方法可以让它变得更容易:Python datetime 模块。
datetime 帮助我们识别和处理与时间相关的元素,如日期、小时、分钟、秒、星期几、月份、年份等。它提供各种服务,如管理时区和夏令时。它可以处理时间戳数据。它可以从字符串中提取星期几、月份中的某一天以及其他日期和时间格式。
简而言之,它是处理 Python 中与日期和时间相关的任何内容的非常强大的方法。让我们开始吧!
在本教程中,我们将详细了解 Python 日期时间函数,包括:
创建日期对象 从日期获取年和月 从日期获取月日和工作日 从日期获取小时和分钟 从日期获取一年中的周数 将日期对象转换为时间戳 将 UNIX 时间戳字符串转换为日期对象 处理 timedelta 对象 获取两个日期和时间之间的差异 格式化日期:strftime() 和 strptime() 处理时区 使用 Pandas 日期时间对象获取年、月、日、小时和分钟获取工作日和一年中的某一天将日期对象转换为 Dataframe 索引 Python 日期时间类在开始编写代码之前,有必要了解一下datetime 模块中使用的五个主要对象类 。根据我们尝试做的事情,我们可能需要使用这些不同的类中的一个或多个:
datetime – 允许我们一起操作时间和日期(月、日、年、小时、秒、微秒)。 date – 允许我们独立于时间(月、日、年)操作日期。 time – 允许我们独立于日期(小时、分钟、秒、微秒)操纵时间。 timedelta — 用于操作日期和测量的持续时间。 tzinfo — 处理时区的抽象类。如果这些区别还没有意义,请不要担心!让我们深入研究 datetime 并开始使用它,以更好地了解这些是如何应用的。
创建日期对象首先,让我们仔细看看一个 datetime 对象。由于 datetime 既是模块又是该模块中的类,我们将从datetime 从datetime 模块中导入类 开始 。
然后,我们将打印当前日期和时间以仔细查看datetime 对象中包含的内容 。我们可以使用datetime的 .now() 函数来做到这一点 。我们将打印 datetime 对象,然后使用 using 打印其类型, type() 以便我们可以仔细查看。
# import datetime class from datetime modulefrom datetime import datetime# get current datedatetime_object = datetime.now()print(datetime_object)print(\\\'Type :- \\\',type(datetime_object))
2019-10-25 10:24:01.521881Type :-
从上面的结果我们可以看出datetime_object 确实是一个 类的 datetime 对象 datetime。这包括年、月、日、小时、分钟、秒和微秒。
从日期中提取年和月现在我们已经看到了是什么让一个 datetime 对象,我们可能已经猜到了如何 date 和 time 对象看,因为我们知道, date 物体就像 datetime 没有时间数据和 time 对象就像 datetime 没有最新数据。
我们也可以预见一些问题。例如,在大多数数据集中,日期和时间信息以字符串格式存储!此外,我们可能不 想要 所有这些日期和时间数据——如果我们正在做诸如每月销售分析之类的事情,那么以微秒为单位进行细分将不会很有用。
所以现在,让我们开始深入研究数据科学中的一个常见任务:使用 datetime.
为此,我们需要做一些事情。
使用 strptime() 和 strftime() 处理日期和时间字符串值得庆幸的是,datetime 包括两个方法, strptime() 和 strftime(),用于将对象从字符串转换为 datetime 对象,反之亦然。 strptime() 可以读取带有日期和时间信息的字符串并将它们转换为 datetime 对象, strftime() 并将日期时间对象转换回字符串。
当然, strptime() 这不是魔法——它不能将 任何 字符串转换为日期和时间,它需要我们的一些帮助来解释它所看到的!但它能够读取日期和时间数据的大多数传统字符串格式(有关更多详细信息,请参阅 文档)。让我们给它一个 YYYY-MM-DD 格式的日期字符串,看看它能做什么!
my_string = \\\'2019-10-31\\\'# Create date object in given time format yyyy-mm-ddmy_date = datetime.strptime(my_string, "%Y-%m-%d")print(my_date)print(\\\'Type: \\\',type(my_date))
2019-10-31 00:00:00 Type:
请注意,它strptime() 采用了两个参数:字符串 ( my_string) 和 “%Y-%m-%d”,另一个字符串告诉 strptime() 如何解释输入字符串 my_string。 %Y例如,告诉它期望字符串的前四个字符是年份。
文档中提供了这些模式的完整列表 ,我们将在本教程后面更深入地介绍这些方法。
您可能还注意到 00:00:00 日期中添加了时间。那是因为我们创建了一个 datetime 对象,其中必须包含日期 和 时间。 00:00:00 如果在我们输入的字符串中没有指定时间,则是默认时间。
无论如何,我们希望为我们的分析分离出日期的特定元素。一种方法可以使用 datetime 对象的内置类属性来做到这一点,例如 .month 或 .year:
print(\\\'Month: \\\', my_date.month) # To Get month from dateprint(\\\'Year: \\\', my_date.year) # To Get month from year
Month: 10 Year: 2019
从日期获取月份中的某天和一周中的某天 让我们再做一些提取,因为这是一项非常常见的任务。这一次,我们将尝试从 my_date. Datetime 将使用其.weekday() 函数为我们提供星期几作为数字,但我们可以使用calendar 模块和名为 的方法 将其 转换为文本格式(即星期一、星期二、星期三……) day_name。
我们将从导入开始 calendar,然后使用 .day 和 .weekday() on my_date。从那里,我们可以像这样以文本格式获取星期几:
# import calendar moduleimport calendarprint(\\\'Day of Month:\\\', my_date.day)# to get name of day(in number) from dateprint(\\\'Day of Week (number): \\\', my_date.weekday())# to get name of day from dateprint(\\\'Day of Week (name): \\\', calendar.day_name[my_date.weekday()])
Day of Month: 31 Day of Week (number): 3 Day of Week (name): Thursday
等等,这看起来有点奇怪!一周的第三天应该是周三,而不是周四吧?
让我们day_name 使用 for 循环仔细查看该 变量:
j = 0for i in calendar.day_name: print(j,\\\'-\\\',i) j+=1
0 - Monday 1 - Tuesday 2 - Wednesday 3 - Thursday 4 - Friday 5 - Saturday 6 - Sunday
现在我们可以看到 Python 从星期一开始,从索引 0 开始计数,而不是从 1 开始。所以数字 3 被转换为“星期四”是有道理的,正如我们上面看到的。
从 Python 日期时间对象获取小时和分钟现在让我们深入研究时间并从 datetime 对象中提取小时和分钟。就像我们用月和年以上了,我们就可以使用类属性 .hour ,并 .minute 拿到小时,一天分钟。
让我们使用该.now() 函数设置新的日期和时间 。在撰写本文时,时间是 2019 年 10 月 25 日上午 10:25。当然,根据您选择运行此代码的时间,您将获得不同的结果!
from datetime import datetime todays_date = datetime.now()# to get hour from datetimeprint(\\\'Hour: \\\', todays_date.hour)# to get minute from datetimeprint(\\\'Minute: \\\', todays_date.minute)
Hour: 10 Minute: 25
从日期时间对象获取一年中的一周 我们还可以用 datetime. 例如,如果我们想知道今年是哪一周怎么办?
我们可以datetime 使用该.isocalendar() 函数从对象中 获取年、年中的一周和一周中的哪一天 。
具体来说, isocalendar() 返回一个包含 ISO 年份、周数和工作日的元组。在 ISO日历 是基于公历广泛使用的标准日历。您可以在该链接上更详细地了解它,但出于我们的目的,我们只需要知道它作为一个常规日历工作,从每周一开始。
# Return a 3-tuple, (ISO year, ISO week number, ISO weekday).todays_date.isocalendar()
(2019, 43, 5)
请注意,在 ISO 日历中,一周从 1 开始计数,因此这里的 5 代表一周中的正确日期:星期五。
我们可以从上面看到这是一年中的第 43 周,但是如果我们想隔离这个数字,我们可以像对任何其他 Python 列表或元组一样使用索引来做到这一点:
todays_date.isocalendar()[1]
43
将日期对象转换为 Unix 时间戳,反之亦然 在编程中,经常会遇到存储为时间戳的时间和日期数据,或者想要以Unix 时间戳格式存储自己的数据 。
我们可以使用 datetime 的内置timestamp() 函数来做到这一点 ,它接受一个 datetime 对象作为参数并以时间戳格式返回该日期和时间:
#import datetimefrom datetime import datetime# get current datenow = datetime.now()# convert current date into timestamptimestamp = datetime.timestamp(now)print("Date and Time :", now)print("Timestamp:", timestamp)
Date and Time : 2019-10-25 10:36:32.827300 Timestamp: 1572014192.8273
同样,我们可以使用fromtimestamp(). 这是一个 datetime 以时间戳(浮点格式)为参数并返回一个 datetime 对象的函数,如下所示:
#import datetimefrom datetime import datetimetimestamp = 1572014192.8273#convert timestamp to datetime objectdt_object = datetime.fromtimestamp(timestamp)print("dt_object:", dt_object)print("type(dt_object): ", type(dt_object))
dt_object: 2019-10-25 10:36:32.827300 type(dt_object): <class \\\'datetime.datetime\\\'>
使用 Timedelta 对象测量时间跨度 通常,我们可能希望使用 Python 日期时间来测量时间跨度或持续时间。我们可以用它的内置timedelta 类来做到这一点 。甲 timedelta 对象表示的两个日期或时间之间的时间量。我们可以使用它来测量时间跨度,或者通过添加和减去它们等来操纵日期或时间。
默认情况下,timedelta 对象的所有参数都设置为零。让我们创建一个两周长的新 timedelta 对象,看看它看起来如何:
#import datetimefrom datetime import timedelta# create timedelta object with difference of 2 weeksd = timedelta(weeks=2)print(d)print(type(d))print(d.days)
14 days, 0:00:00 <class \\\'datetime.timedelta\\\'> 14
请注意,我们可以使用timedelta class 属性 获取以天为单位的持续时间.days。正如我们在其文档中所见 ,我们还可以以秒或微秒为单位获取此持续时间。
让我们创建另一个 timedelta 持续时间以获得更多练习:
year = timedelta(days=365)print(year)
365 days, 0:00:00
现在让我们开始使用 timedelta 对象和 datetime 对象来做一些数学运算!具体来说,让我们为当前时间和日期添加一些不同的持续时间,以查看 15 天后的日期,两周前的日期。
为此,我们可以使用 + or – 运算符将 timedelta 对象添加到 datetime 对象或从 datetime 对象中减去。结果将是 datetime 对象加上或减去我们的 timedelta 对象中指定的持续时间。酷,对吧?
(注意:在下面的代码中,时间是 10 月 25 日上午 11 点 12 分;您的结果将因运行代码的时间而异,因为我们datetime 使用该.now() 函数获取 对象 )。
#import datetimefrom datetime import datetime, timedelta# get current timenow = datetime.now()print ("Today\\\'s date: ", str(now))#add 15 days to current datefuture_date_after_15days = now + timedelta(days = 15)print(\\\'Date after 15 days: \\\', future_date_after_15days)#subtract 2 weeks from current datetwo_weeks_ago = now - timedelta(weeks = 2)print(\\\'Date two weeks ago: \\\', two_weeks_ago)print(\\\'two_weeks_ago object type: \\\', type(two_weeks_ago))
Today\\\'s date: 2019-10-25 11:12:24.863308 Date after 15 days: 2019-11-09 11:12:24.863308 Date two weeks ago: 2019-10-11 11:12:24.863308 two_weeks_ago object type: <class \\\'datetime.datetime\\\'>
请注意,这些数学运算的输出仍然是一个datetime 对象。
找出两个日期和时间之间的差异与我们上面所做的类似,我们还可以使用 datetime 从另一个日期中减去一个日期以找到它们之间的时间跨度。
因为这个数学运算的结果是一个 持续时间,当我们从另一个日期中减去一个日期时产生的对象将是一个 timedelta 对象。
在这里,我们将创建两个 date 对象(请记住,它们的工作方式与datetime 对象相同 ,只是不包含时间数据)并从另一个中减去一个以找到持续时间:
# import datetimefrom datetime import date# Create two datesdate1 = date(2008, 8, 18)date2 = date(2008, 8, 10)# Difference between two datesdelta = date2 - date1print("Difference: ", delta.days)print(\\\'delta object type: \\\', type(delta))
Difference: -8 delta object type: <class \\\'datetime.timedelta\\\'>
上面,为了清楚起见,我们只使用了日期,但我们可以对datetime 物体做同样的事情,以获得更精确的测量,包括小时、分钟和秒:
# import datetimefrom datetime import datetime# create two dates with year, month, day, hour, minute, and seconddate1 = datetime(2017, 6, 21, 18, 25, 30)date2 = datetime(2017, 5, 16, 8, 21, 10)# Difference between two datesdiff = date1-date2print("Difference: ", diff)
Difference: 36 days, 10:04:20
格式化日期:更多关于 strftime() 和 strptime() 我们谈到简要地 strftime() 和 strptime() 较早,但让我们在这些方法仔细看,因为他们是在Python数据分析工作往往是重要的。
strptime() 是我们之前使用的方法,您会记得它可以将格式化为文本字符串的日期和时间转换为日期时间对象,格式如下:
time.strptime(string, format)
请注意,它需要两个参数:
string – 我们要转换的字符串格式的时间 format – 字符串中时间的特定格式,以便 strptime() 可以正确解析它这次让我们尝试转换不同类型的日期字符串。 该站点 是查找帮助strptime() 解释我们的字符串输入所需的格式代码的非常有用的参考 。
# import datetimefrom datetime import datetimedate_string = "1 August, 2019"# format datedate_object = datetime.strptime(date_string, "%d %B, %Y")print("date_object: ", date_object)
date_object: 2019-08-01 00:00:00
现在让我们做一些更高级的事情来练习到目前为止我们学到的一切!我们将从字符串格式的日期开始,将其转换为日期时间对象,然后查看几种不同的格式化方式(dd/mm 和 mm/dd)。
然后,坚持使用 mm/dd 格式,我们将其转换为 Unix 时间戳。然后,我们将它转换成一个 datetime 对象,并转换 是 使用一些不同的回字符串 的strftime模式 来控制输出:
# import datetimefrom datetime import datetimedt_string = "12/11/2018 09:15:32"# Considering date is in dd/mm/yyyy formatdt_object1 = datetime.strptime(dt_string, "%d/%m/%Y %H:%M:%S")print("dt_object1:", dt_object1)# Considering date is in mm/dd/yyyy formatdt_object2 = datetime.strptime(dt_string, "%m/%d/%Y %H:%M:%S")print("dt_object2:", dt_object2)# Convert dt_object2 to Unix Timestamptimestamp = datetime.timestamp(dt_object2)print(\\\'Unix Timestamp: \\\', timestamp)# Convert back into datetimedate_time = datetime.fromtimestamp(timestamp)d = date_time.strftime("%c")print("Output 1:", d)d = date_time.strftime("%x")print("Output 2:", d)d = date_time.strftime("%X")print("Output 3:", d)
dt_object1: 2018-11-12 09:15:32 dt_object2: 2018-12-11 09:15:32 Unix Timestamp: 1544537732.0 Output 1: Tue Dec 11 09:15:32 2018 Output 2: 12/11/18 Output 3: 09:15:32
这是一张图片,您可以将其与常用的有用 strptime 和 strftime 模式的备忘单一起保存:
让我们使用这些进行更多练习:
# current date and timenow = datetime.now()# get year from dateyear = now.strftime("%Y")print("Year:", year)# get month from datemonth = now.strftime("%m")print("Month;", month)# get day from dateday = now.strftime("%d")print("Day:", day)# format time in HH:MM:SStime = now.strftime("%H:%M:%S")print("Time:", time)# format datedate_time = now.strftime("%m/%d/%Y, %H:%M:%S")print("Date and Time:",date_time)
Year: 2019 Month; 10 Day: 25 Time: 11:56:41 Date and Time: 10/25/2019, 11:56:41
处理时区 当涉及时区时,在 Pythin 中处理日期和时间会变得更加复杂。幸运的是,该 pytz 模块的存在是为了帮助我们处理跨时区转换。它还处理使用夏令时的地方的夏令时。
我们可以使用该 localize 函数将时区位置添加到 Python 日期时间对象。然后我们可以使用该函数 astimezone() 将现有的本地时区转换为我们指定的任何其他时区(它将我们想要转换为的时区作为参数)。
例如:
# import timezone from pytz modulefrom pytz import timezone# Create timezone US/Easterneast = timezone(\\\'US/Eastern\\\')# Localize dateloc_dt = east.localize(datetime(2011, 11, 2, 7, 27, 0))print(loc_dt)# Convert localized date into Asia/Kolkata timezonekolkata = timezone("Asia/Kolkata")print(loc_dt.astimezone(kolkata))# Convert localized date into Australia/Sydney timezoneau_tz = timezone(\\\'Australia/Sydney\\\')print(loc_dt.astimezone(au_tz))
2011-11-02 07:27:00-04:00 2011-11-02 16:57:00+05:30 2011-11-02 22:27:00+11:00
在处理包含多个不同时区的数据集时,此模块可以帮助简化生活。
使用 pandas 日期时间对象数据科学家喜欢 pandas 的原因有很多。其中之一是它包含用于处理时间序列数据的广泛功能和特性。就像datetime 它本身一样 ,pandas 有 datetime 和 timedelta 对象,分别用于指定日期、时间和持续时间。
我们可以使用以下函数将日期、时间和持续时间文本字符串转换为 Pandas Datetime 对象:
to_datetime():将字符串日期和时间转换为 Python 日期时间对象。 to_timedelta():根据天、小时、分钟和秒查找时间差异。正如我们将看到的,这些函数实际上非常擅长通过自动检测格式将字符串转换为 Python 日期时间对象,而无需我们使用 strftime 模式定义它。
让我们看一个简单的例子:
# import pandas module as pdimport pandas as pd# create date object using to_datetime() functiondate = pd.to_datetime("8th of sep, 2019")print(date)
2019-09-08 00:00:00
请注意,即使我们给它一个带有一些复杂因素的字符串,例如“th”和“sep”而不是“Sep”。或“September”,pandas 能够正确解析字符串并返回格式化的日期。
我们还可以使用 pandas(及其一些附属的 numpy 功能)自动创建日期范围作为 pandas 系列。例如,下面我们从上面定义的那一天开始创建一系列十二个日期。然后我们使用pd.date_range()以下命令从预定义日期开始创建一系列不同的日期 :
# Create date series using numpy and to_timedelta() functiondate_series = date + pd.to_timedelta(np.arange(12), \\\'D\\\')print(date_series)# Create date series using date_range() functiondate_series = pd.date_range(\\\'08/10/2019\\\', periods = 12, freq =\\\'D\\\')print(date_series)
DatetimeIndex([\\\'2019-09-08\\\', \\\'2019-09-09\\\', \\\'2019-09-10\\\', \\\'2019-09-11\\\', \\\'2019-09-12\\\', \\\'2019-09-13\\\', \\\'2019-09-14\\\', \\\'2019-09-15\\\', \\\'2019-09-16\\\', \\\'2019-09-17\\\', \\\'2019-09-18\\\', \\\'2019-09-19\\\'], dtype=\\\'datetime64[ns]\\\', freq=None) DatetimeIndex([\\\'2019-08-10\\\', \\\'2019-08-11\\\', \\\'2019-08-12\\\', \\\'2019-08-13\\\', \\\'2019-08-14\\\', \\\'2019-08-15\\\', \\\'2019-08-16\\\', \\\'2019-08-17\\\', \\\'2019-08-18\\\', \\\'2019-08-19\\\', \\\'2019-08-20\\\', \\\'2019-08-21\\\'], dtype=\\\'datetime64[ns]\\\', freq=\\\'D\\\')
在 Pandas 中获取年、月、日、时、分 我们可以使用dt 所有列的属性轻松地从 Pandas 数据框列中的日期中获取年、月、日、小时或分钟 。例如,我们可以使用 df[‘date’].dt.year 从包含完整日期的 Pandas 列中仅提取年份。
为了探索这一点,让我们使用上面创建的系列之一制作一个快速的 Dataframe:
# Create a Dataframe with one column datedf = pd.Dataframe()df[\\\'date\\\'] = date_series df.head()
日期 0 2019-08-10 1 2019-08-11 2 2019-08-12 3 2019-08-13 4 2019-08-14 现在,让我们使用相关的 Python 日期时间(通过 访问dt)属性为日期的每个元素创建单独的列 :
# Extract year, month, day, hour, and minute. Assign all these date component to new column.df[\\\'year\\\'] = df[\\\'date\\\'].dt.yeardf[\\\'month\\\'] = df[\\\'date\\\'].dt.monthdf[\\\'day\\\'] = df[\\\'date\\\'].dt.daydf[\\\'hour\\\'] = df[\\\'date\\\'].dt.hourdf[\\\'minute\\\'] = df[\\\'date\\\'].dt.minutedf.head()
日期 年 月 日 小时 分钟 0 2019-08-10 2019年 8 10 0 0 1 2019-08-11 2019年 8 11 0 0 2 2019-08-12 2019年 8 12 0 0 3 2019-08-13 2019年 8 13 0 0 4 2019-08-14 2019年 8 14 0 0 获取工作日和一年中的某一天 Pandas 还能够从它的 datetime 对象中获取其他元素,比如星期几和一年中的哪一天。同样,我们可以使用 dt 属性来做到这一点。请注意,此处,与 Python 中的一般情况一样,一周从周一的索引 0 开始,因此一周中的第 5 天是 周六。
# get Weekday and Day of Year. Assign all these date component to new column.df[\\\'weekday\\\'] = df[\\\'date\\\'].dt.weekdaydf[\\\'day_name\\\'] = df[\\\'date\\\'].dt.weekday_namedf[\\\'dayofyear\\\'] = df[\\\'date\\\'].dt.dayofyeardf.head()
日期 年 月 日 小时 分钟 工作日 日期名称 一年中的一天 0 2019-08-10 2019年 8 10 0 0 5 周六 222 1 2019-08-11 2019年 8 11 0 0 6 星期日 223 2 2019-08-12 2019年 8 12 0 0 0 周一 224 3 2019-08-13 2019年 8 13 0 0 1 周二 225 4 2019-08-14 2019年 8 14 0 0 2 周三 226 将日期对象转换为数据帧索引 我们还可以使用 pandas 将日期时间列放入我们的 Dataframe 的索引中。这对于探索性数据可视化等任务非常有帮助,因为 matplotlib 会识别出 Dataframe 索引是一个时间序列并相应地绘制数据。
为此,我们所要做的就是重新定义 df.index:
# Assign date column to dataframe indexdf.index = df.datedf.head()
日期 年 月 日 小时 分钟 工作日 日期名称 一年中的一天 日期 2019-08-10 2019-08-10 2019年 8 10 0 0 5 周六 222 2019-08-11 2019-08-11 2019年 8 11 0 0 6 星期日 223 2019-08-12 2019-08-12 2019年 8 12 0 0 0 周一 224 2019-08-13 2019-08-13 2019年 8 13 0 0 1 周二 225 2019-08-14 2019-08-14 2019年 8 14 0 0 2 周三 226 结论 在本教程中,我们深入研究了 Python 日期时间,并且还对 Pandas 和日历模块进行了一些工作。我们已经介绍了很多,但请记住:学习某些东西的最佳方式是亲自编写代码!
如果您想练习datetime 使用交互式答案检查编写代码,请查看我们的 Python 中级课程, 了解有关 Python 中日期时间 的课程,其中包含交互式答案检查和浏览器内代码运行。