Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;boost date\u input\u facet似乎意外地解析了传递给facet构造函数的格式不正确的日期_C++_Date_Parsing_Boost - Fatal编程技术网

C++ C++;boost date\u input\u facet似乎意外地解析了传递给facet构造函数的格式不正确的日期

C++ C++;boost date\u input\u facet似乎意外地解析了传递给facet构造函数的格式不正确的日期,c++,date,parsing,boost,C++,Date,Parsing,Boost,我用于测试的coliru中的玩具代码: 我在使用C++之后又重新习惯了。我正在编写代码,解析可能有多个带有日期或空值的列的CSV。我的假设是,每个日期列都有一种有效的日期格式,尽管不同的列可能有不同的格式 对于我拥有的每个日期列,我都会找到第一个值,该值被成功解析为一个日期,给定了一个包含boost date\u input\u facet对象的潜在地区的std::vector。正确解析的第一个日期将返回我所在的区域设置数组中的索引。一旦我有了第一个可解析日期的合适格式,我想永远修复该格式,这

我用于测试的coliru中的玩具代码:

我在使用C++之后又重新习惯了。我正在编写代码,解析可能有多个带有日期或空值的列的CSV。我的假设是,每个日期列都有一种有效的日期格式,尽管不同的列可能有不同的格式

对于我拥有的每个日期列,我都会找到第一个值,该值被成功解析为一个日期,给定了一个包含boost date\u input\u facet对象的潜在地区的std::vector。正确解析的第一个日期将返回我所在的区域设置数组中的索引。一旦我有了第一个可解析日期的合适格式,我想永远修复该格式,这样我就不必再浪费CPU时间来检测该格式

以下是我的区域设置数组:

const std::vector<std::locale> Date::date_formats = {
    std::locale(std::locale::classic(), new date_input_facet("%Y-%m-%d")),
    std::locale(std::locale::classic(), new date_input_facet("%Y/%m/%d")),
    std::locale(std::locale::classic(), new date_input_facet("%m-%d-%Y")),
    std::locale(std::locale::classic(), new date_input_facet("%m/%d/%Y")),
    std::locale(std::locale::classic(), new date_input_facet("%d-%b-%Y")),
    std::locale(std::locale::classic(), new date_input_facet("%Y%m%d")),
};
对于20170130、20170131,报告了“%Y%m%d”的正确格式索引(第5个)


有什么想法吗?我只希望使用我传递的精确格式字符串。

我自己制作了一个支持多种格式的日期-时间解析器。一、 同样,他们发现使用标准库和boost中的工具很难/不可能严格解析

我最终使用了
strtime
——大部分是\

计划以支持的格式列表为种子,顺序为 偏爱默认情况下,解析器是不自适应的(模式是
固定的

在自适应模式下,可以要求

  • sticky
    (始终重复使用第一个匹配的格式)
  • ban_failed
    (从列表中删除失败的模式;仅发生禁止 成功解析以避免禁止无效输入上的所有模式)
  • mru
    (保留列表,但为性能重新排序)
  • 注意:
    如果格式不明确(例如,
    mm-dd-yyyy
    vs
    dd-mm-yyyy
    ),则允许 重新排序会导致不可预测的结果

    ⇒ 只有在没有不明确的格式时才使用
    mru

  • 注:
    函数对象是有状态的。在算法中,通过引用传递它 (
    std::ref(obj)
    )以避免复制模式并确保正确 适应行为

演示 我在您的测试数据上尝试了解析器:

#include "adaptive_parser.h"
#include <boost/date_time/gregorian/greg_date.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

class Date{
public:
    Date() : y(0), m(0), d(0) {}
    Date(int yy, int mm, int dd) : y(yy), m(mm), d(dd) {}
    Date(boost::gregorian::date dt) : y(dt.year()), m(dt.month()), d(dt.day()) {}
    Date(std::string const& delimitedString);

    std::string to_string() const;

    int getYear()  const { return y; }
    int getMonth() const { return m; }
    int getDay()   const { return d; }
 private:
    using parser_t = mylib::datetime::adaptive_parser;
    parser_t parser { parser_t::full_match, 
        {
            "%Y-%m-%d", "%Y/%m/%d",
            "%m-%d-%Y", "%m/%d/%Y",
            "%d-%b-%Y",
            "%Y%m%d",
        } };

    int y, m, d;
};

Date::Date(const std::string& delimitedString)
{
    using namespace boost::posix_time;

    auto t = ptime({1970,1,1}) + seconds(parser(delimitedString).count());

    *this = Date(t.date());
}

std::string Date::to_string() const
{
    std::ostringstream os;

    os << std::setfill('0')
       << std::setw(4) << y 
       << std::setw(2) << m 
       << std::setw(2) << d;

    return os.str();
}

int main() {
    std::vector<Date> vec(31);
    std::generate(vec.begin(), vec.end(), [i=1]() mutable { return Date(2017,1,i++); });

    std::vector<std::string> strvec;
    std::transform(vec.begin(), vec.end(), back_inserter(strvec), std::mem_fn(&Date::to_string));

    std::cout << "YYYYMMDD\tpY\tpM\tpD\tformat_index\n";

    for (auto& str : strvec) {
        Date parsed(str);

        std::cout << str 
            << "\t" << parsed.getYear()
            << "\t" << parsed.getMonth()
            << "\t" << parsed.getDay()
            << "\t" << "?"
            << "\n";
    }
}


只是时区的东西需要调整,主要是我自己做了一个多格式的日期时间解析器。一、 同样,他们发现使用标准库和boost中的工具很难/不可能严格解析

我最终使用了
strtime
——大部分是\

计划以支持的格式列表为种子,顺序为 偏爱默认情况下,解析器是不自适应的(模式是
固定的

在自适应模式下,可以要求

  • sticky
    (始终重复使用第一个匹配的格式)
  • ban_failed
    (从列表中删除失败的模式;仅发生禁止 成功解析以避免禁止无效输入上的所有模式)
  • mru
    (保留列表,但为性能重新排序)
  • 注意:
    如果格式不明确(例如,
    mm-dd-yyyy
    vs
    dd-mm-yyyy
    ),则允许 重新排序会导致不可预测的结果

    ⇒ 只有在没有不明确的格式时才使用
    mru

  • 注:
    函数对象是有状态的。在算法中,通过引用传递它 (
    std::ref(obj)
    )以避免复制模式并确保正确 适应行为

演示 我在您的测试数据上尝试了解析器:

#include "adaptive_parser.h"
#include <boost/date_time/gregorian/greg_date.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

class Date{
public:
    Date() : y(0), m(0), d(0) {}
    Date(int yy, int mm, int dd) : y(yy), m(mm), d(dd) {}
    Date(boost::gregorian::date dt) : y(dt.year()), m(dt.month()), d(dt.day()) {}
    Date(std::string const& delimitedString);

    std::string to_string() const;

    int getYear()  const { return y; }
    int getMonth() const { return m; }
    int getDay()   const { return d; }
 private:
    using parser_t = mylib::datetime::adaptive_parser;
    parser_t parser { parser_t::full_match, 
        {
            "%Y-%m-%d", "%Y/%m/%d",
            "%m-%d-%Y", "%m/%d/%Y",
            "%d-%b-%Y",
            "%Y%m%d",
        } };

    int y, m, d;
};

Date::Date(const std::string& delimitedString)
{
    using namespace boost::posix_time;

    auto t = ptime({1970,1,1}) + seconds(parser(delimitedString).count());

    *this = Date(t.date());
}

std::string Date::to_string() const
{
    std::ostringstream os;

    os << std::setfill('0')
       << std::setw(4) << y 
       << std::setw(2) << m 
       << std::setw(2) << d;

    return os.str();
}

int main() {
    std::vector<Date> vec(31);
    std::generate(vec.begin(), vec.end(), [i=1]() mutable { return Date(2017,1,i++); });

    std::vector<std::string> strvec;
    std::transform(vec.begin(), vec.end(), back_inserter(strvec), std::mem_fn(&Date::to_string));

    std::cout << "YYYYMMDD\tpY\tpM\tpD\tformat_index\n";

    for (auto& str : strvec) {
        Date parsed(str);

        std::cout << str 
            << "\t" << parsed.getYear()
            << "\t" << parsed.getMonth()
            << "\t" << parsed.getDay()
            << "\t" << "?"
            << "\n";
    }
}

只是时区的东西需要调整,主要是使用以下方法:

使用以下命令:


没有解释,但我非常感谢您在提供的链接中所做的工作!稍后我会更详细地阅读。你添加的语法糖也不错!没有解释,但我非常感谢您在提供的链接中所做的工作!稍后我会更详细地阅读。你添加的语法糖也不错!非常好…所以我猜你遇到了和我一样的不直观的事情-std/boost的人真的需要修复它!我当然也很欣赏你适应能力的灵活性——这正是我想要做的。假设它能工作(我肯定能),这看起来很棒。Boost的输入方面:很难知道什么是bug,什么不是由于未指定的契约造成的。但是,是的,它在我的书中是不可用的非常好…所以我猜你遇到了和我一样的不直观的东西-性病/艾滋病患者真的需要修复它!我当然也很欣赏你适应能力的灵活性——这正是我想要做的。假设它能工作(我肯定能),这看起来很棒。Boost的输入方面:很难知道什么是bug,什么不是由于未指定的契约造成的。但是是的,在我的书里它是不能用的
YYYYMMDD    pY  pM  pD  format_index
20170101    2017    1   1   ?
20170102    2017    1   2   ?
20170103    2017    1   3   ?
20170104    2017    1   4   ?
20170105    2017    1   5   ?
20170106    2017    1   6   ?
20170107    2017    1   7   ?
20170108    2017    1   8   ?
20170109    2017    1   9   ?
20170110    2017    1   10  ?
20170111    2017    1   11  ?
20170112    2017    1   12  ?
20170113    2017    1   13  ?
20170114    2017    1   14  ?
20170115    2017    1   15  ?
20170116    2017    1   16  ?
20170117    2017    1   17  ?
20170118    2017    1   18  ?
20170119    2017    1   19  ?
20170120    2017    1   20  ?
20170121    2017    1   21  ?
20170122    2017    1   22  ?
20170123    2017    1   23  ?
20170124    2017    1   24  ?
20170125    2017    1   25  ?
20170126    2017    1   26  ?
20170127    2017    1   27  ?
20170128    2017    1   28  ?
20170129    2017    1   29  ?
20170130    2017    1   30  ?
20170131    2017    1   31  ?
#include "date/date.h"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

int
localeIndexFromString(const std::string& delimitedString)
{
    using namespace std;
    static vector<string> date_formats
    {
        "%Y-%m-%d",
        "%Y/%m/%d",
        "%m-%d-%Y",
        "%m/%d/%Y",
        "%d-%b-%Y",
        "%Y%m%d"
    };

    istringstream is;
    date::year_month_day dt;
    size_t i;
    for (i = 0; i < date_formats.size(); ++i)
    {
        is.clear();
        is.str(delimitedString);
        is >> date::parse(date_formats[i], dt);
        if (!is.fail())
        {
            std::cout << dt.year() << "\t" << dt.month() << "\t" << dt.day();
            return i;
        }
    }
    return -1;
}

int
main()
{
    using namespace date::literals;
    std::vector<date::year_month_day> vec;
    for (auto i = 1; i < 32; ++i)
        vec.push_back(2017_y/jan/i);

    std::vector<std::string> strvec;
    for (auto const& d : vec)
        strvec.push_back(date::format("%Y%m%d", d));

    std::cout << "YYYYMMDD\tpY\tpM\tpD\tformat_index\n";

    for (size_t i=0; i < strvec.size(); ++i)
    {
        std::cout << strvec[i] << "\t";
        int fmt_index = localeIndexFromString(strvec[i]);
        std::cout << "\t" << fmt_index << "\n";
    }
}
YYYYMMDD        pY        pM        pD        format_index
20170101        2017      Jan       01        5
20170102        2017      Jan       02        5
20170103        2017      Jan       03        5
20170104        2017      Jan       04        5
20170105        2017      Jan       05        5
20170106        2017      Jan       06        5
20170107        2017      Jan       07        5
20170108        2017      Jan       08        5
20170109        2017      Jan       09        5
20170110        2017      Jan       10        5
20170111        2017      Jan       11        5
20170112        2017      Jan       12        5
20170113        2017      Jan       13        5
20170114        2017      Jan       14        5
20170115        2017      Jan       15        5
20170116        2017      Jan       16        5
20170117        2017      Jan       17        5
20170118        2017      Jan       18        5
20170119        2017      Jan       19        5
20170120        2017      Jan       20        5
20170121        2017      Jan       21        5
20170122        2017      Jan       22        5
20170123        2017      Jan       23        5
20170124        2017      Jan       24        5
20170125        2017      Jan       25        5
20170126        2017      Jan       26        5
20170127        2017      Jan       27        5
20170128        2017      Jan       28        5
20170129        2017      Jan       29        5
20170130        2017      Jan       30        5
20170131        2017      Jan       31        5