课程
在 Python 中,字符串是一种常见的数据类型,常用于表示日期和时间。但作为数据科学家和工程师,我们经常需要将这些字符串转换为 datetime 对象,以便执行排序、比较等各类操作。
将字符串转换为 datetime 对象可能有些棘手,尤其对 Python 新手而言。因此,在本文中,我将带您一步步掌握这些方法的用法,并在过程中提供代码示例。无论您是经验丰富的开发者,还是刚刚起步的学习者,让我们一起走进 Python 中的 datetime 世界!
若想轻松运行本教程的所有示例代码,您可以免费创建一个 DataLab 工作簿,其中已预装 Python 并包含所有代码示例。想进一步练习如何将字符串转换为 datetime 对象,请查看这道 DataCamp 实战练习。
要点速览
使用 datetime.strptime(date_string, format) 在 Python 中将字符串转换为 datetime 对象。若无需格式字符串的更灵活解析,使用 dateutil.parser.parse()。对于 DataFrame,pd.to_datetime() 可高效处理整列数据。关键格式代码:%Y(四位年份)、%m(月份)、%d(日期)、%H(小时)、%M(分钟)、%S(秒)。
Python datetime 模块简介
datetime 模块是 Python 内置 的模块,适用于所有使用 Python 构建的应用中需要处理日期、时间或时间间隔的场景。它提供了便捷的类与方法来表示和操作日期时间数据。
表 1:datetime 模块中的类与方法概览
| 类/方法 | 用途 | 常见用例 |
|---|---|---|
| datetime.date | 表示日期(年、月、日)。 | 计算日期差、将日期格式化为字符串、提取日期组成部分。 |
| datetime.time | 表示一天中的时间(时、分、秒、微秒)。 | 比较时间、将时间格式化为字符串、提取时间组成部分。 |
| datetime.datetime | 表示日期和时间,结合了 date 与 time 的功能。 | 处理时间序列数据、提取日期与时间组成部分、格式化为字符串。 |
| datetime.timedelta | 表示两个日期或时间之间的差(时长)。 | 对日期或时间加/减时长、计算时间间隔。 |
| datetime.strptime() | 根据指定格式将字符串解析为 datetime 对象。 | 将字符串转换为 datetime 对象以便进一步操作与分析。 |
| datetime.strftime() | 根据指定格式将 datetime 对象格式化为字符串。 | 将 datetime 对象转换为便于展示或报告的人类可读字符串。 |
让我们了解该模块下的主要类,后续我们将把数据转换为这些 datetime 对象:
1. datetime.date
该类表示日期(年、月、日),并提供了处理日期的方法,例如计算两个日期的差、将日期格式化为字符串等。
假设我们有一个包含公司每日股价的数据集。我们可以使用 date 类从数据集中提取日期,并绘制股价随时间的变化。
以下是一个展示 date 类用法的代码片段:
from datetime import date
# create a date object representing March 1, 2023
start_date = date(2023, 3, 1)
# extract information such as the year, month, and day
year = start_date.year
month = start_date.month
day = start_date.day
# get the day of the week (Note: Monday is coded as 0, and Sunday as 6)
weekday = start_date.weekday()
# the date can be formatted as a string if needed
date_str = start_date.strftime('%Y-%m-%d')
2. datetime.time
该类表示一天中的时间(时、分、秒、微秒),并提供了处理时间的方法,例如比较时间、将时间格式化为字符串等。
比如我们有一个包含比赛完赛时间的数据集;我们可以使用 time 类提取每位参赛者的完赛小时和分钟。
from datetime import time
# create a time object with the microsecond granularity
end_time = time(15, 45, 30, 500000)
# get the hour and minute
hour = end_time.hour
minute = end_time.minute
second = end_time.second
microsecond = end_time.microsecond
3. datetime.datetime
该类同时表示日期与时间,并提供处理两者的方法。它结合了 date 与 time 类的功能。
它常用于包含高时间分辨率(如按小时或分钟)的时间序列数据分析任务。假设我们有一个包含某城市每小时用电需求的数据集。我们可以使用 datetime 类从数据集中提取日期与时间,并绘制用电需求随时间的变化。关于此类数据的可视化,请参阅我们的Matplotlib 时间序列折线图教程。
from datetime import datetime
# create a datetime object representing March 1, 2023 at 9:30 AM
start_datetime = datetime(2023, 3, 1, 9, 30)
# get the year, month, day, hour, and minute
year = start_datetime.year
month = start_datetime.month
day = start_datetime.day
hour = start_datetime.hour
minute = start_datetime.minute
4. datetime.timedelta
该类表示一段时长或时间间隔,并提供处理时间间隔的方法,例如对日期或时间加减时间间隔。
假设我们有一个包含一组事件起止时间的数据集,想要计算所有事件的总时长。我们可以使用 timedelta 类计算每个事件的持续时间并将其求和。
from datetime import timedelta
# create a timedelta object representing 3 hours and 15 minutes
event_duration = timedelta(hours=3, minutes=15)
# get the total duration in seconds
event_duration_seconds = event_duration.total_seconds()
# add the duration to a start time to get an end time
event_start_time = datetime(2023, 3, 1, 18, 15)
event_end_time = event_start_time + event_duration
在上述所有案例中,我们都使用了 datetime 对象,但现实世界中的数据往往以字符串形式存在。将其转换为 datetime 对象,才能解锁上述在数据科学分析与应用中非常强大的功能。
使用 datetime.strptime() 进行日期时间转换
在 Python 中,我们可以使用 datetime.strptime() 方法将字符串转换为 datetime 对象。strptime() 方法接受两个参数:要转换的字符串,以及用于指定输入字符串格式的格式字符串。
格式字符串由一组格式化代码组合而成,用以表示日期与时间的各个组成部分。 以下是一些最常用的格式代码(在Python 字符串格式化中也有类似概念):
表 2:常用日期时间格式化代码
| 格式代码 | 说明 | 示例输入 | 示例输出 |
|---|---|---|---|
| %Y | 四位年份 | 2023 | 2023 |
| %y | 两位年份 | 23 | 23 |
| %m | 两位月份(01-12) | 03 | 03 |
| %d | 两位日期(01-31) | 15 | 15 |
| %H | 两位小时(00-23) | 14 | 14 |
| %I | 两位小时(01-12) | 02 | 02 |
| %M | 两位分钟(00-59) | 45 | 45 |
| %S | 两位秒(00-59) | 30 | 30 |
| %f | 微秒(000000-999999) | 123456 | 123456 |
| %p | AM 或 PM | PM | PM |
| %z | UTC 偏移 | +0530 | +0530 |
| %a | 星期缩写 | Tue | Tue |
| %A | 星期全称 | Tuesday | Tuesday |
| %b | 月份缩写 | Mar | Mar |
| %B | 月份全称 | March | March |
| %j | 一年中的第几天(001-366) | 074 | 074 |
| %U | 一年中的第几周(周日为一周的第一天) | 10 | 10 |
| %W | 一年中的第几周(周一为一周的第一天) | 09 | 09 |
理解了这些 strptime 指令后,将字符串转换为 datetime 对象的流程就更简单了。
- 步骤 01:分析要转换的日期时间字符串,找出与格式代码匹配的模式。
- 步骤 02:根据 strptime() 指令构建日期时间格式字符串。
- 步骤 03:将字符串与格式传入函数,得到对象作为输出。
让我们把这些步骤付诸实践。
将特定格式的字符串转换为 datetime 对象
from datetime import datetime
# Example with the standard date and time format
date_str = '2023-02-28 14:30:00'
date_format = '%Y-%m-%d %H:%M:%S'
date_obj = datetime.strptime(date_str, date_format)
print(date_obj)
# Example with a different format
date_str = '02/28/2023 02:30 PM'
date_format = '%m/%d/%Y %I:%M %p'
date_obj = datetime.strptime(date_str, date_format)
print(date_obj)
在第一个示例中,字符串采用 “YYYY-MM-DD HH:MM:SS” 格式;第二个示例使用另一种 “MM/DD/YYYY HH:MM AM/PM” 格式。
两种情况下,我们都需要将正确的格式字符串作为 strptime() 的第二个参数,才能得到正确的 datetime 对象。
将包含时区信息的字符串转换为 datetime 对象
from datetime import datetime
date_str = '2023-02-28 14:30:00+05:30'
date_format = '%Y-%m-%d %H:%M:%S%z'
date_obj = datetime.strptime(date_str, date_format)
print(date_obj)
此示例中的字符串包含时区信息,格式为 “YYYY-MM-DD HH:MM:SS+TZOFFSET”,其中 TZOFFSET 表示相对于 UTC 的时区偏移(小时与分钟)。我们将格式字符串作为 strptime() 的第二个参数,并包含 %z 格式代码以解析时区偏移。
尽管理论上上述函数看起来很简单,但在实践中,当出现问题时也可能令人挫败。
使用 dateutil 在不提供格式字符串的情况下解析日期
另一个灵活的选项是 dateutil 库,尤其是 parser.parse() 函数。它会自动检测日期格式,使您无需指定格式字符串即可解析字符串。
from dateutil.parser import parse
# Automatically infers the format
date_obj = parse("March 1, 2023 9:30 AM")
print(date_obj)
当需要处理不可预测或不一致的日期格式时,这种方法尤为有用。
处理时区
对于具备时区感知的 datetime 处理,Python 提供了两个常用选项:
-
pytz(广泛使用,并兼容较旧版本)
-
zoneinfo(Python 3.9 引入,属标准库)
from datetime import datetime
from zoneinfo import ZoneInfo
# Using zoneinfo
dt = datetime(2023, 3, 1, 9, 30, tzinfo=ZoneInfo("America/New_York"))
print(dt)
# Using pytz (alternative)
import pytz
tz = pytz.timezone("America/New_York")
dt_pytz = tz.localize(datetime(2023, 3, 1, 9, 30))
print(dt_pytz)
这些工具可为您设置时区、在不同时区间转换,并自动考虑夏令时。
夏令时注意事项
在处理具备时区感知的 datetime 时,夏令时(DST)可能带来复杂性——尤其在时钟向前或向后调整时。
当您分配了合适的时区时,zoneinfo 与 pytz 等库会自动处理 DST 的切换:
from datetime import datetime
from zoneinfo import ZoneInfo
# Before and after DST starts
before_dst = datetime(2023, 3, 12, 1, 30, tzinfo=ZoneInfo("America/New_York"))
after_dst = datetime(2023, 3, 12, 3, 30, tzinfo=ZoneInfo("America/New_York"))
print(before_dst)
print(after_dst)
这样可以确保 datetime 计算在 DST 变化期间仍然准确。
使用 pandas 进行日期时间转换
尽管 Python 自带的 datetime 模块功能强大,许多数据科学家更倾向于使用 pandas 库进行日期时间转换,因为它简单易用,并且可借助DataFrame高效处理整列日期。
import pandas as pd
# Converting a column of strings to datetime objects
date_series = pd.to_datetime(['2023-02-28', '2023-03-01', '2023-03-02'])
print(date_series)
Pandas 会自动推断格式并优雅地处理常见不一致性,因此在处理表格数据时是首选。更多内容参见我们的pandas 数据准备指南。
使用 strftime() 将 datetime 对象格式化为字符串
当您已将字符串转换为 datetime 对象并完成所需操作后,可能需要再将其转换回字符串。您可以使用 datetime.strftime() 来实现。
from datetime import datetime
now = datetime.now()
formatted = now.strftime('%Y-%m-%d %H:%M:%S')
print(formatted)
此方法让您能够完全掌控 datetime 对象以字符串形式的呈现方式。
常见 strptime() 错误排查
以下是您可能遇到的一些常见错误及其修复方法。更多关于Python 异常处理的内容,请参见我们的专门教程:
ValueError: time data 'date_string' does not match format '%Y-%m-%d %H:%M:%S'
最常见的错误发生在输入字符串与格式字符串不匹配时。请仔细检查输入字符串与格式字符串是否完全一致。
import datetime
# When using 4-digit year format but input has 2-digit year
date_str = '23-03-01'
date_obj = datetime.datetime.strptime(date_str, '%Y-%m-%d') # Wrong: %Y expects 4 digits
# Raises ValueError: time data '23-03-01' does not match format '%Y-%m-%d'
# When format doesn't match separator in string
time_str = '08:30:00'
time_obj = datetime.datetime.strptime(time_str, '%H-%M-%S') # Wrong: using - instead of :
# Raises ValueError: time data '08:30:00' does not match format '%H-%M-%S'
TypeError: strptime() argument 1 must be str, not 'int'
另一个常见错误是在调用 datetime.strptime() 或 time.strptime() 时传入了整数而非字符串。请确保传入函数的所有值都是字符串。
# Example 1: Integer instead of string
date_int = 20230301
date_obj = datetime.datetime.strptime(date_int, '%Y%m%d')
# Raises TypeError: strptime() argument 1 must be str, not int
# Example 2: List instead of string
date_list = [2023, 3, 1]
date_obj = datetime.datetime.strptime(date_list, '%Y-%m-%d')
# Raises TypeError: strptime() argument 1 must be str, not list
ValueError: unconverted data remains: ':00'
当输入字符串中存在未被格式字符串匹配的剩余字符时,会出现此错误。比如,如果格式字符串只指定了年、月、日,而输入字符串还包含了时间信息,就会报错。要调试此错误,请确保格式字符串覆盖整个输入字符串。
# when input string contains time of day
date_str = '2023-03-01 12:30:00'
date_obj = datetime.datetime.strptime(date_str, '%Y-%m-%d')
# Raises ValueError: unconverted data remains: 12:30:00
# When input string contains extra characters
date_str = '2023-03-01T00:00:00Z'
date_obj = datetime.datetime.strptime(date_str, '%Y-%m-%d')
# Raises ValueError: unconverted data remains: T00:00:00Z
结语
可以肯定的是,datetime.strptime() 方法为在 Python 中将字符串转换为 datetime 对象提供了灵活而强大的途径,并能处理多种日期时间格式。不妨收藏我们的日期与时间速查表以备后用。
理解日期与时间之后,下一步是在项目中加以练习。我们建议您选择以下之一来巩固所学:
我们同意,真实世界中的日期和时间数据很复杂,但您所需要做的,就是理解数据中各类日期时间背后的格式与模式,并善用手边的库。
常见问题
如何在同一数据集中处理混合日期格式的字符串?
在处理包含混合日期格式的数据集时,您可以使用 Python 的 dateutil 模块。dateutil.parser.parse() 比 datetime.strptime() 更灵活,因为它能在无需预定义格式字符串的情况下自动检测并解析多种日期格式:
from dateutil.parser import parse
date_str1 = '2023-03-01'
date_str2 = 'March 1, 2023'
date_obj1 = parse(date_str1)
date_obj2 = parse(date_str2)
print(date_obj1) # Output: 2023-03-01 00:00:00
print(date_obj2) # Output: 2023-03-01 00:00:00在考虑不同时区的情况下,我能将字符串转换为 datetime 对象吗?
可以。您可以将 pytz 库与 datetime 结合使用来处理时区。首先将字符串转换为 datetime 对象,然后通过 pytz.timezone() 附加时区:
from datetime import datetime
import pytz
date_str = '2023-03-01 14:30:00'
date_format = '%Y-%m-%d %H:%M:%S'
date_obj = datetime.strptime(date_str, date_format)
# Set time zone
timezone = pytz.timezone('US/Eastern')
date_obj_tz = timezone.localize(date_obj)
print(date_obj_tz) # Output: 2023-03-01 14:30:00-05:00datetime.strptime() 与 datetime.fromisoformat() 有何区别?
datetime.strptime() 允许您指定自定义格式字符串以解析非标准或多样的日期格式。
datetime.fromisoformat() 专门用于解析 ISO 8601 格式的日期字符串(例如 '2023-03-01T14:30:00')。如果您的字符串严格遵循 ISO 8601 标准,它会更简单易用:
from datetime import datetime
iso_date_str = '2023-03-01T14:30:00'
date_obj = datetime.fromisoformat(iso_date_str)
print(date_obj) # Output: 2023-03-01 14:30:00如何在 Python 中将 datetime 对象转换回字符串?
使用 strftime() 方法可将 datetime 对象转换回字符串。传入一个格式字符串来指定输出的呈现方式:
from datetime import datetime
dt = datetime(2023, 3, 1, 14, 30)
date_string = dt.strftime('%Y-%m-%d %H:%M:%S')
print(date_string) # Output: 2023-03-01 14:30:00格式代码与 strptime() 使用的相同,这使得字符串与 datetime 对象之间的往返转换更加方便。
在 Python 中,strptime() 与 strftime() 有何区别?
strptime() 与 strftime() 是相反的操作:
strptime()("string parse time")将字符串转换为 datetime 对象。它接收字符串和格式作为参数。strftime()("string format time")将datetime 对象转换为字符串。它根据指定的格式字符串对 datetime 进行格式化。
一个好记的口诀:strptime() 负责“解析”字符串,而 strftime() 负责“格式化”为字符串。
作为一名高级数据科学家,我设计、开发并部署大规模机器学习解决方案,帮助企业做出更明智的数据驱动决策。作为数据科学写作者,我分享所学心得、职业建议以及深入的实践型教程。
