直接用datetime64创建数组易出错,因必须显式指定单位(如'D'、's'),缺省为'Y'导致精度丢失;字符串需ISO格式且单位统一,否则引发TypeError或静默截断。

为什么直接用 datetime64 创建数组容易出错
NumPy 的 datetime64 不是 Python 原生 datetime,它必须指定单位(如 'D'、's'、'ms'),缺单位会默认为 'Y'(年),导致精度丢失或意外截断。比如 np.array(['2023-01-01', '2023-01-02']) 生成的是 datetime64[Y],所有时间信息只剩年份。
常见错误现象:TypeError: Cannot convert input to timestamp 或数值计算结果为 0(因单位不匹配,减法返回“年差”而非“天数”)。
- 始终显式指定单位:用
dtype='datetime64[D]'而非依赖推断 - 字符串输入需 ISO 格式(
'2023-01-01'、'2023-01-01T12:30'),含时分秒时单位至少用's'或'ms' - 避免混用单位:同一数组内所有元素必须统一单位,否则强制转换可能静默截断
如何正确生成带频率的时间序列(类似 pandas.date_range)
np.arange 是 NumPy 原生方案,但参数逻辑和 pandas 不同:它接受起止值 + 步长(不是频率字符串),且步长必须是 timedelta64 类型。
例如生成 2023 年每天一个时间点:
dates = np.arange('2023-01-01', '2023-01-10', dtype='datetime64[D]')
若要按小时生成,单位需升为 'h',并确保起止值能被整除:
hours = np.arange('2023-01-01T00', '2023-01-02T00', dtype='datetime64[h]')
- 起始值包含单位信息,所以
'2023-01-01T00'比'2023-01-01'更安全(明确到小时) - 不能写
np.arange(..., step='1D')——step必须是timedelta64,如np.timedelta64(1, 'D') - 跨月/年时注意边界:
np.arange('2023-01-30', '2023-02-05', dtype='datetime64[D]')没问题,但dtype='datetime64[M]'会只保留年月,丢弃日
datetime64 数组参与计算时的单位陷阱
两个 datetime64 相减得到 timedelta64,但结果单位取决于两者中**更精细的单位**。比如 datetime64[D] 减 datetime64[s],结果是 timedelta64[s];而 datetime64[D] 减 datetime64[D] 得到 timedelta64[D] —— 这意味着你不能直接对 [D] 数组做除法换算成小时,除非先转换单位。
常见需求:把天数差转为小时数
d1 = np.datetime64('2023-01-02')
d2 = np.datetime64('2023-01-01')
diff_days = d1 - d2 # timedelta64[D]
diff_hours = diff_days / np.timedelta64(1, 'h') # 得到 24.0
- 别用
int(diff_days)强转 —— 它返回的是以“基准单位”计的整数,可能不是你想要的尺度 - 做比较(如
arr > np.datetime64('2023'))时,右侧必须与arr单位一致,否则报TypeError: invalid type promotion - 广播运算中,标量 datetime 若未指定单位,会被推断为数组单位;但显式写
np.datetime64('2023-01-01', 'D')更可靠
读取 CSV 时间列时如何避免自动转成 object
用 np.loadtxt 或 np.genfromtxt 读 CSV 时间列,默认会当成字符串(object dtype),后续无法直接计算。必须用 converters 参数配合 datetime64 构造函数。
例如 CSV 第 0 列是 '2023-01-01' 格式:
data = np.genfromtxt('times.csv', delimiter=',',
converters={0: lambda x: np.datetime64(x.decode(), 'D')},
dtype=None, encoding=None)
注意:传入的字符串是 bytes,需 .decode();且构造函数第二个参数单位不能省略。
-
np.loadtxt不支持converters,必须用genfromtxt - 如果时间格式不统一(有带时分秒、有不带),统一转成最细粒度单位(如
's'),再用.astype('datetime64[D]')向上取整 - 遇到解析失败(如空值、非法格式),
genfromtxt默认填np.nan,但datetime64不支持np.nan,会变成NaT(Not a Time)——这是合法的缺失值表示,可用np.isnat()检测
实际使用中,最易被忽略的是单位一致性:从创建、读取、计算到输出,每个环节都要确认当前 datetime64 的单位是否是你预期的,而不是靠打印看“长得像”。一旦单位错,数值就错,而且往往不报错。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











