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 + 5D15D
timedelta64 * int timedelta64 7D * 321D
timedelta64 / timedelta64 float 30D / 7D4.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_countnp.is_busdaynp.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 字节,但表示范围更窄。日常用 Ds 即可。
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)] 过滤缺失。

📖 小节


📝 作业

(1) 2024 全年日期

  1. np.arange 生成 2024 年全年 366 天的日期数组(datetime64[D]
  2. 找出所有周六和周日(np.is_busday 取反)
  3. 统计周末天数

(2) 计算工作日

  1. 定义假期列表:['2024-01-01', '2024-02-10', '2024-02-11', '2024-05-01', '2024-10-01', '2024-10-02', '2024-10-03']
  2. 计算 2024 年全年工作日数(busday_count,排除假期)
  3. 计算 Q1(1~3 月)、Q2(4~6 月)、Q3(7~9 月)、Q4(10~12 月)各自的工作日数

(3) 项目延期天数

  1. 项目原定 2024-03-01 启动、2024-08-31 结束
  2. 假期:['2024-04-04', '2024-05-01', '2024-06-10']
  3. 计算原定工作日天数
  4. 实际延期到 2024-09-15,计算延期了多少个工作日
  5. busday_offset 从启动日偏移原定工作日数,验证是否落在 8 月 31 日之前
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏