当前位置: 首页 > news >正文

鸿蒙PC适配llvm-gcc-compat编译安装第三方库chrono,打造Rust 第三方日期时间处理库

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

本文讲解鸿蒙 PC 端 Rust 开发环境搭建,鸿蒙基于 musl 库、强制二进制签名,无法直接使用通用 Linux 编译产物。需借助鸿蒙专属包管理器 Harmonybrew,提供两套编译方案:方案一安装 llvm-gcc-compat,零配置开箱即用;方案二仅安装 ohos-sdk,需手动配置 Cargo 链接器,二者都依托 ohos-sdk 完成自动签名编译。

可以来参考一下这个文章搭建环境OpenHarmony 鸿蒙 PC + CodeArts IDE 实现 Rust开发完整开发环境搭建指南


一、chrono 是什么

chrono是 Rust 生态最主流、功能完整的日期时间处理库,替代标准库单薄的std::time/SystemTime
标准库时间缺陷:时区支持差、格式化繁琐、缺少日期加减、星期/月份便捷方法、无法简单解析日期字符串;
chrono 完整补齐所有时间业务需求,是 Rust 后端、CLI、数据处理项目标配。

核心作用

  1. 支持本地时间、UTC时间、带时区时间,时区计算完善
  2. 日期快速加减:年/月/日/时/分/秒,自动处理月末、闰年边界
  3. 强大格式化 + 字符串解析,自定义格式模板
  4. 获取星期、季度、月初月末、年份首尾、时间戳互转
  5. 时间差值计算(计算相隔几天、几小时)
  6. 支持序列化(搭配 serde 存JSON/数据库)
  7. 兼容时间戳:秒、毫秒、微秒、纳秒互相转换

二、安装依赖

1. 新建项目(已有项目跳过)

cargonew chrono_democdchrono_demo

2. 添加 chrono 依赖

# 基础版本(本地/UTC时间,格式化)cargoaddchrono# 如果需要时区支持(拓展)cargoaddchrono--featuresclock,timezone# 如果需要serde序列化(接口/数据库必用)cargoaddchrono--featuresserde

打开Cargo.toml自动生成依赖:

[dependencies] chrono = { version = "0.4", features = ["clock", "timezone", "serde"] }


三、完整无报错 main.rs 示例

覆盖绝大多数业务场景:当前时间、格式化、解析字符串、日期偏移、时间戳、差值、月初月末、时区、serde序列化

usechrono::{DateTime,Datelike,Local,Months,NaiveDate,NaiveDateTime,NaiveTime,TimeDelta,Utc,};fnmain(){// ===================== 1. 获取当前时间 =====================println!("===== 1. 当前本地时间 / UTC 时间 =====");letnow_local:DateTime<Local>=Local::now();letnow_utc:DateTime<Utc>=Utc::now();println!("本地完整时间: {}",now_local);println!("UTC 标准时间: {}",now_utc);// 只获取日期/只获取时间(无时区裸时间)lettoday:NaiveDate=Local::now().date_naive();letnow_time:NaiveTime=Local::now().time();println!("今日日期: {}",today);println!("当前时刻: {}",now_time);// ===================== 2. 时间格式化 =====================println!("\n===== 2. 自定义格式化输出 =====");letfmt_str="%Y-%m-%d %H:%M:%S";println!("标准格式: {}",now_local.format(fmt_str));println!("仅年月日: {}",now_local.format("%Y-%m-%d"));println!("中文格式: {}",now_local.format("%Y年%m月%d日 %H:%M:%S"));println!("星期: {}",now_local.format("%A"));// ===================== 3. 字符串解析成时间 =====================println!("\n===== 3. 字符串解析为日期时间 =====");letdate_text="2026-08-15 14:30:00";matchNaiveDateTime::parse_from_str(date_text,fmt_str){Ok(dt)=>println!("解析成功: {}",dt),Err(e)=>eprintln!("解析失败: {}",e),}letday_text="2026-10-01";letholiday=NaiveDate::parse_from_str(day_text,"%Y-%m-%d").unwrap();println!("解析纯日期: {}",holiday);// ===================== 4. 日期加减 =====================println!("\n===== 4. 日期偏移 加减年/月/日/时/分 =====");lettomorrow=today+TimeDelta::days(1);letlast_month=today-TimeDelta::days(30);letafter_2_hour=Local::now()+TimeDelta::hours(2);println!("明天: {}",tomorrow);println!("30天前: {}",last_month);println!("2小时后: {}",after_2_hour.format(fmt_str));// 按月偏移letnext_month=today.checked_add_months(Months::new(1)).unwrap();println!("下个月今日: {}",next_month);// ===================== 5. 时间戳互转 =====================println!("\n===== 5. 时间戳转换 =====");letnow=Utc::now();letts_sec=now.timestamp();letts_ms=now.timestamp_millis();println!("UTC 秒级时间戳: {}",ts_sec);println!("UTC 毫秒时间戳: {}",ts_ms);letfrom_sec=DateTime::from_timestamp(ts_sec,0).unwrap();println!("时间戳还原UTC时间: {}",from_sec);// ===================== 6. 计算两个时间差值 =====================println!("\n===== 6. 计算时间间隔 =====");letstart=NaiveDate::from_ymd_opt(2026,1,1).unwrap();letend=NaiveDate::from_ymd_opt(2026,12,31).unwrap();letdiff=end-start;println!("2026全年相差天数: {} 天",diff.num_days());println!("相差小时数: {} h",diff.num_hours());// ===================== 7. 获取月初、月末 =====================println!("\n===== 7. 当月第一天 / 当月最后一天 =====");letcurrent_month_first=today.with_day(1).unwrap();letnext_month_first=current_month_first.checked_add_months(Months::new(1)).unwrap();letcurrent_month_last=next_month_first-TimeDelta::days(1);println!("本月一号: {}",current_month_first);println!("本月最后一天: {}",current_month_last);}

四、运行

cargorun

chrono是 Rust 生态最主流、功能最全的日期时间处理库,替代标准库简陋的时间工具,支持时区、格式化、解析、时间偏移、时间戳、日期差值、月初月末等业务常用能力。

前置配置

先在Cargo.toml引入依赖(推荐开启本地时区、月份运算功能)

[dependencies] chrono = { version = "0.4", features = ["local", "months"] }

导入包中核心类型:

usechrono::{DateTime,Datelike,Local,Months,NaiveDate,NaiveDateTime,NaiveTime,TimeDelta,Utc,};

先区分核心概念(看懂下面代码的关键)

  1. 带时区时间DateTime<Local>本地时区、DateTime<Utc>UTC零时区,包含时区信息,可直接格式化、转时间戳
  2. 裸时间(无时区)
    • NaiveDate:只有年月日,无时分秒、无时区
    • NaiveTime:只有时分秒,无年月日、无时区
    • NaiveDateTime:年月日+时分秒,没有时区,仅存储纯时间数字
  3. TimeDelta:时间间隔,用来做时间加减(天/时/分/秒/毫秒)
  4. Months:专门按月偏移(解决2月、大小月天数不一致问题,TimeDelta只能按固定天数偏移)
  5. Dateliketrait:提供年月日、星期、当月第几天等日期取值方法

1. 获取当前时间

letnow_local:DateTime<Local>=Local::now();letnow_utc:DateTime<Utc>=Utc::now();println!("本地完整时间: {}",now_local);println!("UTC 标准时间: {}",now_utc);// 只提取裸日期 / 裸时刻lettoday:NaiveDate=Local::now().date_naive();letnow_time:NaiveTime=Local::now().time();println!("今日日期: {}",today);println!("当前时刻: {}",now_time);

详解

  • Local::now():获取操作系统本地时区当前完整时间(东八区北京时间)
  • Utc::now():获取零时区标准时间,服务器存储时间戳优先用UTC,避免时区混乱
  • .date_naive():从带时区时间中剥离时区,只保留年月日NaiveDate
  • .time():剥离日期,只保留时分秒NaiveTime

输出示例

本地完整时间: 2026-06-18 15:20:30.123456 +08:00 UTC 标准时间: 2026-06-18 07:20:30.123456 UTC 今日日期: 2026-06-18 当前时刻: 15:20:30.123456

2. 时间格式化输出

letfmt_str="%Y-%m-%d %H:%M:%S";println!("标准格式: {}",now_local.format(fmt_str));println!("仅年月日: {}",now_local.format("%Y-%m-%d"));println!("中文格式: {}",now_local.format("%Y年%m月%d日 %H:%M:%S"));println!("星期: {}",now_local.format("%A"));

格式化占位符常用对照表

占位符含义示例
%Y4位年份2026
%m两位月份06
%d两位日期18
%H24小时制小时15
%M分钟20
%S30
%A完整英文星期Thursday
%w数字星期(0=周日)4

说明

.format(模板字符串)支持带时区DateTime和裸时间NaiveDateTime;可以自由拼接中文,非常适合前端展示、日志打印。


3. 字符串解析成时间

letdate_text="2026-08-15 14:30:00";matchNaiveDateTime::parse_from_str(date_text,fmt_str){Ok(dt)=>println!("解析成功: {}",dt),Err(e)=>eprintln!("解析失败: {}",e),}letday_text="2026-10-01";letholiday=NaiveDate::parse_from_str(day_text,"%Y-%m-%d").unwrap();println!("解析纯日期: {}",holiday);

核心逻辑

parse_from_str(待解析字符串, 格式化模板)模板必须和字符串格式完全匹配,否则返回解析错误。

  • NaiveDateTime::parse_from_str:解析「年月日 时分秒」完整字符串
  • NaiveDate::parse_from_str:只解析纯日期,不带时分秒

错误处理

返回Result<T, ParseError>

  1. match分支:生产环境推荐,优雅处理格式错误
  2. .unwrap():测试、确定字符串格式合法时快速取值,格式不对程序直接panic

4. 日期时间加减偏移

4.1 TimeDelta 固定时长偏移(天/时/分/秒)

lettomorrow=today+TimeDelta::days(1);letlast_month=today-TimeDelta::days(30);letafter_2_hour=Local::now()+TimeDelta::hours(2);println!("明天: {}",tomorrow);println!("30天前: {}",last_month);println!("2小时后: {}",after_2_hour.format(fmt_str));

TimeDelta代表固定时长,支持:

  • TimeDelta::days(n)
  • TimeDelta::hours(n)小时
  • TimeDelta::minutes(n)分钟
  • TimeDelta::seconds(n)

4.2 Months 按月自然偏移(推荐处理月份)

letnext_month=today.checked_add_months(Months::new(1)).unwrap();println!("下个月今日: {}",next_month);

关键区别(重点)

  1. TimeDelta::days(30):强制固定30天,遇到大小月、2月会出错
    例:1月31日 +30天 = 3月2日,不符合“下个月同一天”业务需求
  2. checked_add_months(Months::new(1)):自然按月跳转
    1月31日 → 2月28/29日,3月31日→4月30日,完美适配日历逻辑
  • checked_add_months返回Option:月末跨月无对应日期返回None,.unwrap()适合确定合法场景

5. 时间戳互转(前后端交互核心)

letnow=Utc::now();letts_sec=now.timestamp();letts_ms=now.timestamp_millis();println!("UTC 秒级时间戳: {}",ts_sec);println!("UTC 毫秒时间戳: {}",ts_ms);letfrom_sec=DateTime::from_timestamp(ts_sec,0).unwrap();println!("时间戳还原UTC时间: {}",from_sec);

方法说明

  1. .timestamp():输出秒级时间戳(i64),后端接口通用
  2. .timestamp_millis():输出毫秒时间戳,前端JS常用
  3. DateTime::from_timestamp(秒, 纳秒):秒级时间戳转回带时区UTC时间
    第二个参数是纳秒补充,不需要填0即可

最佳实践

数据库存储、接口传输一律使用UTC时间戳,避免本地时区导致的时差bug。


6. 计算两个时间差值

letstart=NaiveDate::from_ymd_opt(2026,1,1).unwrap();letend=NaiveDate::from_ymd_opt(2026,12,31).unwrap();letdiff=end-start;println!("2026全年相差天数: {} 天",diff.num_days());println!("相差小时数: {} h",diff.num_hours());

流程拆解

  1. NaiveDate::from_ymd_opt(年,月,日):安全构造日期,返回Option<NaiveDate>,非法日期(2月30日)返回None
  2. 两个同类型时间相减,得到TimeDelta差值对象
  3. 差值取值方法:
    • .num_days():总相差天数
    • .num_hours():总相差小时
    • .num_minutes()/.num_seconds():总分钟、总秒数

适用场景

倒计时、活动剩余时长、计算年龄、统计间隔天数。


7. 获取当月第一天、当月最后一天

letcurrent_month_first=today.with_day(1).unwrap();letnext_month_first=current_month_first.checked_add_months(Months::new(1)).unwrap();letcurrent_month_last=next_month_first-TimeDelta::days(1);println!("本月一号: {}",current_month_first);println!("本月最后一天: {}",current_month_last);

逻辑分步拆解

  1. .with_day(1):把当前日期强制改为当月1号,得到本月首日
  2. 本月1号 +1个月 → 下个月1号
  3. 下个月1号 减1天 → 本月最后一天

优势

自动兼容28/29天2月、31天大月、30天小月,不用手动判断月份天数,报表统计、月度筛选高频使用。


关键类型总结 & 使用建议

什么时候用 Naive(裸时间)

  1. 只做本地日期计算、报表统计、不需要跨时区传输
  2. 本地文件存储、仅程序内部计算

什么时候用 DateTime/DateTime

  1. 和前端、数据库交互、生成时间戳
  2. 需要格式化展示本地时间、处理时区转换

加减选择

  • 固定时长(往后推2小时、7天)→TimeDelta
  • 自然月/年(下个月、去年今日)→Months

安全编码小提示

  1. 构造日期、月份偏移优先用xxx_opt+ match 处理None,少用unwrap上线
  2. 对外接口时间统一用UTC时间戳,避免时区混乱
  3. 解析用户输入日期必须捕获解析错误,防止非法格式panic

五、核心模块与类型说明

1. 基础时间类型

类型含义使用场景
NaiveDate纯日期,无时间、无时区生日、订单创建日
NaiveTime纯时刻,无日期、无时区固定每日执行时刻
NaiveDateTime日期+时刻,无时区数据库不带时区存储
DateTime<Local>带本地时区完整时间展示给前端本地时间
DateTime<Utc>UTC零时区时间服务统一存储、时间戳

2. 关键结构体

  • TimeDelta:时间差值,days/hours/minutes/seconds
  • Months:按月偏移,自动适配大小月、闰年

3. 格式化模板常用占位符

  • %Y4位年份2026
  • %m两位月份01~12
  • %d两位日期01~31
  • %H24小时制00~23
  • %M分钟00~59
  • %S
  • %A完整星期名称 Monday
  • %w数字星期 0=周日

六、常用Feature功能说明

  1. clock(默认开启)
    Local::now()/Utc::now()获取系统当前时间,关闭则无法获取实时时间。
  2. timezone
    拓展时区库,支持Asia/Shanghai等完整IANA时区,用于跨国系统。
  3. serde
    实现Serialize/Deserialize,时间结构体直接转JSON,Web后端必备。
  4. rkyv / sqlx
    额外feature适配数据库ORM(sqlx、diesel)直接存取时间字段。

七、典型业务开发场景

  1. Web后端接口
    UTC时间存库,本地时区格式化返回前端,JSON序列化时间
  2. 定时任务计算
    计算下月执行日、每月1号、距离过期剩余天数
  3. 日志系统
    日志打印格式化时间、计算请求耗时(两个时间差值)
  4. 数据库业务
    生日、订单创建时间、活动起止时间校验
  5. 爬虫/数据同步
    时间戳转换、按日期分段拉取历史数据

八、优势对比标准库std::time

  1. 标准库SystemTime只支持时间戳,无日期、月份、星期操作;
  2. chrono自动处理闰年、2月、月末边界,不用手动判断;
  3. 统一格式化/解析模板,不用手写复杂转换;
  4. 原生支持时区,解决前后端时区错乱问题;
  5. 生态兼容serde、sqlx、axum、rocket等主流框架。
http://www.jsqmd.com/news/1070930/

相关文章:

  • 从拉流、叠加到国标多平台分发:SmartMediaKit 多模态融合推流方案设计
  • 16-Redis 与 Redisson 采集:缓存节点如何参与问题定位
  • Web渗透测试实战:SQL注入漏洞从入门到深度防御
  • 智能硬件产品 App 全球发布 第 6 章:IoT App 特殊审核体系
  • 无人机航拍输电线路缺陷检测开源数据集|电力电缆散股异物识别YOLODETR双格式图像库10452期
  • 基于U2-Net与深度度量学习的自动化花粉显微图像分析系统实践
  • Linux线程3.0-线程同步与互斥,C/C++互斥锁。
  • 关于GraalVM的说明
  • 豆包导出pdf怎么调顺序?试试AI 导出鸭智能排序
  • 联邦学习实战:破解非独立同分布数据困局的算法策略与调优指南
  • 鸿蒙PC适配llvm-gcc-compat编译安装第三方库itertools,打造Rust 第三方迭代器增强库
  • 东莞企业做GEO为什么AI不推荐你-信源权重的3个硬指标拆开看
  • 基于MobileNetV3的轻量化人脸年龄估计模型:MobileAgeNet实战指南
  • AI开发-多路径写入一致性:从一次 Debug 到系统性防御
  • 从“会聊天“到“能干活“:用 OpenCode 给自己找个 AI 搭子
  • 【收藏夹必备】写博文还在用“●“做列表?这些图标让文章质感翻倍!
  • 【硬核长文】万字拆解无线网络核心:AP(无线访问接入点)从底层原理到企业级实战调优指南
  • HoRain云--R语言列表操作全指南:从入门到精通
  • 无人机遥感国土目标检测数据集 无人机耕地数据集 无人机道路农田检测 国土遥感地物实例分割数据集 yolo数据集第10759期
  • 五、进程控制
  • 程序员面试翻车?我用了两个月测遍AI面试工具,最终只推荐这一个
  • Redis...2
  • 影刀RPA新手教程:零基础入门完全指南——从下载安装到独立开发你的第一个自动化流程
  • Ntk-aware 插值
  • 医疗AI多模态学习:M-IDoL框架突破信息模糊困境
  • 流体-结构耦合与声子亚表面在湍流减阻中的应用
  • 反射的定义、使用方式、优缺点和具体使用场景
  • RFID 仓库管理系统 项目总结
  • 基于用户画像的AI内容生成与安全检测闭环系统实践
  • 外部中断EXTI和NVIC