如何让 boost::program_options 与 boost::posix_time::ptime 一起工作?
How can you get boost::program_options working with boost::posix_time::ptime?
我已经多次尝试让这项工作无济于事。程序可以编译,但是我能想到的提供给程序的所有时间戳格式都是无效的。
#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <string>
using namespace boost::program_options;
using namespace std;
int main(int argc, const char** argv) {
boost::posix_time::ptime forceDate;
boost::optional<boost::posix_time::ptime> forceDateOptional;
options_description descr("Options");
descr.add_options()
("force-date,a", value(&forceDate)->value_name("<date>"), "...");
try {
variables_map args;
store(command_line_parser(argc, argv).options(descr).run(), args);
notify(args);
cout << "Done." << endl;
return 0;
} catch (std::exception& e) {
cerr << e.what() << endl;
return 1;
}
}
使用 g++ -I /usr/local/include -L /usr/local/lib -lboost_program_options -lboost_system x.cpp
和 运行 使用 ./a.out --force-date 2012-01-03
编译。
这是抛出异常的错误:
the argument ('2012-01-03') for option '--force-date' is invalid
我能够复制您的代码并在 Ubuntu 14.04 上编译它——我得到了与您相同的结果。所以我将日期传递给 std::string
,然后尝试从中构造一个 boost::posix_time::ptime
:
#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <string>
using namespace boost::program_options;
using namespace std;
int main (int argc, const char ** argv) {
auto dateStr = string {};
auto descr = options_description { "Options" };
descr.add_options ()
("help,h", "produce help message")
("date,a", value (&dateStr)->value_name ("<date>"), "...");
try {
auto args = variables_map {};
store (command_line_parser (argc, argv).options (descr).run (), args);
notify (args);
auto forceDate = boost::posix_time::ptime { dateStr };
cout << "Done." << endl;
return 0;
} catch (std::exception & e) {
cout << e.what () << endl;
return 1;
}
}
在发现 according to this SO answer 你必须 link boost_date_time
之前,我不得不四处挖掘一下。我用下面的脚本同时编译和重新运行:
rerun.sh
#!/bin/bash
g++ -o main.x64 -std=c++11 -I . -L/usr/lib/x86_64-linux-gnu main.cpp -lboost_program_options -lboost_system -lboost_date_time
./main.x64 --date "2012-01-01"
这是我用来获取它的最终代码 运行:
main.cpp
#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <string>
using namespace boost::program_options;
using namespace boost::posix_time;
using namespace std;
int main (int argc, const char ** argv) {
auto dateStr = string {};
auto descr = options_description { "Options" };
descr.add_options ()
("date,a", value (&dateStr)->value_name ("<date>"), "...");
try {
auto args = variables_map {};
store (command_line_parser (argc, argv).options (descr).run (), args);
notify (args);
// this is the important part.
auto d = boost::gregorian::date {
boost::gregorian::from_simple_string (dateStr)
};
auto forceDate = boost::posix_time::ptime { d };
cout << "Done." << endl;
return 0;
} catch (std::exception & e) {
cout << e.what () << endl;
return 1;
}
}
让我们首先尝试通过删除 program_options
并简单地尝试从流中解析 posix_time::ptime
来简化您的示例。
boost::posix_time::ptime forceDate;
std::istringstream ss("2012-01-03");
if(ss >> forceDate) {
std::cout << forceDate << "\n";
}
上面的例子没有打印任何东西,很明显解析出了问题。如果您查找 operator>>
的 documentation ,很明显月份的预期格式是缩写名称而不是数值。
如果把上面的代码改成
boost::posix_time::ptime forceDate;
std::istringstream ss("2012-Jan-03");
if(ss >> forceDate) {
std::cout << forceDate << "\n";
}
它会产生所需的输出。
通过 documentation 的更多挖掘显示了使用 boost::posix_time::time_input_facet
控制输入格式的方法。 set_iso_extended_format
将格式设置为您要使用的数字格式。
boost::posix_time::ptime forceDate;
std::istringstream ss("2012-01-03");
auto facet = new boost::posix_time::time_input_facet();
facet->set_iso_extended_format();
ss.imbue(std::locale(ss.getloc(), facet));
if(ss >> forceDate) {
std::cout << forceDate << "\n";
}
现在回到 program_options
。看起来图书馆不直接提供区域设置支持,所以我能让上述解决方案起作用的唯一方法是搞乱全局区域设置。如果您将以下行添加到您的示例中,它的行为将如您所愿。
auto facet = new boost::posix_time::time_input_facet();
facet->set_iso_extended_format();
std::locale::global(std::locale(std::locale(), facet));
我已经多次尝试让这项工作无济于事。程序可以编译,但是我能想到的提供给程序的所有时间戳格式都是无效的。
#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <string>
using namespace boost::program_options;
using namespace std;
int main(int argc, const char** argv) {
boost::posix_time::ptime forceDate;
boost::optional<boost::posix_time::ptime> forceDateOptional;
options_description descr("Options");
descr.add_options()
("force-date,a", value(&forceDate)->value_name("<date>"), "...");
try {
variables_map args;
store(command_line_parser(argc, argv).options(descr).run(), args);
notify(args);
cout << "Done." << endl;
return 0;
} catch (std::exception& e) {
cerr << e.what() << endl;
return 1;
}
}
使用 g++ -I /usr/local/include -L /usr/local/lib -lboost_program_options -lboost_system x.cpp
和 运行 使用 ./a.out --force-date 2012-01-03
编译。
这是抛出异常的错误:
the argument ('2012-01-03') for option '--force-date' is invalid
我能够复制您的代码并在 Ubuntu 14.04 上编译它——我得到了与您相同的结果。所以我将日期传递给 std::string
,然后尝试从中构造一个 boost::posix_time::ptime
:
#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <string>
using namespace boost::program_options;
using namespace std;
int main (int argc, const char ** argv) {
auto dateStr = string {};
auto descr = options_description { "Options" };
descr.add_options ()
("help,h", "produce help message")
("date,a", value (&dateStr)->value_name ("<date>"), "...");
try {
auto args = variables_map {};
store (command_line_parser (argc, argv).options (descr).run (), args);
notify (args);
auto forceDate = boost::posix_time::ptime { dateStr };
cout << "Done." << endl;
return 0;
} catch (std::exception & e) {
cout << e.what () << endl;
return 1;
}
}
在发现 according to this SO answer 你必须 link boost_date_time
之前,我不得不四处挖掘一下。我用下面的脚本同时编译和重新运行:
rerun.sh
#!/bin/bash
g++ -o main.x64 -std=c++11 -I . -L/usr/lib/x86_64-linux-gnu main.cpp -lboost_program_options -lboost_system -lboost_date_time
./main.x64 --date "2012-01-01"
这是我用来获取它的最终代码 运行:
main.cpp
#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <string>
using namespace boost::program_options;
using namespace boost::posix_time;
using namespace std;
int main (int argc, const char ** argv) {
auto dateStr = string {};
auto descr = options_description { "Options" };
descr.add_options ()
("date,a", value (&dateStr)->value_name ("<date>"), "...");
try {
auto args = variables_map {};
store (command_line_parser (argc, argv).options (descr).run (), args);
notify (args);
// this is the important part.
auto d = boost::gregorian::date {
boost::gregorian::from_simple_string (dateStr)
};
auto forceDate = boost::posix_time::ptime { d };
cout << "Done." << endl;
return 0;
} catch (std::exception & e) {
cout << e.what () << endl;
return 1;
}
}
让我们首先尝试通过删除 program_options
并简单地尝试从流中解析 posix_time::ptime
来简化您的示例。
boost::posix_time::ptime forceDate;
std::istringstream ss("2012-01-03");
if(ss >> forceDate) {
std::cout << forceDate << "\n";
}
上面的例子没有打印任何东西,很明显解析出了问题。如果您查找 operator>>
的 documentation ,很明显月份的预期格式是缩写名称而不是数值。
如果把上面的代码改成
boost::posix_time::ptime forceDate;
std::istringstream ss("2012-Jan-03");
if(ss >> forceDate) {
std::cout << forceDate << "\n";
}
它会产生所需的输出。
通过 documentation 的更多挖掘显示了使用 boost::posix_time::time_input_facet
控制输入格式的方法。 set_iso_extended_format
将格式设置为您要使用的数字格式。
boost::posix_time::ptime forceDate;
std::istringstream ss("2012-01-03");
auto facet = new boost::posix_time::time_input_facet();
facet->set_iso_extended_format();
ss.imbue(std::locale(ss.getloc(), facet));
if(ss >> forceDate) {
std::cout << forceDate << "\n";
}
现在回到 program_options
。看起来图书馆不直接提供区域设置支持,所以我能让上述解决方案起作用的唯一方法是搞乱全局区域设置。如果您将以下行添加到您的示例中,它的行为将如您所愿。
auto facet = new boost::posix_time::time_input_facet();
facet->set_iso_extended_format();
std::locale::global(std::locale(std::locale(), facet));