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

【printpdf】date.rs 文件详细解析

一、项目背景与设计目标

这是 printpdf 库的日期时间模块,专门为 PDF 文档生成 设计。主要目标是为PDF文件提供符合PDF标准的元数据时间戳支持。

二、核心数据结构

1. 基础结构体

// 日期结构体 - 内存优化设计
pub struct Date {pub year: i32,   // 支持负年份(历史日期)pub month: u8,   // 1-12,最小内存占用pub day: u8,     // 1-31,最小内存占用
}// 时间结构体 - 精确到毫秒
pub struct Time {pub hour: u8,           // 0-23pub minute: u8,         // 0-59  pub second: u8,         // 0-59pub millisecond: u16,   // 0-999
}// 时区偏移结构体
pub struct Offset {pub hours: i8,          // -12 到 +14pub minutes: i8,        // 0-59pub seconds: i8,        // 0-59pub milliseconds: i16,  // 0-999
}// 完整日期时间
pub struct DateTime {pub date: Date,pub time: Time, pub offset: Offset,     // 包含时区信息
}

2. 月份枚举

pub enum Month {January = 1,    // 明确从1开始,符合自然习惯February,       // 自动递增// ... 其他月份December,
}

特征分析

  • 所有结构体都实现了完整的trait集合(Debug, Clone, Copy等)
  • 内存布局紧凑,适合PDF文档的序列化需求
  • 支持时区信息,符合国际化PDF标准

三、多平台时间获取实现

1. 原生平台实现

#[cfg(not(target_arch = "wasm32"))]
pub fn now() -> Self {use time::OffsetDateTime; // 依赖time库let now = OffsetDateTime::now_utc();Self {date: Date {year: now.year(),month: now.month() as u8,  // 类型转换day: now.day(),},time: Time {hour: now.hour(),minute: now.minute(),second: now.second(),millisecond: now.millisecond(),},offset: Offset {hours: now.offset().whole_hours() as i8,minutes: now.offset().minutes_past_hour() as i8,seconds: 0,milliseconds: 0,},}
}

2. 浏览器WASM实现

#[cfg(all(feature = "js-sys", target_arch = "wasm32"))]
pub fn now() -> Self {use js_sys::Date as JsDate;let js_date = JsDate::new_0();let month = (js_date.get_month() + 1) as u8; // JS月份从0开始let tz_offset_minutes = js_date.get_timezone_offset() as i16;let offset_hours = -(tz_offset_minutes / 60) as i8; // 时区计算let offset_minutes = -(tz_offset_minutes % 60) as i8;// ... 构建DateTime
}

3. 回退实现

#[cfg(其他WASM环境)]
pub fn now() -> Self {Self::epoch() // 返回Unix纪元作为安全值
}

平台兼容性策略

  • 条件编译支持不同目标平台
  • 优雅降级保证基础功能
  • 利用平台原生时间API

四、PDF特定功能

1. PDF日期格式解析

pub fn parse_pdf_date(s: &str) -> Result<OffsetDateTime, String> {let s = if s.starts_with("D:") { &s[2..] } else { s };// 解析 "D:20170505150224+02'00'" 格式// 固定位置解析:YYYYMMDDHHMMSSlet year: i32 = s[0..4].parse()?;let month: u8 = s[4..6].parse()?;let day: u8 = s[6..8].parse()?;let hour: u8 = s[8..10].parse()?;let minute: u8 = s[10..12].parse()?;let second: u8 = s[12..14].parse()?;// 时区解析:+02'00' 或 -05'30' 格式if s.len() > 14 {let tz_sign = match &s[14..15] {"+" => 1i8, "-" => -1i8, _ => 0i8,};// 解析时区偏移}
}

2. 时间戳转换

impl DateTime {#[cfg(not(target_arch = "wasm32"))]pub fn unix_timestamp(&self) -> i64 {use time::{Date as TimeDate, Month as TimeMonth, PrimitiveDateTime};// 将自定义格式转换为time库格式进行计算let month = match self.date.month {1 => TimeMonth::January,// ... 月份映射};let date = TimeDate::from_calendar_date(self.date.year, month, self.date.day)?;let time = TimeTime::from_hms_milli(...)?;let primitive_dt = PrimitiveDateTime::new(date, time);primitive_dt.assume_offset(offset).unix_timestamp()}
}

五、序列化与反序列化

1. Serde集成

impl Serialize for DateTime {fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> {// 序列化为字符串格式self.to_string().serialize(serializer)}
}impl<'de> Deserialize<'de> for DateTime {fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> {let s = String::deserialize(deserializer)?;s.parse().map_err(serde::de::Error::custom)}
}

2. 字符串格式

impl std::str::FromStr for DateTime {fn from_str(s: &str) -> Result<Self, Self::Err> {// 解析 "2024-01-15 14:30:00.500 +08:00:00" 格式let parts: Vec<&str> = s.split_whitespace().collect();// 日期部分: "2024-01-15"// 时间部分: "14:30:00.500"  // 时区部分: "+08:00:00"}
}

序列化特点

  • 使用人类可读的字符串格式
  • 支持JSON等格式的序列化
  • 完整的错误处理

六、数据验证

1. 日期有效性检查

fn check_date_valid(d: &DateTime) -> Result<(), String> {if !is_valid_date(d.date.year, d.date.month, d.date.day) {return Err(format!("Invalid date: {}-{:02}-{:02}",d.date.year, d.date.month, d.date.day));}// 时间范围验证if d.time.hour > 23 { return Err(format!("Invalid hour: {}", d.time.hour)); }if d.time.minute > 59 { return Err(format!("Invalid minute: {}", d.time.minute)); }if d.time.second > 59 { return Err(format!("Invalid second: {}", d.time.second)); }if d.time.millisecond > 999 { return Err(format!("Invalid millisecond: {}", d.time.millisecond)); }Ok(())
}

2. 闰年计算

fn is_valid_date(year: i32, month: u8, day: u8) -> bool {let days_in_month = match month {1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,4 | 6 | 9 | 11 => 30,2 => {// 闰年判断if (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) {29} else {28}}_ => unreachable!(),};day >= 1 && day <= days_in_month
}

七、架构设计总结

设计优点:

  1. PDF标准合规 - 完美支持PDF日期格式
  2. 跨平台兼容 - 支持原生、WASM等多平台
  3. 内存高效 - 紧凑的数据结构设计
  4. 类型安全 - 充分的trait实现和验证
  5. 序列化友好 - 完整的Serde支持
http://www.dtcms.com/a/560762.html

相关文章:

  • Pycharm详解:高效Python开发的首选IDE
  • 广州市品牌网站建设公司微网站的特点
  • 影刀RPA完全指南:从零开始掌握智能自动化(1/10)
  • 淄博淘宝网站建设企业管理官网登录入口
  • ES6模板字符串
  • Dart 语法核心 7 讲:变量 + 常量 + 数据类型 + 空安全 + 运算符 + 流程控制 + 函数
  • 【Android】活动的正/异常生命周期和启动模式、标志位详解
  • AI换脸技术安全指南:3条法律红线与合规实践
  • 【2025-11-01】软件供应链安全日报:最新漏洞预警与投毒预警情报汇总
  • 使用thefuck报错ModuleNotFoundError: No module named ‘distutils‘
  • 算法23.0
  • 怎么做免费的网站推广网站正在建设中 html 模板
  • 鸿蒙Flutter三方库适配指南:10.插件测试
  • 购物车高效开发指南:API与Vuex实战
  • 广州网站建设公司哪家好展厅设计制作
  • 【BFS 解决FloodFill 算法】4. 被围绕的区域(medium)
  • Go channel 的核心概念、操作语义、设计模式和实践要点
  • 现在还可以做夺宝网站怎么让网站被百度搜到
  • 深蓝汽车10月全球销量36792辆 S05销量突破2万辆
  • 四、CSS选择器(续)和三大特性
  • 高职新能源汽车技术专业职业发展指南
  • 初识MySQL:库的操作、数据类型、表的操作
  • AI助力汽车 UI 交互设计
  • 广州市手机网站建设平台有意义网站
  • MySQL到达梦数据库快速替换操作指南
  • Python NumPy广播机制详解:从原理到实战,数组运算的“隐形翅膀”
  • QT背景介绍与环境搭建
  • 【C++:多态】C++多态实现深度剖析:从抽象类约束到虚函数表机制
  • 【软考架构】案例分析-分布式锁
  • 15.5.手机设备信息