C++make12 make24小时制转换
C++ 实现 12 小时制与 24 小时制时间格式双向转换
在日常开发中,时间格式的解析与转换是基础而高频的需求。尤其在国际化应用、日志分析、用户界面展示等场景下,12 小时制(如 02:30 PM)与 24 小时制(如 14:30)之间的准确互转至关重要。C++ 标准库虽提供 <chrono> 和 <iomanip> 等强大工具,但对带 AM/PM 的字符串解析仍需手动处理。本文将完整实现一个健壮、可复用的 C++ 时间转换模块,支持双向转换、输入校验与异常防护,代码简洁清晰,符合现代 C++ 风格(C++17 及以上)。
核心设计思路
转换逻辑需覆盖三类关键问题:
- 语义映射:
12:00 AM→00:00,12:00 PM→12:00,01:00 PM→13:00; - 格式鲁棒性:兼容空格、大小写(
am/AM/a.m.)、前导零缺失(9:5 AM); - 错误防御:拒绝非法输入(如
13:00 AM、25:00、8:65 PM),返回明确错误状态。
我们不依赖第三方库,仅使用 <string>、<cctype>、<sstream> 和 <stdexcept>,确保轻量可嵌入。
完整实现代码
以下为封装在命名空间 timeconv 中的两个核心函数:
#include <string>
#include <cctype>
#include <sstream>
#include <stdexcept>
namespace timeconv {
// 将 12 小时制字符串(如 "02:30 PM")转为 24 小时制 "HH:MM" 格式
std::string to_24h(const std::string& input) {
if (input.empty()) {
throw std::invalid_argument("Empty input string");
}
// 提取时间主体与周期标识(AM/PM)
std::string time_part, period;
size_t pos = input.find_first_of("aApPmM");
if (pos == std::string::npos) {
throw std::invalid_argument("Missing AM/PM indicator");
}
// 分离时间数字部分与周期部分(忽略中间空格)
time_part = input.substr(0, pos);
period = input.substr(pos);
// 清理 period:只保留字母并转大写
std::string clean_period;
for (char c : period) {
if (std::isalpha(c)) {
clean_period += std::toupper(c);
}
}
if (clean_period != "AM" && clean_period != "PM") {
throw std::invalid_argument("Invalid period: " + clean_period);
}
// 解析 HH:MM
std::istringstream iss(time_part);
int hour = 0, minute = 0;
char colon;
if (!(iss >> hour >> colon >> minute) || colon != ':') {
throw std::invalid_argument("Invalid time format: missing colon or digits");
}
// 校验数值范围
if (hour < 1 || hour > 12) {
throw std::invalid_argument("Hour must be 1–12 in 12-hour format");
}
if (minute < 0 || minute > 59) {
throw std::invalid_argument("Minute must be 0–59");
}
// 转换逻辑
if (clean_period == "AM") {
if (hour == 12) hour = 0; // 12:xx AM → 00:xx
} else { // PM
if (hour != 12) hour += 12; // 1:xx PM → 13:xx, ..., 11:xx PM → 23:xx
// 12:xx PM remains 12:xx
}
// 格式化为两位数字符串
std::ostringstream oss;
oss.fill('0');
oss.width(2);
oss << hour;
oss << ':';
oss.width(2);
oss << minute;
return oss.str();
}
// 将 24 小时制字符串(如 "14:30")转为 12 小时制 "H:MM AM/PM"(无前导零)
std::string to_12h(const std::string& input) {
if (input.empty()) {
throw std::invalid_argument("Empty input string");
}
std::istringstream iss(input);
int hour = 0, minute = 0;
char colon;
if (!(iss >> hour >> colon >> minute) || colon != ':') {
throw std::invalid_argument("Invalid 24-hour format: expected HH:MM");
}
if (hour < 0 || hour > 23) {
throw std::invalid_argument("Hour must be 0–23 in 24-hour format");
}
if (minute < 0 || minute > 59) {
throw std::invalid_argument("Minute must be 0–59");
}
std::string period = (hour < 12) ? "AM" : "PM";
int display_hour = hour % 12;
if (display_hour == 0) display_hour = 12; // 0→12, 12→12, 13→1...
std::ostringstream oss;
oss << display_hour << ':';
oss.fill('0');
oss.width(2);
oss << minute;
oss << ' ' << period;
return oss.str();
}
} // namespace timeconv
使用示例与测试验证
调用方式直观简洁:
#include <iostream>
#include <string>
int main() {
try {
std::cout << timeconv::to_24h("12:00 AM") << '\n'; // "00:00"
std::cout << timeconv::to_24h("01:45 PM") << '\n'; // "13:45"
std::cout << timeconv::to_24h("9:05 am") << '\n'; // "09:05"
std::cout << timeconv::to_24h("12:30 PM") << '\n'; // "12:30"
std::cout << timeconv::to_12h("00:15") << '\n'; // "12:15 AM"
std::cout << timeconv::to_12h("12:00") << '\n'; // "12:00 PM"
std::cout << timeconv::to_12h("23:59") << '\n'; // "11:59 PM"
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << '\n';
}
return 0;
}
运行结果严格符合标准时间语义,且所有边界情况(如 12:00 AM/PM、单数字小时、大小写混用)均被正确处理。
注意事项与扩展建议
- 当前实现默认采用宽松空格处理,若需更严格的格式匹配(如禁止
9:5 AM),可在解析前添加正则或增强分词逻辑; - 对于高并发服务,可将字符串操作改为
std::string_view(C++17)以减少拷贝; - 若需支持时区或秒级精度,建议在此基础上集成
<chrono>进行时间点运算; - 生产环境建议增加单元测试覆盖全部边界用例(如
00:00、12:60、空输入、纯空格等)。
结语
本文提供的 C++ 时间转换模块兼具正确性、可读性与工程实用性。它不依赖外部组件,逻辑清晰,错误提示明确,可直接集成至各类 C++ 项目中。掌握此类基础转换能力,不仅提升日常编码效率,也为构建更复杂的时间处理系统奠定坚实基础。时间虽无形,但其表达必须精确——这正是程序员对确定性的不懈追求。
文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

