DateTime::ToString 日期时间文本格式化深度解析(C++)
⚙️ DateTime::ToString 日期时间文本格式化深度解析(C++)
——结构、流程、原理与完整实现
引用:
- ppp/DateTime.cpp#L139
家山别矣 想念天涯子
怅然老矣
我共二三子
惶然梦矣
梦也徘徊起
暮暮朝朝
老去吟游
离魂无据
梦里痴痴语
🏗️ 一、整体结构
组成模块:
- 格式解析器:扫描格式字符串,识别
yMdHmsfuT
格式符 - 状态追踪器:使用
symbol
和symbol_size
跟踪当前格式组 - 组件处理器:将时间分量转换为字符串
- 宽度控制器:实现fixed模式下的截断/补零
- 字符串构建器:拼接最终结果
🔄 二、处理流程
⏱️ 三、格式处理原理
关键算法:
while (*format) {ch = *format++;if (是格式符(ch)) {if (symbol != 0 && symbol != ch) {symbol_exec(0); // 提交当前组}symbol = ch; // 设置新符号symbol_size++; // 增加计数} else {symbol_exec(ch); // 提交组并添加字面值}
}
symbol_exec(0); // 处理剩余组
符号处理器行为:
🛠️ 四、完整代码实现
ppp::string DateTime::ToString(const char* format, bool fixed) noexcept {ppp::string result;if (NULL == format || *format == '\x0') {return result;}char symbol = 0;int symbol_size = 0;auto symbol_exec = int ch noexcept {ppp::string seg;switch (symbol) {case 'y': seg = stl::to_string<ppp::string>(Year()); break;case 'M': seg = stl::to_string<ppp::string>(Month()); break;case 'd': seg = stl::to_string<ppp::string>(Day()); break;case 'H': seg = stl::to_string<ppp::string>(Hour()); break;case 'm': seg = stl::to_string<ppp::string>(Minute()); break;case 's': seg = stl::to_string<ppp::string>(Second()); break;case 'f': seg = stl::to_string<ppp::string>(Millisecond()); break;case 'u': seg = stl::to_string<ppp::string>(Microseconds()); break;case 'T': seg = stl::to_string<ppp::string>((int64_t)TotalHours()); break;}if (fixed && symbol != 0) {int64_t seg_size = seg.size();if (seg_size > symbol_size) {seg = seg.substr(seg_size - symbol_size);} else if (seg_size < symbol_size) {seg = PaddingLeft(seg, symbol_size, '0');}}if (ch != 0) {seg.append(1, ch);}result += seg;symbol = 0;symbol_size = 0;};const char* p = format;while (*p) {char ch = *p++;if (ch == 'y' || ch == 'M' || ch == 'd' || ch == 'H' || ch == 'm' || ch == 's' || ch == 'f' || ch == 'u' || ch == 'T') {if (symbol != 0 && symbol != ch) {symbol_exec(0);}symbol = ch;symbol_size++;} else {symbol_exec(ch);}}symbol_exec(0);return result;
}template <typename _Ty>
_Ty DateTime::PaddingLeft(const _Ty& s, int count, char padding_char) noexcept {int string_length = static_cast<int>(s.size());if (count < 1 || count <= string_length) {return s;}_Ty r = s;for (int i = 0; i < count - string_length; i++) {r = _Ty(1ul, padding_char) + r;}return r;
}
🔍 五、核心机制剖析
1. 格式符处理矩阵
输入 | 当前状态 | 动作 |
---|---|---|
新符号 | symbol相同 | symbol_size++ |
新符号 | symbol不同 | 提交旧组,开始新组 |
非符号 | 有状态 | 提交组,添加字面值 |
非符号 | 无状态 | 直接添加字面值 |
2. fixed模式控制逻辑
3. 时间分量映射关系
💡 六、应用场景示例
1. 标准日期格式
// 输出:2025-07-29
ToString("yyyy-MM-dd", true)
处理流程:
2. 精确时间戳
// 输出:23:38:03.000000
ToString("HH:mm:ss.ffffff", false)
3. 压缩日期格式
// 输出:25/7/29
ToString("yy/M/d", true)
📌 总结要点
- 状态驱动设计:双变量(symbol/size)实现高效状态跟踪
- 分层处理架构:
- 格式扫描 → 状态管理 → 分量转换 → 宽度控制 → 结果构建
- 关键处理流程:
- 流程子图:
-
核心算法:
- 线性扫描格式字符串 O(n)
- 状态变更触发分组处理
- 数值到字符串的精确转换
-
流程子图:
“日期格式化是时间数据的符号化表达——状态机驱动字符串的精密重组”