NumPy: 日期时间
难度:⭐⭐ | 关键词:
np.datetime64,np.timedelta64,np.arange,np.busday_count,np.is_busday
Alice 需要计算"实际工作日"——去掉周末。np.busday_count 直接搞定:"datetime64 精度从年到纳秒,busday 是金融/项目管理的时间利器。"
1. datetime64 创建与精度
np.datetime64(date_string, unit) 创建日期时间标量;精度由 unit 决定。
(1) 精度单位
| 单位 | 缩写 | 示例 | 含义 |
|---|---|---|---|
| 年 | Y |
np.datetime64('2024','Y') |
2024 年 |
| 月 | M |
np.datetime64('2024-06','M') |
2024 年 6 月 |
| 周 | W |
np.datetime64('2024-01-01','W') |
2024 年第 1 周 |
| 天 | D |
np.datetime64('2024-06-15') |
2024 年 6 月 15 日 |
| 时 | h |
np.datetime64('2024-06-15T10') |
10 时 |
| 分 | m |
np.datetime64('2024-06-15T10:30') |
10 时 30 分 |
| 秒 | s |
np.datetime64('2024-06-15T10:30:00') |
整秒 |
| 毫秒 | ms |
np.datetime64('2024-06-15T10:30:00.123','ms') |
毫秒精度 |
| 微秒 | us |
np.datetime64('2024-06-15T10:30:00.123456','us') |
微秒精度 |
| 纳秒 | ns |
np.datetime64('2024-06-15T10:30:00.123456789','ns') |
纳秒精度 |
(2) datetime64 vs Python datetime
| 特性 | np.datetime64 |
Python datetime |
|---|---|---|
| 向量化运算 | ✅ 原生数组支持 | ❌ 逐个操作 |
| 精度范围 | 年 ~ 纳秒(10 种) | 天 ~ 微秒(3 种) |
| 缺失值表示 | NaT |
None |
| 时区支持 | ❌ 无 | ✅ timezone |
| NumPy 函数兼容 | ✅ | ❌ |
▶ 示例
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
:datetime64 创建(难度⭐)
PYTHON
import numpy as np
d1 = np.datetime64('2024-06-15')
print(d1) # 2024-06-15
print(d1.dtype) # datetime64[D]
d2 = np.datetime64('2024-06', 'M')
print(d2) # 2024-06
print(d2.dtype) # datetime64[M]
d3 = np.datetime64('2024-06-15T10:30:00')
print(d3) # 2024-06-15T10:30:00
print(d3.dtype) # datetime64[s]
nat = np.datetime64('NaT')
print(nat) # NaT
print(np.isnat(nat)) # True
dates = np.array(['2024-01-01', '2024-06-15', '2024-12-31'],
dtype='datetime64[D]')
print(dates)
# ['2024-01-01' '2024-06-15' '2024-12-31']
print(dates.dtype) # datetime64[D]
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
2. timedelta64 — 时间差
np.timedelta64(value, unit) 表示时间间隔,是 datetime64 运算的基础。
(1) 运算规则
| 运算 | 结果类型 | 示例 |
|---|---|---|
| datetime64 - datetime64 | timedelta64 | '2024-06-15' - '2024-01-01' → 166D |
| datetime64 + timedelta64 | datetime64 | '2024-01-01' + 30D → '2024-01-31' |
| timedelta64 + timedelta64 | timedelta64 | 10D + 5D → 15D |
| timedelta64 * int | timedelta64 | 7D * 3 → 21D |
| timedelta64 / timedelta64 | float | 30D / 7D → 4.285... |
▶ 示例
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
:timedelta64 运算(难度⭐)
PYTHON
import numpy as np
d1 = np.datetime64('2024-06-15')
d2 = np.datetime64('2024-01-01')
diff = d1 - d2
print(diff) # 166 days
print(diff.dtype) # timedelta64[D]
future = d1 + np.timedelta64(30, 'D')
print(future) # 2024-07-15
past = d1 - np.timedelta64(1, 'W')
print(past) # 2024-06-08
td1 = np.timedelta64(10, 'D')
td2 = np.timedelta64(5, 'D')
print(td1 + td2) # 15 days
print(td1 * 3) # 30 days
print(td1 / td2) # 2.0
hours = np.timedelta64(2, 'h')
print(d1 + hours) # 2024-06-15T02 (精度自动提升)
nat_td = np.timedelta64('NaT', 'D')
print(np.isnat(nat_td)) # True
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
3. 日期运算
datetime64 数组支持向量化运算:比较、排序、差分等。
(1) 运算方式对比
| 运算 | Python datetime | np.datetime64 |
|---|---|---|
| 日期差 | (d2 - d1).days |
d2 - d1 → timedelta64 |
| 向量化比较 | 列表推导 | dates > threshold |
| 排序 | sorted() |
np.sort() |
| 差分 | 循环 | np.diff() |
| 最值 | min()/max() |
np.min()/np.max() |
▶ 示例
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
:日期运算(难度⭐⭐)
PYTHON
import numpy as np
dates = np.array(['2024-01-01', '2024-03-15', '2024-06-01',
'2024-09-01', '2024-12-31'], dtype='datetime64[D]')
print(np.min(dates)) # 2024-01-01
print(np.max(dates)) # 2024-12-31
deltas = np.diff(dates)
print(deltas)
# [74 78 93 121] days
deadline = np.datetime64('2024-06-30')
mask = dates < deadline
print(dates[mask])
# ['2024-01-01' '2024-03-15' '2024-06-01']
sorted_idx = np.argsort(dates)
print(dates[sorted_idx] == dates) # True (已有序示例)
q1_end = np.datetime64('2024-03-31')
q2_end = np.datetime64('2024-06-30')
q3_end = np.datetime64('2024-09-30')
in_q2 = (dates > q1_end) & (dates <= q2_end)
print(dates[in_q2])
# ['2024-06-01']
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
4. 日期范围生成
np.arange(start, stop, step, dtype=datetime64[...]) 生成日期序列。
▶ 示例
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
:日期范围(难度⭐⭐)
PYTHON
import numpy as np
days = np.arange('2024-01-01', '2024-01-08', dtype='datetime64[D]')
print(days)
# ['2024-01-01' '2024-01-02' '2024-01-03' '2024-01-04'
# '2024-01-05' '2024-01-06' '2024-01-07']
months = np.arange('2024-01', '2025-01', dtype='datetime64[M]')
print(months)
# ['2024-01' '2024-02' '2024-03' ... '2024-12']
quarters = np.arange('2024-01', '2025-01', 3, dtype='datetime64[M]')
print(quarters)
# ['2024-01' '2024-04' '2024-07' '2024-10']
weekly = np.arange('2024-01-01', '2024-02-01', dtype='datetime64[W]')
print(weekly)
# ['2024-01-04' '2024-01-11' '2024-01-18' '2024-01-25']
hours = np.arange('2024-06-15T09', '2024-06-15T18', dtype='datetime64[h]')
print(hours)
# ['2024-06-15T09' '2024-06-15T10' ... '2024-06-15T17']
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
5. busday — 工作日计算
np.busday_count、np.is_busday、np.busday_offset 构成工作日工具集。
(1) busday 函数速查
| 函数 | 功能 | 关键参数 |
|---|---|---|
np.busday_count(beg, end) |
计算工作日天数 | weekmask, holidays |
np.is_busday(dates) |
判断是否工作日 | weekmask, holidays |
np.busday_offset(dates, offsets) |
偏移 N 个工作日 | roll, weekmask, holidays |
(2) weekmask 参数
| 格式 | 示例 | 含义 |
|---|---|---|
| 字符串 | '1111100' |
周一至周五上班 |
| 字符串 | '1111110' |
周一至周六上班 |
| 列表 | [1,1,1,1,1,0,0] |
同上 |
▶ 示例
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
:busday 工作日(难度⭐⭐)
PYTHON
import numpy as np
b1 = np.datetime64('2024-01-01')
b2 = np.datetime64('2024-01-31')
print(np.busday_count(b1, b2)) # 22
print(np.is_busday(np.datetime64('2024-01-06'))) # False (周六)
print(np.is_busday(np.datetime64('2024-01-08'))) # True (周一)
holidays = ['2024-01-01', '2024-01-02']
print(np.busday_count(b1, b2, holidays=holidays)) # 20
roll_forward = np.busday_offset(np.datetime64('2024-01-06'), 0, roll='forward')
print(roll_forward) # 2024-01-08 (跳到下一个工作日)
roll_backward = np.busday_offset(np.datetime64('2024-01-06'), 0, roll='backward')
print(roll_backward) # 2024-01-05 (回到上一个工作日)
next3 = np.busday_offset(np.datetime64('2024-01-08'), 3)
print(next3) # 2024-01-11 (3个工作日后)
dates = np.array(['2024-01-06', '2024-01-07', '2024-01-08'],
dtype='datetime64[D]')
print(np.is_busday(dates))
# [False False True]
cn_mask = '1111100'
print(np.busday_count(b1, b2, weekmask=cn_mask, holidays=holidays))
# 20
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
6. Python datetime 互转
datetime64 与 Python 标准库 datetime 可互相转换。
▶ 示例
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
:Python datetime 互转(难度⭐⭐)
PYTHON
import numpy as np
from datetime import datetime, timedelta
py_dt = datetime(2024, 6, 15, 10, 30, 0)
np_dt = np.datetime64(py_dt)
print(np_dt) # 2024-06-15T10:30:00
print(np_dt.dtype) # datetime64[us]
np_d = np.datetime64('2024-06-15')
py_d = np_d.astype(datetime)
print(py_d) # 2024-06-15T00:00:00
print(type(py_d)) # <class 'datetime.datetime'>
np_s = np.datetime64('2024-06-15T10:30:00', 's')
ts = np_s.astype('int64')
print(ts) # Unix 时间戳
from_ts = np.datetime64(ts, 's')
print(from_ts) # 2024-06-15T10:30:00
td = np.timedelta64(3, 'D')
py_td = td.astype(timedelta)
print(py_td) # 3 days, 0:00:00
dt64_arr = np.array([datetime(2024, 1, 1),
datetime(2024, 6, 15),
datetime(2024, 12, 31)])
print(dt64_arr.dtype) # datetime64[us]
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
7. 综合示例:项目时间表
Alice 管理项目时间表:计算工作日天数、排除假期、推算里程碑日期。
PYTHON
import numpy as np
project_start = np.datetime64('2024-03-01')
project_end = np.datetime64('2024-09-30')
holidays = np.array([
'2024-04-04', '2024-04-05', # 清明
'2024-05-01', '2024-05-02', '2024-05-03', # 劳动节
'2024-06-10', # 端午
'2024-09-16', # 中秋
], dtype='datetime64[D]')
total_workdays = np.busday_count(project_start, project_end, holidays=holidays)
print(f"项目总工作日: {total_workdays}")
milestones_offsets = [0, 20, 45, 80, 120]
milestone_names = ['启动', '需求评审', '设计评审', '开发完成', '测试上线']
print("\n里程碑计划:")
for name, offset in zip(milestone_names, milestones_offsets):
date = np.busday_offset(project_start, offset, holidays=holidays, roll='forward')
print(f" {name}: {date}")
actual_end = np.datetime64('2024-10-15')
delay_workdays = np.busday_count(project_end, actual_end, holidays=holidays)
print(f"\n延期工作日: {delay_workdays} 天")
check_date = np.datetime64('2024-05-01')
is_holiday = np.isin(check_date, holidays)
is_weekend = not np.is_busday(check_date)
print(f"\n2024-05-01 是假期: {is_holiday}, 是周末: {is_weekend}")
all_dates = np.arange(project_start, project_end + 1, dtype='datetime64[D]')
work_mask = np.is_busday(all_dates, holidays=holidays)
work_dates = all_dates[work_mask]
print(f"\n日历天数: {len(all_dates)}")
print(f"工作日数: {len(work_dates)}")
print(f"节假日/周末: {len(all_dates) - len(work_dates)}")
TEXT
📖 仅展示
> **输出:** 在本地 Python 环境运行 NumPy 2.x,输出 ndarray 数组内容。Piston 服务器未预装 NumPy,请在本机安装(`pip install numpy`)后实操对照。实际数值可能因 NumPy 版本、随机种子略有差异。
❓ 常见问题
Q datetime64 和 Python datetime 有什么区别?
A
datetime64 支持向量化运算和数组操作,精度从年到纳秒共 10 档;Python datetime 是标量对象,不支持 NumPy 向量化,精度只到微秒。datetime64 不支持时区,Python datetime 支持。Q 精度单位怎么选?
A 按业务需求选最小必要精度:日期选
D、月度报表选 M、日志时间戳选 s、高频交易选 ns。精度越高存储越大:datetime64[Y] 占 8 字节,datetime64[ns] 同样 8 字节,但表示范围更窄。日常用 D 或 s 即可。Q busday 能排除自定义假期吗?
A 能。通过
holidays 参数传入日期列表即可。holidays 接受 datetime64 数组或字符串列表,如 holidays=['2024-01-01', '2024-05-01']。配合 weekmask 还可自定义工作日(如六日上班的调休)。Q 能做时区处理吗?
A
datetime64 本身不支持时区。需要时区处理时,先转为 Python datetime 并附加 timezone 信息,或使用 pandas.Timestamp(内置时区支持)。常见做法是统一用 UTC 存储,显示时再转换。Q 如何转时间戳?
A
np_dt.astype('int64') 将 datetime64 转为自 1970-01-01 起的整数计数(单位与 dtype 精度一致)。datetime64[s] 转出的是 Unix 秒时间戳,datetime64[ms] 是毫秒时间戳。反向转换用 np.datetime64(ts, unit)。Q NaT 是什么?
A
NaT(Not a Time)是 datetime64 的缺失值,类似 NaN 之于浮点数。任何涉及 NaT 的运算结果都是 NaT。用 np.isnat() 检测。数组中可用 dates[~np.isnat(dates)] 过滤缺失。📖 小节
np.datetime64— 日期时间标量/数组,精度 Y~ns 共 10 档np.timedelta64— 时间差,datetime64 运算的基础- 日期运算 — 比较排序、np.diff 差分,向量化高效
np.arange(dtype=datetime64)— 按天/月/周/时生成日期序列np.busday_count— 计算两个日期间的工作日数np.is_busday— 判断日期是否为工作日np.busday_offset— 偏移 N 个工作日,roll 处理非工作日- Python 互转 —
astype(datetime)/np.datetime64(py_dt)
📝 作业
(1) 2024 全年日期
- 用
np.arange生成 2024 年全年 366 天的日期数组(datetime64[D]) - 找出所有周六和周日(
np.is_busday取反) - 统计周末天数
(2) 计算工作日
- 定义假期列表:
['2024-01-01', '2024-02-10', '2024-02-11', '2024-05-01', '2024-10-01', '2024-10-02', '2024-10-03'] - 计算 2024 年全年工作日数(
busday_count,排除假期) - 计算 Q1(1~3 月)、Q2(4~6 月)、Q3(7~9 月)、Q4(10~12 月)各自的工作日数
(3) 项目延期天数
- 项目原定 2024-03-01 启动、2024-08-31 结束
- 假期:
['2024-04-04', '2024-05-01', '2024-06-10'] - 计算原定工作日天数
- 实际延期到 2024-09-15,计算延期了多少个工作日
- 用
busday_offset从启动日偏移原定工作日数,验证是否落在 8 月 31 日之前