介绍
数据可以用多种形式表示——一种方便的表示日期和时间的方法是 字符串. 然而,要以算术方式处理这些日期和时间(例如计算时差、添加或删除时间等)——我们需要将它们转换为 datetime
目的。
最常见的来源之一 字符串格式的日期时间 是返回不可知字符串的 REST API,然后我们可以将其转换为其他格式。
此外,在处理日期时间对象时,时区是一个常见的头痛问题,因此我们在转换时也需要考虑到这一点。
在本指南中,我们将了解如何将字符串日期/时间转换为
datetime
Python 中的对象,使用内置的datetime
模块,还有第三方模块,例如dateutil
,arrow
和玛雅人,占时区。
使用日期时间转换字符串
日期时间 模块由三种不同的对象类型组成: date
, time
及 datetime
。 该 date
对象保存日期, time
保持时间,并且 datetime
包含日期和时间!
import datetime
print(f'Current date/time: {datetime.datetime.now()}')
运行此代码将导致:
Current date/time: 2022-12-01 10:27:03.929149
当没有给出自定义格式时,使用默认的字符串格式,即“2022-12-01 10:27:03.929149”的格式是 ISO 8601
格式 (YYYY-MM-DDTHH:MM:SS.mmmmmm). 如果我们的输入字符串创建一个 datetime
对象采用相同的 ISO 8601 格式,或者如果您知道您将预先接收的格式,我们可以轻松地将其解析为 datetime
宾语:
import datetime
date_time_str = '2022-12-01 10:27:03.929149'
date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S.%f')
print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)
运行它将打印日期、时间和日期时间:
Date: 2022-12-01
Time: 10:27:03.929149
Date-time: 2022-12-01 10:27:03.929149
在这里,我们使用 strptime()
方法,它接受两个参数:
- 字符串格式的日期
- 第一个参数的格式
像这样指定格式会使解析速度更快,因为 datetime
不需要自己尝试和解释格式,这在计算上要昂贵得多。 返回值是类型 datetime
.
在我们的例子中, "2022-12-01 10:27:03.929149"
是输入字符串和 "%Y-%m-%d %H:%M:%S.%f"
是我们日期字符串的格式。 返回的 datetime
值存储为 date_time_obj
.
由于这是一个 datetime
对象,我们可以调用 date()
和 time()
方法直接就可以了。 从输出中可以看出,它打印了输入字符串的“日期”和“时间”部分!
格式标记
值得花点时间去理解 格式标记 - 在 "%Y-%m-%d %H:%M:%S.%f"
从以前。
每个标记代表日期时间的不同部分,如日、月、年、月中日或周中等。 支持的令牌列表 足够广泛以启用各种格式。 我们之前也使用过的一些常用的是:
%Y
: 年份(4 位数)%m
: 月%d
: 一个月中的第几天%H
: 小时(24 小时)%M
: 分钟%S
: 秒%f
: 微秒
请注意: 除年份外,所有这些标记都将被零填充(即八月是第 8 个月,并且被零填充到 08
).
使用 strptime() 格式标记将字符串转换为不同的日期时间格式
如果一个字符串的格式是已知的,它可以很容易地解析为 datetime
对象使用 strptime()
. 让我们看一个从一种格式转换为另一种格式的重要示例:
import datetime
date_time_str = 'Jul 17 2022 9:20AM'
date_time_obj = datetime.datetime.strptime(date_time_str, '%b %d %Y %I:%M%p')
print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)
输入字符串是一种格式——“Jul 17 2022 9:20AM”。 知道了这种格式,我们将组成元素映射到 ISO 8601 格式并将其转换为 datetime
宾语:
Date: 2022-07-17
Time: 09:20:00
Date-time: 2022-07-17 09:20:00
以下是常见字符串格式日期时间及其相应格式的简短列表 strptime()
:
"Jun 28 2018 at 7:40AM" -> "%b %d %Y at %I:%M%p"
"September 18, 2017, 22:19:55" -> "%B %d, %Y, %H:%M:%S"
"Sun,05/12/99,12:30PM" -> "%a,%d/%m/%y,%I:%M%p"
"Mon, 21 March, 2015" -> "%a, %d %B, %Y"
"2018-03-12T10:12:45Z" -> "%Y-%m-%dT%H:%M:%SZ"
您可以解析任何格式的日期时间字符串——只要您对接收到的输入使用正确的格式标记字符串即可。
使用时区将字符串转换为日期时间
在处理时区时,处理日期时间变得更加复杂。 到目前为止,上述所有示例对时区来说都是幼稚的。 这些被称为 天真的日期时间对象.
然而,本 datetime
对象包含一个专门用于存储时区相关数据的字段 – tzinfo
:
import datetime as dt
dtime = dt.datetime.now()
print(dtime)
print(dtime.tzinfo)
tzinfo
字段是一个 datetime.timezone
对象,表示时区信息。 它是 None
默认情况下,表示日期时间对象是时区天真的。 一个非常常见的用于处理时区的外部库是 pytz
。 你可以设定 吡啶 对象作为 tzinfo
领域。
如果您还没有 - 通过以下方式安装它:
$ pip install pytz
使用 PyTz,我们可以为时区感知日期时间创建一个锚点,例如 UTC:
import datetime as dt
import pytz
dtime = dt.datetime.now(pytz.utc)
print(dtime)
print(dtime.tzinfo)
输出:
2022-12-01 02:07:41.960920+00:00
UTC
现在不再是上午 11 点,而是凌晨 2 点,因为我们已经将时区拨快了几个小时! 这个 更改时区 日期时间。
+00:00
是显示时间与作为全局协调锚点的 UTC 时间之间的差异。 我们已经将时间设置为 UTC,所以偏移量是 00:00
。 这是一个 时区感知对象.
同样,我们可以在时区之间切换相同日期时间的解释。 让我们将字符串(例如“2022-06-29 17:08:00”)转换为日期时间,然后 本地化 它到“美国/纽约”时区:
import datetime as dt
import pytz
date_time_str = '2022-06-29 17:08:00'
date_time_obj = dt.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S')
timezone = pytz.timezone('America/New_York')
timezone_date_time_obj = timezone.localize(date_time_obj)
print(timezone_date_time_obj)
print(timezone_date_time_obj.tzinfo)
请注意: 本地化 将时区天真的日期时间转换为时区感知日期时间,并将时区视为本地时区。 就这样 日期时间保持不变, 但考虑到不同的时区,它不再代表不受时区限制的同一时间点。
我们得到相同的 日期时间值, 抵消 - 04:00 与 UTC 时间相比:
2022-06-29 17:08:00-04:00
America/New_York
17:08 在东京 不 与纽约 17:08 相同的时间点。 东京的 17:08 是纽约的 3:08。
如何找到所有时区代码/别名?
要查找所有可用时区,请检查 all_timezones
字段,它是所有可用时区的列表:
print(f'There are {len(pytz.all_timezones)} timezones in PyTzn')
for time_zone in pytz.all_timezones:
print(time_zone)
查看我们的 Git 学习实践指南,其中包含最佳实践、行业认可的标准以及随附的备忘单。 停止谷歌搜索 Git 命令,实际上 学习 它!
There are 594 timezones in PyTz
Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa
Africa/Algiers
Africa/Asmara
Africa/Asmera
...
更改日期时间的时区
我们可以转换时区感知的时区 datetime
对象从一个区域到另一个区域,而不是通过某个时区的镜头来本地化时区天真的日期时间。
这与本地化不同,因为本地化代表不同的时间点,但是通过不同的镜头转换对象的时区代表相同的时间点:
import datetime as dt
import pytz
timezone_nw = pytz.timezone('America/New_York')
nw_datetime_obj = dt.datetime.now(timezone_nw)
timezone_london = pytz.timezone('Europe/London')
london_datetime_obj = nw_datetime_obj.astimezone(timezone_london)
print('America/New_York:', nw_datetime_obj)
print('Europe/London:', london_datetime_obj)
首先,我们用当前时间创建了一个日期时间对象,并将其设置为“America/New_York”时区。 然后使用 astimezone()
方法,我们已经转换了这个 datetime
到“欧洲/伦敦”时区。 两个都 datetime
s 将打印不同的值,使用 UTC 偏移量作为它们之间的参考链接:
America/New_York: 2022-11-30 21:24:30.123400-05:00
Europe/London: 2022-12-01 02:24:30.123400+00:00
次日 2:24 伦敦 is 与前一天纽约时间21:24相同的时间点 因为伦敦提前 5 小时。
正如预期的那样,日期时间不同,因为它们相隔大约 5 小时。
使用第三方库将字符串转换为日期时间
Python的 datetime
模块可以将所有不同类型的字符串转换为 datetime
目的。 但主要问题是,为了做到这一点,您需要创建适当的格式化代码字符串 strptime()
能理解。 创建此字符串需要时间,并且会使代码更难阅读。
相反,我们可以使用其他第三方库来简化它。
在某些情况下,这些第三方库还为操作和比较日期时间提供了更好的内置支持,有些甚至内置了时区,因此您不需要包含额外的 PyTz 包。
让我们在以下部分中了解其中的一些库。
使用 dateutil 将字符串转换为日期时间
日期工具模块 是对 datetime
模块。 一个优点是我们不需要传递任何解析代码来解析字符串!
使用 Python 自动将字符串转换为没有格式标记的日期时间 dateutil
:
from dateutil.parser import parse
datetime = parse('2018-06-29 22:21:41')
print(datetime)
本篇 parse
函数将自动解析字符串! 您不必包含任何格式字符串。 让我们尝试使用解析不同类型的字符串 dateutil
:
from dateutil.parser import parse
date_array = [
'2018-06-29 08:15:27.243860',
'Jun 28 2018 7:40AM',
'Jun 28 2018 at 7:40AM',
'September 18, 2017, 22:19:55',
'Sun, 05/12/1999, 12:30PM',
'Mon, 21 March, 2015',
'2018-03-12T10:12:45Z',
'2018-06-29 17:08:00.586525+00:00',
'2018-06-29 17:08:00.586525+05:00',
'Tuesday , 6th September, 2017 at 4:30pm'
]
for date in date_array:
print('Parsing: ' + date)
dt = parse(date)
print(dt.date())
print(dt.time())
print(dt.tzinfo)
print('n')
输出:
Parsing: 2018-06-29 08:15:27.243860
2018-06-29
08:15:27.243860
None
Parsing: Jun 28 2018 7:40AM
2018-06-28
07:40:00
None
Parsing: Jun 28 2018 at 7:40AM
2018-06-28
07:40:00
None
Parsing: September 18, 2017, 22:19:55
2017-09-18
22:19:55
None
Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12
12:30:00
None
Parsing: Mon, 21 March, 2015
2015-03-21
00:00:00
None
Parsing: 2018-03-12T10:12:45Z
2018-03-12
10:12:45
tzutc()
Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29
17:08:00.586525
tzutc()
Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29
17:08:00.586525
tzoffset(None, 18000)
Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06
16:30:00
None
您可以看到几乎任何类型的字符串都可以使用 dateutil
模块。
虽然这很方便,但回想一下,必须预测格式会使代码变慢很多,因此如果您的代码需要高性能,那么这可能不适合您的应用程序。
使用 Maya 将字符串转换为日期时间
玛雅 也使得解析字符串和更改时区变得非常容易。 要使用 Python 的 Maya 轻松转换字符串:
import maya
dt = maya.parse('2018-04-29T17:45:25Z').datetime()
print(dt.date())
print(dt.time())
print(dt.tzinfo)
输出:
2018-04-29
17:45:25
UTC
将时间转换为不同的时区:
import maya
dt = maya.parse('2018-04-29T17:45:25Z').datetime(to_timezone='America/New_York', naive=False)
print(dt.date())
print(dt.time())
print(dt.tzinfo)
输出:
2018-04-29
13:45:25
America/New_York
现在不是很容易使用吗? 让我们试试 maya
使用我们使用过的同一组字符串 dateutil
:
import maya
date_array = [
'2018-06-29 08:15:27.243860',
'Jun 28 2018 7:40AM',
'Jun 28 2018 at 7:40AM',
'September 18, 2017, 22:19:55',
'Sun, 05/12/1999, 12:30PM',
'Mon, 21 March, 2015',
'2018-03-12T10:12:45Z',
'2018-06-29 17:08:00.586525+00:00',
'2018-06-29 17:08:00.586525+05:00',
'Tuesday , 6th September, 2017 at 4:30pm'
]
for date in date_array:
print('Parsing: ' + date)
dt = maya.parse(date).datetime()
print(dt)
输出:
Parsing: 2018-06-29 08:15:27.243860
2018-06-29 08:15:27.243860+00:00
Parsing: Jun 28 2018 7:40AM
2018-06-28 07:40:00+00:00
Parsing: Jun 28 2018 at 7:40AM
2018-06-28 07:40:00+00:00
Parsing: September 18, 2017, 22:19:55
2017-09-18 22:19:55+00:00
Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12 12:30:00+00:00
Parsing: Mon, 21 March, 2015
2015-03-21 00:00:00+00:00
Parsing: 2018-03-12T10:12:45Z
2018-03-12 10:12:45+00:00
Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29 17:08:00.586525+00:00
Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29 12:08:00.586525+00:00
Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06 16:30:00+00:00
如您所见,所有日期格式都已成功解析!
如果我们当时不提供时区信息,它会自动将其转换为 UTC。 所以,重要的是要注意我们 必须 提供 to_timezone
和 naive
如果时间不是 UTC,则为参数。
使用箭头将字符串转换为日期时间
箭头 是另一个在 Python 中处理日期时间的库。 和以前一样 maya
,它还会自动计算出日期时间格式。 一旦被解释,它返回一个 Python datetime
来自的对象 arrow
目的。
使用 Python 轻松地将字符串转换为日期时间 arrow
:
import arrow
dt = arrow.get('2018-04-29T17:45:25Z')
print(dt.date())
print(dt.time())
print(dt.tzinfo)
输出:
2018-04-29
17:45:25
tzutc()
这是您可以使用的方法 arrow
使用 to()
方法:
import arrow
dt = arrow.get('2018-04-29T17:45:25Z').to('America/New_York')
print(dt)
print(dt.date())
print(dt.time())
输出:
2018-04-29T13:45:25-04:00
2018-04-29
13:45:25
如您所见,日期时间字符串已转换为“America/New_York”区域。
现在,让我们再次使用我们在上面使用的同一组字符串:
import arrow
date_array = [
'2018-06-29 08:15:27.243860',
'2018-03-12T10:12:45Z',
'2018-06-29 17:08:00.586525+00:00',
'2018-06-29 17:08:00.586525+05:00',
]
for date in date_array:
dt = arrow.get(date)
print('Parsing: ' + date)
print(dt)
对于已被注释掉的日期时间字符串,此代码将失败,这超过了我们示例的一半。 其他字符串的输出将是:
Parsing: 2018-06-29 08:15:27.243860
2018-06-29T08:15:27.243860+00:00
Parsing: 2018-03-12T10:12:45Z
2018-03-12T10:12:45+00:00
Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29T17:08:00.586525+00:00
Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29T17:08:00.586525+05:00
为了正确解析被注释掉的日期时间字符串,你需要传递相应的 格式标记 为图书馆提供有关如何解析它的线索。
结论
在本文中,我们展示了将字符串解析为 datetime
Python 中的对象。 您可以选择默认的 Python datetime
库或本文中提到的任何第三方库,等等。
默认的主要问题 datetime
package 是我们需要为几乎所有的日期时间字符串格式手动指定解析代码。 因此,如果将来您的字符串格式发生变化,您可能也必须更改代码。 但是很多第三方库,比如这里提到的那些,会自动处理它。
我们面临的另一个问题是处理时区。 处理它们的最佳方法始终是将时间以 UTC 格式存储在数据库中,然后在需要时将其转换为用户的本地时区。
这些库不仅适用于解析字符串,还可以用于许多不同类型的日期时间相关操作。 我鼓励您仔细阅读文档以详细了解功能。