使用time_input_facet boost datetime时,posix_time无法解析单个数字的日期。在最初发帖时,我不知道https://github.com/boostorg/date_time/issues/106描述了这个问题,正如在接受的答案中指出的那样。
#include <boost/date_time/posix_time/posix_time.hpp>
#include <vector>
void date_from_string(const std::string& format, const std::string& date_str, boost::posix_time::ptime& date) {
auto* facet = new boost::posix_time::time_input_facet;
facet->format(format.c_str());
std::stringstream ss(date_str);
ss.imbue(std::locale(std::locale::classic(), facet));
ss >> date;
// delete facet; > "Your program has UB. delete facet; leads to double-free."
}
int main() {
std::cout << "Boost Version: " << BOOST_VERSION << std::endl; // 107500
// Boost Version: 107500
for (auto& i : std::vector<std::pair<std::string,std::string>>{
{"%a, %d %b %Y %H:%M:%S %ZP","Thu, 17 Oct 2021 15:00:00 GMT"},
// 2021-Oct-17 15:00:00 from str: Thu, 17 Oct 2021 15:00:00 GMT using: %a, %d %b %Y %H:%M:%S %ZP
{"%a, %d %b %Y %H:%M:%S %ZP","Thu, 7 Oct 2021 15:00:00 GMT"},
// not-a-date-time from str: Thu, 7 Oct 2021 15:00:00 GMT using: %a, %d %b %Y %H:%M:%S %ZP
{"%d", "7"},
// not-a-date-time from str: 7 using: %d
{"%d", "07"}
// 1400-Jan-07 00:00:00 from str: 07 using: %d
}) {
boost::posix_time::ptime m_date;
date_from_string(i.first, i.second,m_date);
std::cout << boost::posix_time::to_simple_string(m_date) << " from str: " << i.second << " using: " << i.first << std::endl;
}
}
%d以十进制形式01到31表示的月份中的第几天。当用于解析输入时,前导零是可选的。(强调我的)
https://www.boost.org/doc/libs/1_75_0/doc/html/date_time/date_time_io.html (format flags)
您的程序有UB。delete facet;
导致双自由。
此外,您只使用了一个时间输入facet。我想知道是否还需要日期输入方面。因此,我扩展了这个示例,以排除其中的一些问题:
Live On Compiler Explorer
#include <boost/date_time/local_time/local_time_io.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iomanip>
using DateTime = boost::local_time::local_date_time;
using PTime = boost::posix_time::ptime;
using Date = boost::gregorian::date;
using boost::date_time::not_a_date_time;
void date_from_string( //
std::string const& dformat, std::string const& dtformat,
std::string const& date_str, DateTime& date)
{
std::stringstream ss(date_str);
ss.imbue(std::locale::classic());
ss.imbue(std::locale( //
ss.getloc(), new boost::gregorian::date_input_facet(dformat)));
ss.imbue(std::locale(
ss.getloc(), new boost::local_time::local_time_input_facet(dtformat)));
ss >> date;
}
void date_from_string( //
std::string const& dformat, std::string const& dtformat,
std::string const& date_str, PTime& date)
{
std::stringstream ss(date_str);
ss.imbue(std::locale::classic());
ss.imbue(std::locale(ss.getloc(),
new boost::gregorian::date_input_facet(dformat)));
ss.imbue(std::locale(ss.getloc(),
new boost::posix_time::time_input_facet(dtformat)));
ss >> date;
}
void date_from_string(std::string const& dformat, std::string const& date_str,
Date& date)
{
std::stringstream ss(date_str);
ss.imbue(std::locale::classic());
ss.imbue(std::locale(ss.getloc(),
new boost::gregorian::date_input_facet(dformat)));
ss >> date;
}
int main() {
std::cout << "Boost Version: " << BOOST_VERSION << std::endl; // 107500
std::string const fmt = "%a, %d %b %Y";
struct {
std::string dformat, dtformat, input;
} tests[]{
{fmt, fmt + " %H:%M:%S %ZP", "Thu, 17 Oct 2021 15:00:00 GMT"},
{"%d", "%d", "07"},
{fmt, fmt + " %H:%M:%S %ZP", "Thu, 7 Oct 2021 15:00:00 GMT"},
{"%d", "%d", "7"},
};
for (auto& [df, dtf, input] : tests) {
std::cout << " -- from str: " << std::quoted(input)
<< " using: " << std::quoted(df) << "n";
Date m_date;
DateTime m_datetime(not_a_date_time);
PTime m_ptime(not_a_date_time);
date_from_string(df, input, m_date);
date_from_string(df, dtf, input, m_datetime);
date_from_string(df, dtf, input, m_ptime);
std::cout << " Date: " << to_simple_string(m_date) << "n";
std::cout << " Local: " << to_simple_string(m_datetime.date()) << "n";
std::cout << " Posix: " << to_simple_string(m_ptime.date()) << "n";
}
}
和输出确认错误:
Boost Version: 107700
-- from str: "Thu, 17 Oct 2021 15:00:00 GMT" using: "%a, %d %b %Y"
Date: 2021-Oct-17
Local: 2021-Oct-17
Posix: 2021-Oct-17
-- from str: "07" using: "%d"
Date: 1400-Jan-07
Local: 1400-Jan-07
Posix: 1400-Jan-07
-- from str: "Thu, 7 Oct 2021 15:00:00 GMT" using: "%a, %d %b %Y"
Date: not-a-date-time
Local: not-a-date-time
Posix: not-a-date-time
-- from str: "7" using: "%d"
Date: not-a-date-time
Local: not-a-date-time
Posix: not-a-date-time
下一个什么?
我支持这个现有的票:https://github.com/boostorg/date_time/issues/106
此外,我可以指出这个adaptive_parser
我在过去,它回避了问题,不使用IO流解析在这里c++ boost date_input_facet似乎解析日期意外与不正确的格式传递给facet构造器