欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
AtomGit 仓库地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_python_numpy

本文介绍在鸿蒙 PC+CodeArts IDE 搭建 Python 开发环境。借助鸿蒙专属包管理器 Harmonybrew 安装适配版 Python,搭配 ohos-pip-autosign 自动签名工具,解决系统对动态库的签名限制。通过虚拟环境隔离依赖,以 NumPy 完成安装与脚本测试,成功解决权限报错,搭建出可用的 Python 开发环境。

可以参考OpenHarmony 鸿蒙 PC + CodeArts IDE 实现 Python开发完整开发环境搭建指南


python-dateutil 完整教程(大量无报错示例)

一、库介绍

1. 作用

python-dateutil 是 Python 超强日期时间扩展库,弥补标准库 datetime 功能缺失,提供日期解析、相对时间、时区、周期、工作日、月份偏移等能力。
原生 datetime 只能做简单加减,dateutil 可以轻松实现:“下个月、下周一、去年、3个月前、每个月最后一天、自动识别任意格式日期字符串”。

核心能力

  1. 万能日期解析 parser.parse:自动识别几乎所有格式日期字符串,无需手动写格式模板;
  2. relativedelta 相对时间偏移:支持按年/月/日/周/时/分/秒增减,解决原生datetime不能直接加减月份的痛点;
  3. rrule 周期生成:生成每日/每周/每月/每年重复日期(日程、定时任务);
  4. 工作日计算 rrule + MO/TU/WE/TH/FR:获取下周一、本月所有工作日、排除周末;
  5. 时区 tzoffset/tzutc:自定义时区、UTC时间转换;
  6. 月份首尾、季度、节假日简易计算
  7. 兼容 datetime.date / datetime.datetime 对象无缝互操作。

业务场景

  1. 爬虫:自动解析网页杂乱格式的发布时间;
  2. 后台统计:近7天、近30天、上月、去年数据筛选;
  3. 日程系统:生成每周重复提醒、每月账单日;
  4. 报表:获取每月第一天/最后一天、季度起止;
  5. 日志处理:解析不规则时间字符串;
  6. 定时脚本:批量生成未来执行时间点。

安装命令

pip install python-dateutil

请添加图片描述

完整大篇幅示例代码 dateutil_demo.py

from datetime import datetime, date, timedelta
from dateutil import parser, rrule
# 修复:单独导入relativedelta类、星期枚举
from dateutil.relativedelta import relativedelta, MO, TU, WE, TH, FR, SA, SU
from dateutil.tz import tzutc, tzoffset

# 基准测试时间
now_dt = datetime(2026, 6, 19, 14, 30, 15)
now_date = date(2026, 6, 19)

# -------------------------- 示例1:万能日期字符串自动解析 parser.parse --------------------------
def demo_parser():
    print("===== 示例1:自动解析任意格式日期字符串 parser.parse =====")
    time_str_list = [
        "2026-06-19",
        "2026/06/19 14:30",
        "19/06/2026",
        "Jun 19, 2026",
        "2026-06-19 14:30:15",
        "19 June 2026 2pm",
        "20260619",
        "6/19/26",
        "2026-06-19T14:30:15Z"
    ]
    for s in time_str_list:
        try:
            dt = parser.parse(s, fuzzy=True)
            print(f"原始:{s:<30} → 解析:{dt}")
        except Exception as e:
            print(f"原始:{s:<30} → 解析失败:{e}")
    print("\n")

# -------------------------- 示例2:relativedelta 相对时间加减(核心,原生timedelta无法按月) --------------------------
def demo_relativedelta_basic():
    print("===== 示例2:relativedelta 年月日时分秒偏移计算 =====")
    base = now_dt
    # 加1年
    next_year = base + relativedelta(years=1)
    # 减2个月
    two_month_ago = base - relativedelta(months=2)
    # 加3周
    three_week_later = base + relativedelta(weeks=3)
    # 加10天5小时
    complex_add = base + relativedelta(days=10, hours=5)
    # 去年同一天
    last_year = base + relativedelta(years=-1)
    print(f"基准时间:{base}")
    print(f"加1年:{next_year}")
    print(f"减2个月:{two_month_ago}")
    print(f"加3周:{three_week_later}")
    print(f"加10天5小时:{complex_add}")
    print(f"去年同日:{last_year}")
    print("\n")

# -------------------------- 示例3:relativedelta 跳转本月/上月第一天、最后一天 --------------------------
def demo_month_start_end():
    print("===== 示例3:获取当月、上月、下月第一天/最后一天 =====")
    base = now_dt
    # 当月第一天
    month_first = base + relativedelta(day=1)
    # 当月最后一天
    month_last = base + relativedelta(months=1, day=1) - relativedelta(days=1)
    # 上月第一天
    last_month_first = base - relativedelta(months=1, day=1)
    # 上月最后一天
    last_month_last = base + relativedelta(day=1) - relativedelta(days=1) - relativedelta(months=1)
    print(f"基准:{base.date()}")
    print(f"本月第一天:{month_first.date()}")
    print(f"本月最后一天:{month_last.date()}")
    print(f"上月第一天:{last_month_first.date()}")
    print(f"上月最后一天:{last_month_last.date()}")
    print("\n")

# -------------------------- 示例4:relativedelta 跳转星期:下周一、上周五 --------------------------
def demo_weekday_jump():
    print("===== 示例4:按星期跳转:下周一、上周五、本月第一个周二 =====")
    base = now_dt
    # 下周一
    next_monday = base + relativedelta(weekday=MO(+1))
    # 上周五
    last_friday = base + relativedelta(weekday=FR(-1))
    # 本月第一个周二
    first_tue_month = base + relativedelta(day=1, weekday=TU(1))
    print(f"基准:{base.date()}")
    print(f"下周一:{next_monday.date()}")
    print(f"上周五:{last_friday.date()}")
    print(f"本月第一个周二:{first_tue_month.date()}")
    print("\n")

# -------------------------- 示例5:rrule 生成周期日期:每日、每周、每月重复 --------------------------
def demo_rrule_cycle():
    print("===== 示例5:rrule 生成周期重复日期(日程/定时任务) =====")
    start = now_dt
    # 生成未来5天,每天
    daily_list = list(rrule.rrule(rrule.DAILY, count=5, dtstart=start))
    print("未来5天每日:")
    for d in daily_list:
        print("  ", d.date())
    # 未来4周,每周一
    weekly_mo = list(rrule.rrule(rrule.WEEKLY, count=4, dtstart=start, byweekday=MO))
    print("\n未来4个周一:")
    for d in weekly_mo:
        print("  ", d.date())
    # 未来3个月,每月1号
    monthly_1 = list(rrule.rrule(rrule.MONTHLY, count=3, dtstart=start, bymonthday=1))
    print("\n未来3个月每月1号:")
    for d in monthly_1:
        print("  ", d.date())
    print("\n")

# -------------------------- 示例6:计算两个日期差值(年/月/日) --------------------------
def demo_date_diff():
    print("===== 示例6:计算两个时间间隔,精确到年月(timedelta只能算天) =====")
    d1 = datetime(2024, 3, 10)
    d2 = datetime(2026, 6, 19)
    diff = relativedelta(d2, d1)
    print(f"起始:{d1}  结束:{d2}")
    print(f"间隔:{diff.years}{diff.months}{diff.days}天")
    print("\n")

# -------------------------- 示例7:工作日筛选,排除周末,获取本月所有工作日 --------------------------
def demo_workday_filter():
    print("===== 示例7:筛选本月所有工作日(排除周六周日) =====")
    month_start = now_dt + relativedelta(day=1)
    month_end = now_dt + relativedelta(months=1, day=1) - relativedelta(days=1)
    # 生成当月所有日期,仅保留周一至周五
    workdays = list(rrule.rrule(
        rrule.DAILY,
        dtstart=month_start,
        until=month_end,
        byweekday=(MO, TU, WE, TH, FR)
    ))
    print(f"本月工作日列表:")
    for d in workdays:
        print("  ", d.date(), d.strftime("%A"))
    print(f"\n本月工作日总数:{len(workdays)}")
    print("\n")

# -------------------------- 示例8:时区处理 UTC、自定义时区偏移 --------------------------
def demo_timezone():
    print("===== 示例8:UTC时区、自定义时区偏移转换 =====")
    utc_now = datetime.now(tzutc())
    # UTC+8 东八区
    tz_cn = tzoffset("UTC+8", 8 * 3600)
    cn_time = utc_now.astimezone(tz_cn)
    print(f"UTC 时间:{utc_now}")
    print(f"UTC+8 北京时间:{cn_time}")
    print("\n")

# -------------------------- 示例9:季度起止日期计算 --------------------------
def demo_quarter():
    print("===== 示例9:获取当前季度、上一季度起止日期 =====")
    base = now_dt
    quarter = (base.month - 1) // 3
    # 本季度第一个月
    q_start_month = quarter * 3 + 1
    q_start = base + relativedelta(month=q_start_month, day=1)
    q_end = q_start + relativedelta(months=3) - relativedelta(days=1)
    print(f"当前时间:{base.date()}")
    print(f"本季度起始:{q_start.date()}")
    print(f"本季度结束:{q_end.date()}")
    print("\n")

# -------------------------- 示例10:模糊解析、忽略无关文字 fuzzy --------------------------
def demo_fuzzy_parse():
    print("===== 示例10:fuzzy模糊解析,忽略无关中文/符号 =====")
    text = "发布时间:2026-06-19 14:30 来自官网"
    dt = parser.parse(text, fuzzy=True)
    print(f"原文:{text}")
    print(f"提取日期:{dt}")
    text2 = "更新于 20/06/2026 10:22 浏览123次"
    dt2 = parser.parse(text2, fuzzy=True)
    print(f"原文:{text2}")
    print(f"提取日期:{dt2}")
    print("\n")

# -------------------------- 统一入口执行所有示例 --------------------------
def run_all():
    demo_parser()
    demo_relativedelta_basic()
    demo_month_start_end()
    demo_weekday_jump()
    demo_rrule_cycle()
    demo_date_diff()
    demo_workday_filter()
    demo_timezone()
    demo_quarter()
    demo_fuzzy_parse()
    print("🎉 python-dateutil 全部示例执行完成,无报错")

if __name__ == "__main__":
    run_all()

请添加图片描述


一、头部导入与常量定义

from datetime import datetime, date, timedelta
from dateutil import parser, rrule
from dateutil.relativedelta import relativedelta, MO, TU, WE, TH, FR, SA, SU
from dateutil.tz import tzutc, tzoffset

# 基准测试时间
now_dt = datetime(2026, 6, 19, 14, 30, 15)
now_date = date(2026, 6, 19)
  1. 原生datetime:Python自带基础日期对象,作为所有计算载体;
  2. parser:万能日期字符串解析器,自动识别千余种日期格式;
  3. rrule:周期日期生成器,生成每日/每周/每月重复时间序列;
  4. relativedelta:核心相对时间计算类,解决原生timedelta不能加减年月的痛点;
  5. MO~SU:周一到周日的星期枚举,用于筛选工作日、跳转指定星期;
  6. tzutc/tzoffset:时区工具,UTC标准时区、自定义时区偏移(北京时间UTC+8);
  7. now_dt/now_date:固定基准测试时间,保证每次运行结果统一,不受系统实时日期干扰。

示例1:万能日期自动解析 parser.parse

def demo_parser():
    time_str_list = [
        "2026-06-19","2026/06/19 14:30","19/06/2026","Jun 19, 2026",
        "2026-06-19 14:30:15","19 June 2026 2pm","20260619","6/19/26","2026-06-19T14:30:15Z"
    ]
    for s in time_str_list:
        try:
            dt = parser.parse(s, fuzzy=True)
            print(f"原始:{s:<30} → 解析:{dt}")
        except Exception as e:
            print(f"原始:{s:<30} → 解析失败:{e}")

核心作用

原生strptime必须手动匹配格式,格式写错直接崩溃;parser.parse自动识别任意主流日期写法

  • fuzzy=True:忽略字符串中无关文字、符号(后面示例10单独演示中文混杂文本);
  • 支持横杠、斜杠、英文月份、数字紧凑格式、ISO标准UTC时间;

业务场景

爬虫抓取网页杂乱发布时间、日志不规则时间字符串解析。

示例2:relativedelta 相对时间偏移(库最核心能力)

def demo_relativedelta_basic():
    base = now_dt
    next_year = base + relativedelta(years=1)
    two_month_ago = base - relativedelta(months=2)
    three_week_later = base + relativedelta(weeks=3)
    complex_add = base + relativedelta(days=10, hours=5)
    last_year = base + relativedelta(years=-1)

关键优势

原生timedelta只支持天/时/分/秒,不能直接加减月份、年份,遇到2月、大小月、闰年直接报错;
relativedelta自动处理历法规则:

  • years=1 加1年,years=-1 上一年;
  • months=2 加减月份,自动适配28/29/30/31天;
  • 支持多参数组合:同时加天数、小时;

业务场景

后台统计:近3个月、去年同期、下月报表时间范围计算。

示例3:获取当月/上月第一天、最后一天

def demo_month_start_end():
    base = now_dt
    month_first = base + relativedelta(day=1)
    month_last = base + relativedelta(months=1, day=1) - relativedelta(days=1)
    last_month_first = base - relativedelta(months=1, day=1)
    last_month_last = base + relativedelta(day=1) - relativedelta(days=1) - relativedelta(months=1)

逻辑说明

  1. day=1:强制跳转到当月1号;
  2. 下月1号再减1天 = 当月最后一天,自动兼容大小月;
  3. 同理算出上月起止;

业务场景

月度报表、账单统计、按月数据筛选。

示例4:按星期跳转:下周一、上周五、当月第N个周二

def demo_weekday_jump():
    base = now_dt
    next_monday = base + relativedelta(weekday=MO(+1))
    last_friday = base + relativedelta(weekday=FR(-1))
    first_tue_month = base + relativedelta(day=1, weekday=TU(1))

参数规则:

  • MO(+1):下一个周一;
  • FR(-1):上一个周五;
  • TU(1):当月第一个周二;

业务场景

排班系统、每周定时任务、信用卡每月固定还款日。

示例5:rrule 生成周期重复日期

def demo_rrule_cycle():
    start = now_dt
    daily_list = list(rrule.rrule(rrule.DAILY, count=5, dtstart=start))
    weekly_mo = list(rrule.rrule(rrule.WEEKLY, count=4, dtstart=start, byweekday=MO))
    monthly_1 = list(rrule.rrule(rrule.MONTHLY, count=3, dtstart=start, bymonthday=1))

rrule是重复日期生成器,类似Linux crontab时间生成:

  • DAILY 每日、WEEKLY 每周、MONTHLY 每月;
  • count=5 生成5个日期停止;
  • dtstart 起始时间;
  • byweekday 指定星期、bymonthday 指定每月几号;

业务场景

日程提醒、定时备份、周期性批量任务。

示例6:两个日期精确拆分间隔(年/月/日)

def demo_date_diff():
    d1 = datetime(2024, 3, 10)
    d2 = datetime(2026, 6, 19)
    diff = relativedelta(d2, d1)
    print(f"间隔:{diff.years}{diff.months}{diff.days}天")

原生timedelta只能算出总天数,无法拆分几年几个月;
relativedelta(结束时间, 起始时间) 自动拆分年、月、日三段间隔;

业务场景

计算用户注册时长、员工工龄、订单存续周期。

示例7:筛选当月所有工作日(排除周六周日)

def demo_workday_filter():
    month_start = now_dt + relativedelta(day=1)
    month_end = now_dt + relativedelta(months=1, day=1) - relativedelta(days=1)
    workdays = list(rrule.rrule(
        rrule.DAILY, dtstart=month_start, until=month_end, byweekday=(MO, TU, WE, TH, FR)
    ))
  1. 生成当月全部日期;
  2. byweekday=(MO, TU, WE, TH, FR) 只保留周一到周五;

业务场景

考勤统计、薪资核算、工作日业务排期。

示例8:时区转换 UTC / UTC+8 北京时间

def demo_timezone():
    utc_now = datetime.now(tzutc())
    tz_cn = tzoffset("UTC+8", 8 * 3600)
    cn_time = utc_now.astimezone(tz_cn)
  1. tzutc():标准零时区;
  2. tzoffset(name, 秒):自定义时区,东八区偏移8*3600秒;
  3. astimezone():时区互相转换;

业务场景

海外接口日志、多时区后台系统、国际化时间展示。

示例9:季度起止日期计算

def demo_quarter():
    base = now_dt
    quarter = (base.month - 1) // 3
    q_start_month = quarter * 3 + 1
    q_start = base + relativedelta(month=q_start_month, day=1)
    q_end = q_start + relativedelta(months=3) - relativedelta(days=1)

计算逻辑:

  1. 月份除以3向下取整,判断属于第几季度;
  2. 算出本季度第一个月,取当月1号为季度起始;
  3. 加3个月再减1天得到季度最后一天;

业务场景

季度财报、季度数据统计、季度活动排期。

示例10:fuzzy 模糊提取混杂文本里的日期

def demo_fuzzy_parse():
    text = "发布时间:2026-06-19 14:30 来自官网"
    dt = parser.parse(text, fuzzy=True)

开启fuzzy=True后,自动忽略文字、中文、符号,只提取数字日期部分;

业务场景

爬虫直接提取网页混杂文案中的发布时间,不用手写正则。

统一入口 run_all()

依次执行上面10个场景示例,最后打印执行完成;
顶层代码if __name__ == "__main__"保证只有直接运行文件时才执行全部逻辑,被其他脚本导入时不会自动执行。

整体库核心价值总结

  1. 解决原生datetime硬伤:原生无法按月/年偏移,大小月、闰年计算极易出错;
  2. 日期解析零模板:不用手动写时间格式,自动识别各类字符串;
  3. 周期、工作日、季度、月度统计一站式工具,报表/后台高频需求一行代码实现;
  4. 时区、时间间隔、文本模糊提取覆盖爬虫、后端、自动化脚本全场景;
  5. 纯Python实现,无二进制依赖,任意Linux/鸿蒙/Windows环境直接运行。

逐段功能详细讲解

1. parser.parse 万能日期解析

无需手动定义 strftime 格式模板,自动识别千余种日期写法;fuzzy=True 可以忽略前后无关文字(爬虫网页提取时间神器)。
原生datetime.strptime 格式写错直接崩溃,dateutil容错极强。

2. relativedelta 相对时间(核心亮点)

标准库 timedelta 只能加减天时分秒,不能直接加减月份、年份(2月加1个月会报错、大小月错乱);
relativedelta 自动处理大小月、闰年、跨年,完美解决统计“近30天、上月、去年”场景。
参数:years/months/weeks/days/hours/minutes/seconds,负数代表往前偏移。

3. 月份首尾快速获取

报表统计高频需求:每月第一天、最后一天,无需判断28/29/30/31号,一行代码算出。

4. 按星期跳转 MO/TU/WE/TH/FR/SA/SU

快速获取下周一、上周五、当月第N个星期二,用于排班、账单日、每周定时任务。
MO(+1) = 下周一,FR(-1) = 上周五。

5. rrule 周期生成器

生成重复日期序列,替代手动循环判断:

  • DAILY 每日、WEEKLY 每周、MONTHLY 每月、YEARLY 每年;
  • count=5 生成5条,until=截止日期;
  • byweekday 指定星期、bymonthday 指定每月几号。

6. 两个日期精确差值计算

timedelta 只能算出总天数,无法区分几年几个月;
relativedelta(结束时间, 起始时间) 直接拆分年、月、日差值,做年龄、服务时长统计。

7. 工作日筛选

结合 rrule + 星期枚举,一键筛选当月所有工作日,排除周六周日,薪资、考勤报表必备。

8. 时区转换 tzutc / tzoffset

内置UTC时区,支持自定义任意时区偏移(东八区UTC+8),解决跨时区日志、海外接口时间转换。

9. 季度计算

自动算出当前季度起始、结束日期,季度报表、季度数据统计。

10. fuzzy 模糊提取

网页混杂文字里自动捞出日期数字,爬虫不用正则提取时间字符串。

核心对比(datetime vs dateutil)

功能 原生datetime python-dateutil
自动解析任意日期字符串 ❌ 必须指定格式 ✅ parser.parse
加减月份/年份 ❌ 大小月报错 ✅ relativedelta
按星期跳转(下周一) ❌ 大量判断 ✅ MO(+1)
生成周期重复日期 ❌ 手写循环 ✅ rrule
年月拆分时间间隔 ❌ 仅总天数 ✅ relativedelta(结束,起始)
模糊提取文本中的日期 ❌ 正则硬写 ✅ fuzzy=True
批量筛选工作日 ❌ 循环判断 ✅ rrule+weekday

运行命令

# 安装
pip install python-dateutil
# 执行代码
python dateutil_demo.py

典型业务使用场景总结

  1. 爬虫:fuzzy模糊解析网页杂乱发布时间;
  2. 后台统计:近7天、上月、本季度数据时间范围生成;
  3. 定时任务:rrule生成每周/每月执行时间;
  4. 考勤薪资:筛选当月工作日;
  5. 报表导出:自动获取每月、季度起止日期;
  6. 用户时长:计算注册到现在几年几个月;
  7. 多时区系统:UTC与本地时间互相转换;
  8. 账单提醒:每月1号、每周一自动生成提醒日期。
Logo

赋能鸿蒙PC开发者,共建全场景原生生态,共享一次开发多端部署创新价值。

更多推荐