落入datetime.date 和 numpy.datetime64 的使用大坑
1. 不同模块日期的问题
数据加载模块和数据处理模块合并联调,发现落入datetime.date 和 numpy.datetime64 / pandas.Timestamp 的使用大坑 。
数据加载模块独立测试没有问题,数据处理模块独立测试没有问题。两者联调,问题不断,总体看就是从数据库加载到dataframe中,日期类型不一致,修改好一处错误,其他地方再出新错误,四处报错。
使用日期的地方,格式不统一,模块中都有各自日期格式转换,修改一处,另外的地方就出错 。
一系列错误:
TypeError: '>=' not supported between instances of 'datetime.date' and 'str'
TypeError: Expect data.index as DatetimeIndex
TypeError: input must have type NumPy datetime
AttributeError: 'numpy.datetime64' object has no attribute 'strftime'
重新梳理 datetime.date / numpy.datetime64 / pandas.Timestamp 的关系和区别 ,不同格式之间日期转换。
2. numpy.datetime64和datetime.date
在Python中,numpy.datetime64和datetime.date都用于表示日期,但它们属于不同的库,并且在使用上存在一些关键的区别。
(1)区别
库来源:
numpy.datetime64是NumPy库提供的数据类型,专门用于数组中的日期和时间数据。
datetime.date是Python标准库datetime模块中的一个类,用于表示日期(年、月、日)。
(2)功能
numpy.datetime64提供了丰富的日期和时间操作,并且非常适合在大型数组或矩阵中进行高效的数值计算。
datetime.date提供了更多的日期处理功能,比如格式化输出、与其他日期时间对象进行比较等。
(3)存储
numpy.datetime64在NumPy数组中是以一种紧凑的格式存储的,这有助于节省内存和提高计算效率。
datetime.date对象通常占用更多的内存,因为它们包含更多的方法和属性。
数组支持:
numpy.datetime64特别适用于NumPy数组,可以直接在数组上进行日期和时间的计算。
datetime.date对象不能直接存储在NumPy数组中,除非将其转换为object类型,这通常会降低计算效率。
(4)转换
将numpy.datetime64转换为datetime.date:
使用numpy.datetime64对象的.astype(object)方法将其转换为Python对象,然后使用datetime.date构造函数进行转换。
- datetime64 转date :
import numpy as np
from datetime import date
# 创建一个numpy.datetime64对象
np_date = np.datetime64('2023-01-01')
# 转换为datetime.date对象
dt_date = date(np_date.astype('O').year, np_date.astype('O').month, np_date.astype('O').day)
print(dt_date,type(dt_date))
结果:
2023-01-01 <class ‘datetime.date’>
- date 转 datetime64 :
import numpy as np
from datetime import date
# 创建一个datetime.date对象
dt_date = date(2023, 1, 1)
# 转换为numpy.datetime64对象
np_date = np.datetime64(dt_date)
print(np_date,type(np_date))
结果:
2023-01-01 <class ‘numpy.datetime64’>
(5)注意事项
当将numpy.datetime64对象转换为datetime.date对象时,注意numpy.datetime64对象可能包含时间信息,这部分信息在转换到datetime.date时会丢失。
如果numpy.datetime64对象包含时区信息,转换到datetime.date时也需要特别处理时区转换。
在实际应用中,选择使用哪种类型取决于具体需求。如果在处理大型数组并且需要高效的数值计算,numpy.datetime64可能是更好的选择。如果需要更多的日期处理功能,比如字符串格式化或与其他日期时间对象的比较,那么datetime.date可能更合适。
(6)datetime64 日期加减
在NumPy中,np.datetime64日期类型可以通过简单的算术运算来增加或减少天数。这是因为np.datetime64对象支持时间单位(如’D’表示天)的算术运算。
参数
np.timedelta64 的参数主要包括两部分:
单位数:一个整数或浮点数,表示时间单位的数量。
时间单位:一个字符串,表示时间单位,‘W’ 表示周, ‘D’ 表示天,‘h’ 表示小时,‘m’ 表示分钟,‘s’ 表示秒。
import numpy as np
# 创建一个np.datetime64日期
date = np.datetime64('2023-01-01')
# 加一天
date_plus_one_day = date + np.timedelta64(1, 'D')
print(date_plus_one_day) # 输出:2023-01-02
# 减一天
date_minus_one_day = date - np.timedelta64(1, 'D')
print(date_minus_one_day) # 输出:2022-12-31
# 加一周
date_plus_one_day = date + np.timedelta64(1, 'W')
print(date_plus_one_day) # 输出:2023-01-08
# 减一周
date_minus_one_day = date - np.timedelta64(1, 'W')
print(date_minus_one_day) # 输出:2022-12-25
增加一个月、年,需要用pd.Timestamp
import pandas as pd
import numpy as np
# 创建一个 datetime64 对象表示某个日期
date = np.datetime64('2024-01-01')
# 将 numpy 的 datetime64 转换为 pandas 的 Timestamp
timestamp = pd.Timestamp(date)
# 使用 pandas 添加一个月
new_date_plus_month = timestamp + pd.DateOffset(months=1)
# 使用 pandas 添加一年
new_date_plus_year = timestamp + pd.DateOffset(years=1)
# 将 pandas 的 Timestamp 转换回 numpy 的 datetime64(如果需要)
new_date_plus_month_np = new_date_plus_month.to_datetime64()
new_date_plus_year_np = new_date_plus_year.to_datetime64()
print(new_date_plus_month_np) # 输出添加一个月后的日期
print(new_date_plus_year_np) # 输出添加一年后的日期
结果:
2024-02-01T00:00:00
2025-01-01T00:00:00
3.pandas.Timestamp和numpy.datetime64
pandas.Timestamp和numpy.datetime64都是用于表示日期和时间的类型,但它们来自不同的库(Pandas和NumPy),并且在功能和使用上存在一些重要的区别。
(1)pandas.Timestamp
pandas.Timestamp是Pandas库中用于表示单个时间点的主要类型。它提供了比numpy.datetime64更丰富的功能集,尤其是在处理时间序列数据时。
-
特点:
-
时区支持:pandas.Timestamp可以包含时区信息,这使得处理跨越多个时区的数据变得相对简单。
-
频率和偏移:它支持日期时间的频率和偏移,如“日”、“月”、“季度”等,使得时间序列的生成和重采样变得容易。
-
纳秒级精度:默认情况下,pandas.Timestamp提供纳秒级的时间精度。
-
字符串格式化:pandas.Timestamp对象可以很容易地格式化为各种字符串表示形式,这对于报告和可视化非常有用。
-
-
操作:支持与其他pandas.Timestamp对象进行算术运算(如加、减)。
-
使用:
pandas.Timestamp通常用于Pandas的Series和DataFrame中,尤其是在时间序列分析中。它使得数据的索引、切片、重采样等操作变得简单。
(2)numpy.datetime64
numpy.datetime64是NumPy库中用于表示日期和时间的类型。它主要用于数值计算和科学计算。
-
特点:
-
高效性:numpy.datetime64在NumPy数组中的存储和计算是高效的,特别适用于大规模数据的处理。
-
固定精度:它支持不同的时间单位(如’D’表示天,'s’表示秒等),但一旦数据类型被确定,精度就是固定的。
-
算术运算:支持与其他numpy.datetime64对象或numpy.timedelta64对象进行算术运算。
-
兼容性:与Python的内置datetime对象相比,numpy.datetime64更易于在NumPy数组中进行操作。
-
-
使用:
numpy.datetime64通常用于需要高效数值计算的场合,特别是在处理包含日期时间数据的NumPy数组时。它也可以与其他NumPy函数和工具无缝集成,用于数据分析和科学计算。
- 区别与选择
在选择使用pandas.Timestamp还是numpy.datetime64时,主要取决于具体需求和你正在使用的库。如果处理时间序列数据,特别是使用Pandas进行数据分析时,pandas.Timestamp通常是更好的选择,因为它提供了更丰富的功能集。而如果进行科学计算或需要高效处理大规模日期时间数据时,numpy.datetime64可能更合适。
**注意:**虽然两者在功能上有所不同,但它们在许多情况下可以相互转换。例如,你可以将pandas.Timestamp转换为numpy.datetime64对象,反之亦然。
(3)相互转换
pandas.Timestamp对象和numpy.datetime64对象可以相互转换,因为它们在内部都表示日期和时间信息。以下是它们之间转换的方法:
将pandas.Timestamp转换为numpy.datetime64
可以直接使用pandas.Timestamp对象的.to_datetime64()方法或者简单地将它转换为numpy.datetime64类型。
- Timestamp 转 datetime64
import pandas as pd
import numpy as np
# 创建一个pandas.Timestamp对象
ts = pd.Timestamp('2023-01-01')
# 使用.to_datetime64()方法转换
np_dt64 = ts.to_datetime64()
# 或者直接转换类型
np_dt64_direct = np.datetime64(ts)
print(ts,type(ts)) # 输出:2023-01-01 00:00:00
print(np_dt64,type(np_dt64)) # 输出:2023-01-01T00:00:00
print(np_dt64_direct,type(np_dt64_direct)) # 输出:2023-01-01T00:00:00.000000000
结果:
2023-01-01 00:00:00 <class ‘pandas._libs.tslibs.timestamps.Timestamp’>
2023-01-01T00:00:00 <class ‘numpy.datetime64’>
2023-01-01T00:00:00.000000 <class ‘numpy.datetime64’>
注意:
pd的Timestamp 转换datetime64 ,和 np直接转换datetime64 ,精度不同。
- datetime64 转 Timestamp
import pandas as pd
import numpy as np
# 创建一个numpy.datetime64对象
np_dt64 = np.datetime64('2023-01-01')
# 转换为pandas.Timestamp对象
ts = pd.Timestamp(np_dt64)
print(ts) # 输出:2023-01-01 00:00:00
结果:
2023-01-01 00:00:00
4.datetime.datetime
datetime.datetime 是 Python 标准库 datetime 模块中的一个类,它提供了丰富的日期和时间操作功能。下面是
(1)datetime.datetime 的主要特点:
- 日期和时间表示:datetime.datetime 对象可以同时表示日期和时间,包括年、月、日、时、分、秒、微秒。
- 时区支持:虽然基本的 datetime.datetime 对象不直接支持时区,但可以使用 datetime.timezone 和 datetime.timedelta 类来处理时区相关的计算。
- 算术运算:datetime.datetime 对象支持加法和减法运算,可以方便地进行日期和时间的偏移。
- 格式化:可以方便地将 datetime.datetime 对象转换为字符串,也可以将字符串解析为 datetime.datetime 对象。
(2) 日期转换为字符串
要将 datetime.datetime 对象转换为字符串,可以使用 strftime 方法,该方法允许你指定输出的格式。
- 日期转字符串
import datetime
# 创建一个 datetime 对象
now = datetime.datetime.now()
# 转换为字符串
formatted_date = now.strftime('%Y-%m-%d %H:%M:%S')
print(formatted_date) # 输出类似于 "2024-03-08 10:39:26" 的字符串
结果:
2024-03-08 10:39:26
(3) 字符串转换为日期
- 字符串转日期
import datetime
# 字符串表示的日期和时间
date_str = '2023-03-15 14:30:45'
# 解析字符串为 datetime 对象
parsed_date = datetime.datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S')
print(parsed_date) # 输出 datetime 对象
结果:
2023-03-15 14:30:45
(4)日期加减
# 创建一个 datetime 对象
now = datetime.datetime.now()
# 增加一天
one_day_later = now + datetime.timedelta(days=1)
print(one_day_later,type(one_day_later)) # 输出一天后的日期和时间
ios_str = one_day_later.isoformat()
print(ios_str,type (ios_str)) # 输出一天后的日期和时间
import datetime
# 创建一个 datetime 对象
now = datetime.datetime.now()
# 增加一周
one_week_later = now + datetime.timedelta(weeks=1)
print(one_week_later) # 输出一周后的日期和时间
date_week = one_week_later.date()
print(date_week,type(date_week)) # 输出一周后的日期
结果:
2024-03-09 10:46:49.783701 <class ‘datetime.datetime’>
2024-03-09T10:46:49.783701 <class ‘str’>
2024-03-15 10:46:49.784441
2024-03-15 <class ‘datetime.date’>
(5)pandas.Timestamp转换datetime
使用to_pydatetime方法转换datetime 。
ts = pd.Timestamp('2020-05-20 00:00:00', tz=None)
print(type(ts))
print(ts)
print(type(ts.to_pydatetime()))
print(ts.to_pydatetime())
结果:
<class ‘pandas._libs.tslibs.timestamps.Timestamp’>
2020-05-20 00:00:00
<class ‘datetime.datetime’>
2020-05-20 00:00:00