c++11 使用chrono库转换时间点和字符串,计算时间点间隔

需要导入以下头文件

cpp 复制代码
#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <ratio>
#include <sstream>

1.将日期字符串转换为时间点对象

按 std::get_time 格式串解析本地日期时间,并转换为 system_clock 时间点。

关键代码std::get_time(&calendar_time, date_format.c_str());

cpp 复制代码
// 按 std::get_time 格式串解析本地日期时间,并转换为 system_clock 时间点。
std::chrono::system_clock::time_point date_string_to_time_point(
    const std::string &date_string, const std::string &date_format) {
    // 未指定日期时默认使用每月 1 日,未指定时间时默认为 00:00:00。
    std::tm calendar_time = {};
    calendar_time.tm_mday = 1;
    std::istringstream date_stream{ date_string };
    date_stream >> std::get_time(&calendar_time, date_format.c_str());
    // 要求格式串成功解析整个输入,避免忽略尾部多余字符。
    if (date_stream.fail() || date_stream.peek() != std::char_traits<char>::eof()) {
        throw std::invalid_argument("date string does not match the given format");
    }

    // 保存解析结果;mktime 会规范化 tm,之后用原值检查日期时间是否合法。
    const int expected_year = calendar_time.tm_year;
    const int expected_month = calendar_time.tm_mon;
    const int expected_day = calendar_time.tm_mday;
    const int expected_hour = calendar_time.tm_hour;
    const int expected_minute = calendar_time.tm_min;
    const int expected_second = calendar_time.tm_sec;
    // 由运行库根据本地时区确定夏令时状态;日期时间按本地时间解释。
    calendar_time.tm_isdst = -1;
    const std::time_t timestamp = std::mktime(&calendar_time);
    if (timestamp == static_cast<std::time_t>(-1) || calendar_time.tm_year != expected_year ||
        calendar_time.tm_mon != expected_month || calendar_time.tm_mday != expected_day ||
        calendar_time.tm_hour != expected_hour || calendar_time.tm_min != expected_minute ||
        calendar_time.tm_sec != expected_second) {
        throw std::invalid_argument("date string is not a valid local date/time");
    }

    // 将本地日历时间对应的 time_t 转换为 system_clock 时间点。
    return std::chrono::system_clock::from_time_t(timestamp);
}

2.将时间点对象转换为日期字符串

按 std::put_time 格式串将 system_clock 时间点转换为本地日期时间字符串。

关键代码std::put_time(calendar_time, date_format.c_str());

cpp 复制代码
// 按 std::put_time 格式串将 system_clock 时间点转换为本地日期时间字符串。
std::string time_point_to_date_string(
    const std::chrono::system_clock::time_point &time_point, const std::string &date_format) {
    const std::time_t timestamp = std::chrono::system_clock::to_time_t(time_point);
    const std::tm *calendar_time = std::localtime(&timestamp);
    if (calendar_time == nullptr) {
        throw std::runtime_error("time point cannot be represented as local time");
    }

    std::ostringstream date_stream;
    date_stream << std::put_time(calendar_time, date_format.c_str());
    if (date_stream.fail()) {
        throw std::runtime_error("date format could not be applied");
    }
    return date_stream.str();
}

3.计算时间点间隔

cpp 复制代码
// 将两个同一时钟的时间点之差转换为 Unit;Rep 控制结果类型及小数是否保留。
template <typename Rep, typename Clock, typename Duration1, typename Duration2, typename Unit>
Rep calculate_time_distance(const std::chrono::time_point<Clock, Duration1> &first_time,
    const std::chrono::time_point<Clock, Duration2> &second_time, Unit) {
    // 使用目标单位的周期和指定的 Rep 构造结果 duration,再读取其计数。
    typedef std::chrono::duration<Rep, typename Unit::period> ResultDuration;
    return std::chrono::duration_cast<ResultDuration>(second_time - first_time).count();
}

4.测试

cpp 复制代码
    const std::string date1_str = "2026/01/01 00:00:00";
const std::string date2_str = "2026/01/01 01:12:13";
const std::string date_format_str = "%Y/%m/%d %H:%M:%S";
const std::string other_date_format_str = "%Y-%m-%d %H:%M:%S";

// 测试字符串转换为时间点
const std::chrono::system_clock::time_point date1 =
    date_string_to_time_point(date1_str, date_format_str);
// 测试时间点转换为字符串
const std::string formated_date1_str =
    time_point_to_date_string(date1, other_date_format_str);
std::cout << "Formatted date1: " << formated_date1_str
            << "\n"; // Formatted date1: 2026-01-01 00:00:00

const std::chrono::system_clock::time_point date2 =
    date_string_to_time_point(date2_str, date_format_str);
const std::string formated_date2_str =
    time_point_to_date_string(date2, other_date_format_str);
std::cout << "Formatted date1: " << formated_date2_str
            << "\n"; // Formatted date1: 2026-01-01 01:12:13

// 测试计算时间点间隔
double distance_hour_float =
    calculate_time_distance<double>(date1, date2, std::chrono::hours{ 1 });
std::cout << "Time distance (floating hours): " << distance_hour_float
            << " hours\n"; // Time distance (floating hours): 1.20361 hours
double distance_minute_float =
    calculate_time_distance<double>(date1, date2, std::chrono::minutes{ 1 });
std::cout << "Time distance (floating minutes): " << distance_minute_float
            << " minutes\n"; // Time distance (floating minutes): 72.2167 minutes
double distance_second_float =
    calculate_time_distance<double>(date1, date2, std::chrono::seconds{ 1 });
std::cout << "Time distance (floating seconds): " << distance_second_float
            << " seconds\n"; // Time distance (floating seconds): 4333 seconds
相关推荐
我最爱吃鱼香茄子3 小时前
【毕业设计优选】人力资源管理系统|Java|SpringBoot|Vue|前后端分离|带详细文档+部署教学视频
java·vue·毕业设计·springboot
步行cgn3 小时前
Spring 只读事务面试详解
java·spring·面试
APIshop3 小时前
淘宝详情接口全解析:从官方开放平台到第三方数据服务
java·python·api
老歌老听老掉牙3 小时前
两个平面旋转平移坐标系间的坐标变换关系
python·算法·平面·旋转·平移
W.A委员会3 小时前
PID与PID整定
python·算法
蜕变的土豆3 小时前
工业监控RTSP取流-实践指南
c++·视频
进化中的刀盾兽3 小时前
从零实现 C++ Json-Rpc(八):补齐 detail.hpp——JSON 封装与请求 ID 生成
c++·rpc
省钱兄--zs3 小时前
24小时自助健身房系统软件开发实战:从架构设计到部署全指南
java·数据仓库·spring boot·系统架构·需求分析
IT研究室3 小时前
最新计算机毕业设计选题推荐-基于spring boot的智慧教学资源管理与互动交流平台-网站-文档指导-Java-springboot
java·spring boot·课程设计