我想转换输入日期字符串(输入中没有提供时间),例如' 2017-05-04'进入unix时间戳,时间为" 00:00:01"和时区是太平洋时间(' America / Los_Angeles)。
我不太确定如何做到这一点 - 我探讨了使用boost::posix_time::time_from_string
,但似乎并没有处理时区。
任何建议都将受到高度赞赏!
答案 0 :(得分:3)
使用Howard Hinnant's free, open source, C++11/14/17 timezone library,您可以使用以下语法执行此操作:
#include "tz.h"
#include <cassert>
#include <iostream>
#include <sstream>
#include <string>
date::sys_seconds
my_parse(const std::string& in)
{
using namespace std;
using namespace std::chrono;
using namespace date;
local_seconds ls;
istringstream infile{in};
infile >> parse("%F", ls);
assert(!infile.fail());
return make_zoned("America/Los_Angeles", ls + seconds{1}).get_sys_time();
}
int
main()
{
std::cout << my_parse("2017-05-04").time_since_epoch().count() << '\n';
}
该程序输出:
1493881201
使用http://www.convert-unix-time.com/?t=1493881201等网站,您可以确认1493881201对应于2017年5月4日星期四07:00:01 UTC,即2017年5月4日星期四00:00:01太平洋时间。
答案 1 :(得分:1)
使用boost,解析posix :: date_time(或gregorian :: date)并在构建local_date_time
对象时添加时间和时区。
这是一个演示 - 甚至没有使用输入方面,因为在所有诚实的解析中它手动似乎更简单:
<强> Live On Coliru 强>
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
struct MyTime {
static boost::local_time::time_zone_ptr time_zone() {
using namespace boost::local_time;
static auto zone = [] { // one-time initialization
tz_database db;
//libs/date_time/data/date_time_zonespec.csv is included with boost
std::istringstream fake_db(R"("America/Los_Angeles","PST","Pacific Standard Time","PDT","Pacific Daylight Time","-08:00:00","+01:00:00","2;0;3","+02:00:00","1;0;11","+02:00:00")");
db.load_from_stream(fake_db);
return db.time_zone_from_region("America/Los_Angeles");
}();
return zone;
}
boost::local_time::local_date_time _value { boost::date_time::not_a_date_time, time_zone() };
friend std::istream& operator>>(std::istream& is, MyTime& parsed) {
unsigned short y, m, d;
char delim;
if (is
>> std::noskipws // optionally of course
&& is >> y && (is >> delim && delim == '-')
&& is >> m && (is >> delim && delim == '-')
&& is >> d)
{
using namespace boost::local_time;
local_date_time ldt({y, m, d}, {0,0,1}, time_zone(), true);
parsed._value = ldt;
return is;
}
is.setstate(is.rdstate() | std::ios::failbit);
return is;
}
friend std::ostream& operator<<(std::ostream& os, MyTime const& v) {
return os << v._value;
}
};
int main()
{
{
MyTime dt;
std::cout << "Not parsed yet: " << dt << "\n";
dt = boost::lexical_cast<MyTime>("2017-05-04");
std::cout << "Parsed: " << dt << " (base utc offset: " << dt._value.zone()->base_utc_offset() << ")\n";
}
// errors
for (auto err : { "2017-15-04", "3", "", "17-1-77", "2017/05/04", "2017-05-04 x" }) try {
MyTime dt;
dt = boost::lexical_cast<MyTime>(err);
std::cout << "Should not have parsed: " << dt << "\n";
} catch(std::exception const& e) {
std::cerr << "'" << err << "': " << e.what() << "\n";
}
}
打印哪些:
Not parsed yet: not-a-date-time
Parsed: 2017-May-04 00:00:01 PDT (base utc offset: -08:00:00)
'2017-15-04': Month number is out of range 1..12
'3': bad lexical cast: source type value could not be interpreted as target
'': bad lexical cast: source type value could not be interpreted as target
'17-1-77': Year is out of valid range: 1400..10000
'2017/05/04': bad lexical cast: source type value could not be interpreted as target
'2017-05-04 x': bad lexical cast: source type value could not be interpreted as target
要使用完整的时区数据库,请更改timezone()
以执行类似
static auto zone = [] { // one-time initialization
tz_database db;
db.load_from_file("/home/sehe/custom/boost_1_62_0/libs/date_time/data/date_time_zonespec.csv");
return db.time_zone_from_region("America/Los_Angeles");
}();
指向安装boost库的位置,或者部署该数据库副本的位置
答案 2 :(得分:0)
我也更喜欢不使用自定义库,但是Howard Hinnant的库要好于boost / date_time,后者取决于用户提供的“ .csv”文件。 HH的库直接从本地时区存储库收集信息,该信息经常由系统更新,不需要您进行维护。 HH也是对std ++的提议,我不知道为什么尚未实现。