在日常生活中,我们可以用多种不同的格式来表示日期和时间,例如,7 月 4 日、2022 年 3 月 8 日、22:00 或 2022 年 12 月 31 日 23:59:59。它们使用整数和字符串的组合,或者也可以使用浮点数来表示一天、一分钟等等,各种各样的时间表示方式,确实让人眼花缭乱。
不过还好,Python 有 datetime 模块,它允许我们轻松地操作表示日期和时间的对象。
在今天的文章中,我们将学习以下内容:
Let's do it!
正如我们之前所看到的,在编程中表示日期和时间是一项非常有挑战的事情。首先,我们必须以标准的、普遍接受的格式来表示它们。幸运的是,国际标准化组织 (ISO) 制定了一个全球标准 ISO 8601,它将与日期和时间相关的对象表示为 YYYY-MM-DD HH:MM:SS,其信息范围从最重要的(年,YYYY)到 最不重要的(秒,SS)。这种格式的每一部分都表示为一个四位数或两位数。
Python 中的 datetime 模块有 5 个主要类(模块的一部分):
此外,我们将使用 zoneinfo 模块,它为我们提供了一种处理时区的更加现代的方式,以及 dateutil 包,它包含许多有用的函数来处理日期和时间。
让我们导入 datetime 模块并创建我们的第一个日期和时间对象:
# From the datetime module import date
from datetime import date
# Create a date object of 2000-02-03
date(2022, 2, 3)
Output:
datetime.date(2022, 2, 3)
在上面的代码中,我们从模块中导入了日期类,然后创建了 2022 年 2 月 3 日的 datetime.date 对象。需要注意的是,用于创建该对象的数字顺序与 ISO 8061 中的完全相同 (但我们省略了 0 并且只写了一个数字的月份和日期)。
关于时间的编码都是基于现实的,所以假设我们要创建一个 2000-26-03 的对象:
# Create a date object of 2000-26-03
date(2000, 26, 3)
Output:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [2], in
1 # Create a date object of 2000-26-03
----> 2 date(2000, 26, 3)
ValueError: month must be in 1..12
我们得到 ValueError: month must be in 1..12,毫无疑问,日历中没有第 26 个月,抛出异常。
让我们看看如何创建一个 datetime.time 对象:
# From the datetime module import time
from datetime import time
# Create a time object of 05:35:02
time(5, 35, 2)
Output:
datetime.time(5, 35, 2)
现在,如果我们想要在一个对象中同时包含日期和时间怎么办?我们应该使用 datetime 类:
# From the datetime module import datetime
from datetime import datetime
# Create a datetime object of 2000-02-03 05:35:02
datetime(2000, 2, 3, 5, 35, 2)
Output:
datetime.datetime(2000, 2, 3, 5, 35, 2)
不出意外,我们成功创建了 datetime 对象。我们还可以更明确地将关键字参数传递给 datetime 构造函数:
datetime(year=2000, month=2, day=3, hour=5, minute=35, second=2)
Output:
datetime.datetime(2000, 2, 3, 5, 35, 2)
如果我们只传入三个参数(年、月和日)会怎样,是否会报错呢
# Create a datetime object of 2000-02-03
datetime(2000, 2, 3)
Output:
datetime.datetime(2000, 2, 3, 0, 0)
我们可以看到,现在对象中有两个零(分别代表)小时和分钟。同时秒数也被省略了。
在许多情况下,我们想知道当前的确切时间。可以使用 datetime 类的 now() 方法:
# Time at the moment
now = datetime.now()
now
Output:
datetime.datetime(2022, 8, 1, 0, 9, 39, 611254)
我们得到一个日期时间对象,这里最后一个数字是微秒。
如果我们只需要今天的日期,我们可以使用 date 类的 today() 方法:
today = date.today()
today
Output:
datetime.date(2022, 8, 1)
如果我们只需要时间,就必须访问 datetime.now() 对象的小时、分钟和秒属性,并将它们传递给时间构造函数:
time(now.hour, now.minute, now.second)
Output:
datetime.time(11, 33, 25)
我们还可以使用 isocalendar() 函数从日期时间对象中提取周数和天数。它将返回一个包含 ISO 年份、周数和工作日数的三项元组:
# isocalendar() returns a 3-item tuple with ISO year, week number, and weekday number
now.isocalendar()
Output:
datetime.IsoCalendarDate(year=2022, week=7, weekday=1)
在 ISO 格式中,一周从星期一开始,到星期日结束。一周中的天数由从 1(星期一)到 7(星期日)的数字编码。如果我们想访问这些元组元素之一,需要使用括号表示法:
# Access week number
week_number = now.isocalendar()[1]
week_number
Output:
7
在数据科学和一般编程中,我们主要使用以数十种不同格式存储为字符串的日期和时间,具体取决于地区、公司或我们需要的信息粒度。有时,我们需要日期和确切时间,但在其他情况下,我们只需要年份和月份。我们该如何从字符串中提取我们需要的数据,以便将其作为日期时间(日期、时间)对象来操作呢?
我们学习的第一个将日期字符串转换为日期对象的函数是 fromisoformat,我们这样称呼它是因为它使用 ISO 8601 格式(即 YYYY-MM-DD),让我们看一个例子:
# Convert a date string into a date object
date.fromisoformat("2022-12-31")
Output:
datetime.date(2022, 12, 31)
ISO 格式也包含时间,但如果我们却不能将它传递给函数:
date.fromisoformat("2022-12-31 00:00:00")
Output:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [13], in
----> 1 date.fromisoformat("2022-12-31 00:00:00")
ValueError: Invalid isoformat string: '2022-12-31 00:00:00'
当然,我们也可以进行逆向运算,将 datetime 对象转换为 ISO 格式的日期字符串,我们应该使用 isoformat():
# Convert a datetime object into a string in the ISO format
date(2022, 12, 31).isoformat()
Output:
'2022-12-31'
为了解决上述 ValueError 问题,我们可以使用 strptime() 函数,该函数可以将任意日期/时间字符串转换为日期时间对象。我们的字符串不一定需要遵循 ISO 格式,但我们应该指定字符串的哪一部分代表哪个日期或时间单位(年、小时等)。让我们看一个例子,首先,我们将使用严格的 ISO 格式将字符串转换为日期时间对象:
# Date as a string
iso_date = "2022-12-31 23:59:58"
# ISO format
iso_format = "%Y-%m-%d %H:%M:%S"
# Convert the string into a datetime object
datetime.strptime(iso_date, iso_format)
Output:
datetime.datetime(2022, 12, 31, 23, 59, 58)
在第一行,我们创建一个日期/时间字符串。在第二行中,我们使用特殊代码指定字符串的格式,该代码包含一个百分号,后跟一个编码日期或时间单位的字符。最后,在第三行中,我们使用 strptime() 函数将字符串转换为日期时间对象。这个函数有两个参数:字符串和字符串的格式。
我们上面使用的代码还可以编码其他日期和时间单位,如工作日、月份名称、周数等。
代码 |
示例 |
说明 |
%A |
Monday |
完整的工作日名称 |
%B |
December |
全月名称 |
%W |
2 |
周数(星期一为一周的第一天) |
让我们再看几个使用其他格式的示例:
# European date as a string
european_date = "31-12-2022"
# European format
european_format = "%d-%m-%Y"
# Convert the string into a datetime object
datetime.strptime(european_date, european_format)
Output:
datetime.datetime(2022, 12, 31, 0, 0)
如上所示,字符串已成功转换,但还有额外的零表示时间字段,让我们看一个使用其他代码的示例:
# Full month name date
full_month_date = "12 September 2022"
# Full month format
full_month_format = "%d %B %Y"
# Convert the string into a datetime object
datetime.strptime(full_month_date, full_month_format)
Output:
datetime.datetime(2022, 9, 12, 0, 0)
还是可以正常转换,但是需要注意的是,我们定义的格式应该与日期字符串的格式相匹配。因此,如果我们有空格、冒号、连字符或其他字符来分隔时间单位,那么它们也应该在代码字符串中。否则,Python 将抛出 ValueError:
# Full month name date
full_month_date = "12 September 2022"
# Wrong format (missing space)
full_month_format = "%d%B %Y"
# Convert the string into a datetime object
datetime.strptime(full_month_date, full_month_format)
Output:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [18], in
5 full_month_format = "%d%B %Y"
7 # Convert the string into a datetime object
----> 8 datetime.strptime(full_month_date, full_month_format)
File ~/coding/dataquest/articles/using-the-datetime-package/env/lib/python3.10/_strptime.py:568, in _strptime_datetime(cls, data_string, format)
565 def _strptime_datetime(cls, data_string, format="%a %b %d %H:%M:%S %Y"):
566 """Return a class cls instance based on the input string and the
567 format string."""
--> 568 tt, fraction, gmtoff_fraction = _strptime(data_string, format)
569 tzname, gmtoff = tt[-2:]
570 args = tt[:6] + (fraction,)
File ~/coding/dataquest/articles/using-the-datetime-package/env/lib/python3.10/_strptime.py:349, in _strptime(data_string, format)
347 found = format_regex.match(data_string)
348 if not found:
--> 349 raise ValueError("time data %r does not match format %r" %
350 (data_string, format))
351 if len(data_string) != found.end():
352 raise ValueError("unconverted data remains: %s" %
353 data_string[found.end():])
ValueError: time data '12 September 2022' does not match format '%d%B %Y'
可以看到,即使缺少一个空格也可能导致错误!
在 Python 中,我们还可以使用 strftime() 函数将日期时间对象转换为字符串。它有两个参数:一个日期时间对象和输出字符串的格式。
# Create a datetime object
datetime_obj = datetime(2022, 12, 31)
# American date format
american_format = "%m-%d-%Y"
# European format
european_format = "%d-%m-%Y"
# American date string
print(f"American date string: {datetime.strftime(datetime_obj, american_format)}.")
# European date string
print(f"European date string: {datetime.strftime(datetime_obj, european_format)}.")
Output:
American date string: 12-31-2022.
European date string: 31-12-2022.
我们采用相同的日期时间对象并将其转换为两种不同的格式。我们还可以指定其他格式,例如完整的月份名称后跟日期和年份。
full_month = "%B %d, %Y"
datetime.strftime(datetime_obj, full_month)
Output:
'December 31, 2022'
另一种使用 strftime 的方法是将它放在 datetime 对象之后:
datetime_obj = datetime(2022, 12, 31, 23, 59, 59)
full_datetime = "%B %d, %Y %H:%M:%S"
datetime_obj.strftime(full_datetime)
Output:
'December 31, 2022 23:59:59'
在实际使用当中,如果我们想提取不同年份 12 月 31 日的工作日名称,strftime() 可能很方便:
# Extract the weekday name of December 31
weekday_format = "%A"
for year in range(2022, 2026):
print(f"Weekday of December 31, {year} is {date(year, 12, 31).strftime(weekday_format)}.")
Output:
Weekday of December 31, 2022 is Saturday.
Weekday of December 31, 2023 is Sunday.
Weekday of December 31, 2024 is Tuesday.
Weekday of December 31, 2025 is Wednesday.
在编程中,通常会看到以 Unix 时间戳格式存储的日期和时间,这种格式将任何日期表示为数字。一般情况时间戳是从 1970 年 1 月 1 日 00:00:00 UTC(协调世界时)开始的 Unix 纪元经过的秒数。我们可以使用 timestamp() 函数计算这个数字:
new_year_2023 = datetime(2022, 12, 31)
datetime.timestamp(new_year_2023)
Output:
1672441200.0
1672441200 就是从 Unix 纪元开始到 2022 年 12 月 31 日之间的秒数。
我们可以使用 fromtimestamp() 函数执行逆运算:
datetime.fromtimestamp(1672441200)
Output:
datetime.datetime(2022, 12, 31, 0, 0)
有时我们可能想要计算两个日期之间的差异或对日期和时间执行其他算术运算。幸运的是,Python 的工具包中有许多工具可以执行此类计算。
我们可以执行的第一个操作是计算两个日期之间的差异。为此,我们使用减号:
# Instatiate two dates
first_date = date(2022, 1, 1)
second_date = date(2022, 12, 31)
# Difference between two dates
date_diff = second_date - first_date
# Function to convert datetime to string
def dt_string(date, date_format="%B %d, %Y"):
return date.strftime(date_format)
print(f"The number of days and hours between {dt_string(first_date)} and {dt_string(second_date)} is {date_diff}.")
Output:
The number of days and hours between January 01, 2022 and December 31, 2022 is 364 days, 0:00:00
让我们看看 first_date - second_date 返回什么类型的对象:
type(date_diff)
Output:
datetime.timedelta
此对象的类型是 datetime.timedelta,它的名称中有 delta,指的是一个绿色字母 delta,在科学和工程中,描述了一种变化<实际上,这里它代表了时间上的变化(差异)。
如果我们只对两个日期之间的天数感兴趣怎么办?我们可以访问 timedelta 对象的不同属性,其中之一称为 .days。
print(f"The number of days between {dt_string(first_date)} and {dt_string(second_date)} is {(date_diff).days}.")
Output:
The number of days between January 01, 2022 and December 31, 2022 is 364.
现在我们知道了 timedelta 对象,是时候介绍 timedelta() 函数了。它允许我们通过加减时间单位(如天、年、周、秒等)对时间对象执行许多算术运算。例如,我们可能想知道从现在起 30 天后是一周中的哪一天。为此,我们必须创建一个表示当前时间的对象和一个定义我们添加到其中的时间量的 timedelta 对象:
# Import timedelta
from datetime import timedelta
# Current time
now = datetime.now()
# timedelta of 30 days
one_month = timedelta(days=30)
# Day in one month/using dt_string function defined above
print(f"The day in 30 days is {dt_string(now + one_month)}.")
Output:
The day in 30 days is March 16, 2022.
如果我们查看 timedelta 函数的帮助页面 (help(timedelta)),我们会看到它有以下参数:days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours= 0,周=0。因此我们还可以练习在日期中添加或减去其他时间单位。例如,我们可以计算 2030 年新年前 12 小时的时间:
# New year 2030
new_year_2030 = datetime(2030, 1, 1, 0, 0)
# timedelta of 12 hours
twelve_hours = timedelta(hours=12)
# Time string of 12 hours before New Year 2023
twelve_hours_before = (new_year_2030 - twelve_hours).strftime("%B %d, %Y, %H:%M:%S")
# Print the time 12 hours before New Year 2023
print(f"The time twelve hours before New Year 2030 will be {twelve_hours_before}.")
Output:
The time twelve hours before New Year 2030 39个PythonDatetime小例子,拯救因时间抓狂的你
文章转载:http://www.shufengxianlan.com/qtweb/news39/476689.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源:
创新互联