在 Python 中将字符串转换为日期时间

介绍

数据可以用多种形式表示——一种方便的表示日期和时间的方法是 字符串. 然而,要以算术方式处理这些日期和时间(例如计算时差、添加或删除时间等)——我们需要将它们转换为 datetime 目的。

最常见的来源之一 字符串格式的日期时间 是返回不可知字符串的 REST API,然后我们可以将其转换为其他格式。

此外,在处理日期时间对象时,时区是一个常见的头痛问题,因此我们在转换时也需要考虑到这一点。

在本指南中,我们将了解如何将字符串日期/时间转换为 datetime Python 中的对象,使用内置的 datetime 模块,还有第三方模块,例如 dateutil, arrow 和玛雅人,占时区。

使用日期时间转换字符串

日期时间 模块由三种不同的对象类型组成: date, timedatetime。 该 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 到“欧洲/伦敦”时区。 两个都 datetimes 将打印不同的值,使用 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_timezonenaive 如果时间不是 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 格式存储在数据库中,然后在需要时将其转换为用户的本地时区。

这些库不仅适用于解析字符串,还可以用于许多不同类型的日期时间相关操作。 我鼓励您仔细阅读文档以详细了解功能。

时间戳记:

更多来自 堆栈滥用