Boost::DateTime无法正确分析

Boost::DateTime unable to parse correctly

本文关键字:DateTime Boost      更新时间:2023-10-16

我正在使用boost::date_time为VS2012的一系列日期输入格式构建一个简单的解析器。我写的有问题的部分在下面

#include <iostream>
#include <sstream>
#include <string>
#include "boost/date_time.hpp"
namespace bt = boost::posix_time;
const std::locale formats[] = {
    std::locale(std::locale::classic(), new bt::time_input_facet("%d%m%Y %H:%M")), //25042014 23:59
    std::locale(std::locale::classic(), new bt::time_input_facet("%d%m%y %H:%M")), //250414 23:59
    std::locale(std::locale::classic(), new bt::time_input_facet("%d%m %H:%M")) //2504 23:59
    //additional formats removed for brevity
};
const size_t formats_n = sizeof(formats)/sizeof(formats[0]);
int main(void) {
    std::string input = "25052014 12:45";
    bt::ptime dateTime;
    std::stringstream ss(input);
    for(size_t i = 0; i < formats_n; ++i) {
        ss.imbue(formats[i]);
        ss >> dateTime;
        if(dateTime != bt::not_a_date_time) {
            break;
        }
    }
    std::cout << dateTime << std::endl;
    return 0;
}

问题是ss.inbue()对我来说似乎不是这样工作的,尽管我在其他地方搜索并找到了类似的代码。我总是有一个非日期时间。如果我把它换成,效果会很好

ss.imbue(std::locale(std::locale::classic(), new bt::time_input_facet("%d%m%Y %H:%M")));

但由于我需要它在不同的格式中循环,所以这并不是一个真正的选择。

您忘记重置输入流。因此,如果第一个失败,它将继续失败。

修复方法如下:

        ss.clear();
        ss.seekg(0);

现在,您仍然需要修复已接受的输入格式的顺序。请参阅Coliru直播

考虑编写一个适合这种场景的解析器,因为仅仅通过对格式进行排序很难强制进行正确的解释。

流操作可能最适合固定格式(反)序列化。

完整代码

#include <iostream>
#include <sstream>
#include <string>
#include "boost/date_time.hpp"
namespace bt = boost::posix_time;
const std::locale formats[] = {
    std::locale(std::locale::classic(), new bt::time_input_facet("%d%m%Y %H:%M")), //25042014 23:59
    std::locale(std::locale::classic(), new bt::time_input_facet("%d%m%y %H:%M")), //250414 23:59
    std::locale(std::locale::classic(), new bt::time_input_facet("%d%m %H:%M")) //2504 23:59
    //additional formats removed for brevity
};
const size_t formats_n = sizeof(formats)/sizeof(formats[0]);
int main(void) {
    for (std::string input : {
            "25052014 12:45",
            "250514 12:45",
            "2505 12:45",
            })
    {
        bt::ptime dateTime;
        std::stringstream ss(input);
        for(size_t i = 0; i < formats_n; ++i) {
            ss.imbue(formats[i]);
            ss >> dateTime;
            if(dateTime != bt::not_a_date_time) {
                break;
            }
            ss.clear();
            ss.seekg(0);
        }
        std::cout << dateTime << std::endl;
    }
}