You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多操作系统下SSL证书过期时间转Epoch秒数的通用实现求助

解决跨系统SSL证书过期时间解析到Epoch秒的通用方案

优先用libcurl自带的curl_getdate

curl_getdate是libcurl专门设计用来解析HTTP标准日期格式的工具,原生支持RFC 1123、RFC 850、ASCII时间戳,甚至兼容你遇到的Windows ISO格式(2031-04-13 23:59:59 GMT),能覆盖绝大多数场景:

#include <curl/curl.h>
#include <ctime>
#include <string>

std::time_t cert_date_to_epoch(const std::string& date_str) {
    // 返回-1表示解析失败,成功则直接返回UTC时间的Epoch秒数
    std::time_t epoch = curl_getdate(date_str.c_str(), nullptr);
    if (epoch == -1) {
        throw std::invalid_argument("curl_getdate failed to parse: " + date_str);
    }
    return epoch;
}

多格式降级解析(标准库实现)

如果curl_getdate意外失效,用C++11及以上标准库,通过遍历多种常见格式解析,无需第三方依赖:

#include <chrono>
#include <ctime>
#include <string>
#include <sstream>
#include <vector>
#include <stdexcept>

std::time_t parse_to_epoch(const std::string& date_str) {
    // 先尝试curl_getdate
    std::time_t curl_result = curl_getdate(date_str.c_str(), nullptr);
    if (curl_result != -1) {
        return curl_result;
    }

    // 定义所有可能遇到的日期格式
    const std::vector<std::string> formats = {
        "%Y-%m-%d %H:%M:%S GMT",    // Windows ISO格式
        "%b %d %H:%M:%S %Y GMT",    // CentOS缩写月份格式
        "%a, %d %b %Y %H:%M:%S GMT",// RFC 1123标准格式
        "%A, %d-%b-%y %H:%M:%S GMT" // RFC 850格式
    };

    std::tm tm = {};
    for (const auto& fmt : formats) {
        std::istringstream ss(date_str);
        ss >> std::get_time(&tm, fmt.c_str());
        if (!ss.fail()) {
            // timegm将UTC时间的tm结构体转为Epoch秒(不要用mktime,它会用本地时区)
            return timegm(&tm);
        }
    }

    throw std::invalid_argument("Unrecognized date format: " + date_str);
}

修复Boost解析的报错问题

你之前遇到的boost::gregorian::bad_month异常,是因为只用了适配CentOS的缩写月份格式去解析Windows的数字月份格式,导致月份解析失败。解决方法是遍历多种格式尝试:

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <string>
#include <sstream>
#include <vector>

namespace bt = boost::date_time;
typedef bt::posix_time::ptime ptime;

std::time_t boost_parse_to_epoch(const std::string& date_str) {
    const std::vector<std::string> formats = {
        "%Y-%m-%d %H:%M:%S GMT",
        "%b %d %H:%M:%S %Y GMT",
        "%a, %d %b %Y %H:%M:%S GMT"
    };

    bt::time_input_facet* facet = new bt::time_input_facet();
    std::istringstream ss(date_str);
    ss.imbue(std::locale(ss.getloc(), facet));

    ptime pt;
    for (const auto& fmt : formats) {
        facet->format(fmt.c_str());
        ss.clear(); // 重置流状态
        ss.seekg(0); // 回到流开头
        ss >> pt;
        if (pt != bt::posix_time::not_a_date_time) {
            // 计算与Epoch时间的差值
            auto epoch = ptime(bt::gregorian::date(1970, 1, 1));
            auto diff = pt - epoch;
            return diff.total_seconds();
        }
    }

    throw std::invalid_argument("Boost failed to parse date: " + date_str);
}

关键注意事项

  • 必须用UTC时间转换:不管是timegm还是Boost的ptime计算,都要基于UTC,避免本地时区导致的时间偏差。
  • 不要硬绑定单一格式:不同系统、不同证书返回的日期格式可能有差异,遍历多种常见格式是通用方案的核心。

内容的提问来源于stack exchange,提问作者Anees

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 06:54:06