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

如何用Boost Date Time Input/Output解析带序数后缀的日期?

解析带序数后缀的日期(Boost Date Time)

针对你遇到的Boost Date Time无法解析带序数后缀(如st/nd/rd/th)的日期问题,这里提供两种实用解决方案:

方法1:预处理字符串移除序数后缀

先对输入字符串做简单处理,剥离日期数字后的序数后缀,再用标准格式解析。这种方案简单直接,适合偶尔处理此类日期的场景。

示例代码:

#include <boost/date_time/gregorian/gregorian.hpp>
#include <regex>
#include <string>
#include <sstream>
#include <iostream>

using namespace boost::gregorian;

date parse_ordinal_date(const std::string& input) {
    // 正则替换:保留日期数字,移除后续的序数后缀
    std::regex ordinal_regex(R"((\d+)(st|nd|rd|th))");
    std::string processed = std::regex_replace(input, ordinal_regex, "$1");
    
    // 用原格式解析处理后的字符串
    date d;
    std::istringstream iss(processed);
    date_input_facet* facet = new date_input_facet("%B %e, %Y");
    iss.imbue(std::locale(iss.getloc(), facet));
    iss >> d;
    return d;
}

int main() {
    std::string date_str = "January 2nd, 2024";
    date d = parse_ordinal_date(date_str);
    std::cout << to_simple_string(d) << std::endl; // 输出:2024-Jan-02
    return 0;
}

方法2:自定义解析Facet(长期优雅方案)

如果需要频繁解析这类日期,可以自定义Boost的date_input_facet,扩展解析逻辑,让它在识别日期数字后自动跳过后续的序数后缀字符,无需修改原字符串。

示例代码:

#include <boost/date_time/gregorian/gregorian.hpp>
#include <locale>
#include <cctype>
#include <sstream>
#include <iostream>

using namespace boost::gregorian;

class ordinal_date_input_facet : public date_input_facet {
public:
    ordinal_date_input_facet(const std::string& format = "%x") : date_input_facet(format) {}

protected:
    virtual bool parse_date(std::istream& is, date& d, bool ignore) {
        // 先调用基类解析日期数字核心部分
        bool parse_success = date_input_facet::parse_date(is, d, ignore);
        if (!parse_success) return false;
        
        // 跳过后续的所有字母字符(即序数后缀)
        while (is && std::isalpha(static_cast<unsigned char>(is.peek()))) {
            is.ignore();
        }
        return true;
    }
};

int main() {
    std::string date_str = "January 2th, 2024"; // 错误后缀也能正常解析
    date d;
    std::istringstream iss(date_str);
    ordinal_date_input_facet* facet = new ordinal_date_input_facet("%B %e, %Y");
    iss.imbue(std::locale(iss.getloc(), facet));
    iss >> d;
    std::cout << to_iso_extended_string(d) << std::endl; // 输出:2024-01-02
    return 0;
}

注意事项

  • 两种方案都不会校验序数后缀的合法性,符合你忽略后缀具体字符的需求
  • 确保项目已正确链接Boost Date Time库

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 17:03:24