Slug Pue Slug Pue - 28 days ago 10
C++ Question

C++: Converting a date in form 20160120 to days since epoch

Assume we have an integer representing a date, in the form 20160120. I would like to convert this to days since epoch (1970-01-01) so that it corresponds to a POSIX-style date. So for example int 20160718 would become int 17000.

My attempt is below, where I first convert the int to a string, then to seconds since epoch, then to days since epoch. One problem with this is that I have to shift the date by 3 hours in order to get the correct date (see the

std::to_string(d*100 + 3)
) line. I suspect this has something to do with timezones? I am in UTC - 1. I am not sure how to deal with that.

So I wonder if there is a less complicated way of doing it, and if not– how I could fix the timezone issue.

#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;
}

Answer

Using a 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
}

See it run

Of course the convert() API would be improved by being more strongly typed, for example by directly returning a date::sys_days to represent the time point.

Comments