多操作系统下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
相关产品推荐
相关产品推荐

