假设我们有一个表示日期的整数,格式为20160120.我想将此转换为epoch(1970-01-01)以来的日期,以便它对应于POSIX样式的日期。因此,例如int 20160718将成为int 17000。
我的尝试在下面,我首先将int转换为字符串,然后转换为自纪元以来的秒数,然后转换为自纪元以来的几天。这样做的一个问题是我必须将日期移动3小时才能获得正确的日期(请参阅std::to_string(d*100 + 3)
)行。我怀疑这与时区有关?我在UTC - 1.我不知道如何处理。
所以我想知道是否有一种不太复杂的方式,如果不是 - 我如何解决时区问题。
#include <iostream>
#include <chrono>
#include <time.h>
#include <iomanip>
#include <sstream>
#include <string>
typedef std::chrono::duration<int, std::ratio<60 * 60 * 24>> days_type;
typedef std::chrono::system_clock sysclock;
int convert(const unsigned d){
std::tm t = {};
std::istringstream ss(std::to_string(d*100 + 3));
ss >> std::get_time(&t, "%Y%m%d%H");
time_t t_ = mktime(&t);
/*
Now convert seconds since epoch to days since epoch via chrono...
*/
sysclock::time_point tp = sysclock::from_time_t(t_);
std::chrono::time_point<sysclock, days_type> tp_day =
std::chrono::time_point_cast<days_type>(tp);
return tp_day.time_since_epoch().count();
}
int main(){
int d = 20160718;
std::cout << d << ": " << convert(d) << std::endl; //17000
return 0;
}
答案 0 :(得分:3)
使用date library:
#include "date.h"
#include <iostream>
int convert(unsigned d) {
date::year_month_day ymd{date::year(d / 100 / 100),
date::month(d / 100 % 100), date::day(d % 100)};
return date::sys_days{ymd}.time_since_epoch().count();
}
int main() {
int d = 20160718;
std::cout << d << ": " << convert(d) << '\n'; // 17000
}
当然,convert()
API会通过更强类型来改进,例如直接返回date::sys_days
来表示时间点。
答案 1 :(得分:1)
time_t
可能不是0
。
这是一个显示不同结果的程序:
#include "date.h" // uses this library: https://github.com/HowardHinnant/date
#include <iostream>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <string>
time_t convert_local(int d)
{
std::tm t{};
auto ts{std::to_string(d)};
ts.insert(8, " ");
ts.insert(6, " ");
ts.insert(4, " "); // this is a workaround for a VS2015 bug: http://stackoverflow.com/q/21172767/1460794
std::istringstream ss(ts);
ss >> std::get_time(&t, "%Y %m %d");
if(!ss) std::cout << "parse fail.\n";
time_t t_{mktime(&t)};
return t_;
}
time_t convert_UTC(int d)
{
std::tm base_t{};
base_t.tm_mday = 1;
base_t.tm_mon = 0;
base_t.tm_year = 70;
base_t.tm_wday = 4;
auto base_tt{std::mktime(&base_t)};
std::tm t{};
auto ts{std::to_string(d)};
ts.insert(8, " ");
ts.insert(6, " ");
ts.insert(4, " "); // this is a workaround for a VS2015 bug: http://stackoverflow.com/q/21172767/1460794
std::istringstream ss(ts);
ss >> std::get_time(&t, "%Y %m %d");
if(!ss) std::cout << "parse fail.\n";
time_t t_{mktime(&t)};
return t_ - base_tt;
}
typedef std::chrono::duration<int, std::ratio<60 * 60 * 24>> days_type;
typedef std::chrono::system_clock sysclock;
int days_since_epoch(time_t t)
{
sysclock::time_point tp = sysclock::from_time_t(t);
std::chrono::time_point<sysclock, days_type> tp_day =
std::chrono::time_point_cast<days_type>(tp);
return tp_day.time_since_epoch().count();
}
int main()
{
std::tm t{};
t.tm_mday = 1;
t.tm_mon = 0;
t.tm_year = 70;
t.tm_wday = 4;
auto tt{std::mktime(&t)};
auto tp{std::chrono::system_clock::from_time_t(tt)};
time_t t0{0};
auto tp0{std::chrono::system_clock::from_time_t(t0)};
using namespace date;
std::cout << tp << " for Jan 1 1970 00:00 UTC in my timezone (-6)\n";
std::cout << std::chrono::system_clock::now() << " is the time now in my timezone (-6)\n";
std::cout << tp0 << " is what we get from time_t{0} in my timezone (-6)\n";
int d = 20160718;
std::cout << "\n\n";
std::cout << d << " converted to time_t is " << convert_local(d) << " but it considers local timezone on my system.\n";
std::cout << "Now, using this time_t, converted to days since epoch: " << days_since_epoch(convert_local(d));
std::cout << "\n\n";
std::cout << d << " converted to time_t, adjusted for local timezone is " << convert_UTC(d) << ".\n";
std::cout << "Now, using this time_t, converted to days since epoch: " << days_since_epoch(convert_UTC(d));
return 0;
}
在我的系统上它产生:
1970-01-01 06:00:00.0000000 for Jan 1 1970 00:00 UTC in my timezone (-6)
2016-11-05 14:42:19.1299886 is the time now in my timezone (-6)
1970-01-01 00:00:00.0000000 is what we get from time_t{0} in my timezone (-6)
20160718 converted to time_t is 1468821600 but it considers local timezone on my system.
Now, using this time_t, converted to days since epoch: 17000
20160718 converted to time_t, adjusted for local timezone is 1468800000.
Now, using this time_t, converted to days since epoch: 17000
在另一台服务器(live demo)上,它会产生:
1970-01-01 00:00:00.000000000 for Jan 1 1970 00:00 UTC in my timezone
2016-11-05 14:37:15.661541264 is the time now in my timezone
1970-01-01 00:00:00.000000000 is what we get from time_t{0} in my timezone
20160718 converted to time_t is 1468800000 but it considers local timezone on my system.
Now, using this time_t, converted to days since epoch: 17000
20160718 converted to time_t, adjusted for local timezone is 1468800000.
Now, using this time_t, converted to days since epoch: 17000
最后,最好是明确地(通过指定日期,月份和年份)获得两个时间点。
通过这种方式,您可以使用system_clock
,这无关紧要,因为我们只想查看以天为单位的持续时间:
#include <iostream>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <string>
#include <sstream>
auto get_epoch_tp()
{
std::tm base_t{};
base_t.tm_mday = 1;
base_t.tm_mon = 0;
base_t.tm_year = 70;
base_t.tm_wday = 4;
auto base_tt{std::mktime(&base_t)};
auto tp{std::chrono::system_clock::from_time_t(base_tt)};
return tp;
}
int get_days_since_epoch(int d)
{
std::tm t{};
auto ts{std::to_string(d)};
ts.insert(8, " ");
ts.insert(6, " ");
ts.insert(4, " "); // this is a workaround for a VS2015 bug: http://stackoverflow.com/q/21172767/1460794
std::istringstream ss(ts);
ss >> std::get_time(&t, "%Y %m %d");
if(!ss) std::cout << "parse fail.\n";
time_t tt{mktime(&t)};
auto tp{std::chrono::system_clock::from_time_t(tt)};
using days_type = std::chrono::duration<int, std::ratio<60 * 60 * 24>>;
auto duration{tp - get_epoch_tp()};
auto days{std::chrono::duration_cast<days_type>(duration)};
return days.count();
}
int main()
{
int d = 20160718;
std::cout << d << ": " << get_days_since_epoch(d) << std::endl; //17000
}
答案 2 :(得分:0)
转换为时间后你可以做简单的数学运算。
OneToOneField