Boost :: DateTime无法正确解析

时间:2014-10-05 06:36:41

标签: c++ parsing datetime boost

我使用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.imbue()似乎并没有以这种方式为我工作,尽管已经在其他地方搜索并找到了类似的代码。我总是得到一个not_a_date_time。如果我用

替换它,它工作正常
ss.imbue(std::locale(std::locale::classic(), new bt::time_input_facet("%d%m%Y %H:%M")));

但是因为我需要循环使用不同的格式,这不是一个真正的选择。

1 个答案:

答案 0 :(得分:0)

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

以下是修复:

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

现在,您仍需要修复已接受的输入格式的顺序。见 Live On 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;
    }
}