time_t
may not be 0
at the start of the POSIX epoch on your system.
Here is a program that shows the different results:
#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;
}
On my system it produces:
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
On another server (live demo) it produces:
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
In the end, it would probably be best to get the two time points you would like to work with explicitly (by specifying the day, month and year) for each.
This way you could use system_clock
and it would not matter because we're only looking to calculate a duration in days:
#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
}
demo