I am using HowardHinnant date library in my project. I want to get the exact datetime before n months.
For Example : "2016-12-17 18:21:26" is current datetime and, i want to know the datetime of 13 months before. It should output "2015-11-17 18:21:26".
/*
* This function will return the current date in year_month_day format
*/
auto currentDate() {
auto currentTime = std::chrono::system_clock::now();
date::year_month_day currentDate = date::floor<date::days>(currentTime);
return currentDate;
}
/*
* This function will find the date before (n) months
*/
template <typename T>
auto oldDate(T monthsNum) {
auto currentDate = currentDate();
auto yearCurrentDate = (int)currentDate.year();
auto monthCurrentDate = currentDate.month();
auto dayCurrentDate = currentDate.day();
auto yearNum = monthsNum/12;
auto yearEndDate = yearCurrentDate - yearNum;
auto monthNum = monthsNum%12;
auto monthEndDate = monthCurrentDate;
while(monthNum) {
monthEndDate--;
}
if(monthEndDate > monthCurrentDate) {
yearEndDate--;
}
date::year_month_day endDate = date::year{yearEndDate}/monthEndDate;
return endDate;
}
My function oldDate() will return the date which was n months before. But i am not able to get the time.
Instead of
currentDate(), create acurrentTimewhich returns asys_seconds(time with seconds precision):Now
oldDatecan callcurrentTimeinstead ofcurrentDateand in that way know and preserve the time-of-day.oldDateshould take as a parameterdate::monthswhich is astd::chrono::durationwith a precision of months. Here's what it could look like (description afterward):The
using namespace dateis handy otherwise you're going to havedate::just all over the place.First get the time from
currentTime(). This is astd::chrono::time_point<system_clock, seconds>, or a count of seconds since 1970-01-01 UTC.Then truncate this count of seconds into a count of days with
floor<days>(). This is astd::chrono::time_point<system_clock, days>.One can think of
sdas a time point to the first instant of the day (in UTC). So if you subtractsdfromtimeyou get astd::chrono::durationrepresenting the time-of-day. The precision is going to be thecommon_typeof the two precisions you're subtracting (seconds).To do the month arithmetic, you need to switch the type of
sdfromsys_days(atime_point) toyear_month_day(a calendar type). Once you have typeyear_month_day, you can just subtract themonthsNumfrom it, yielding anotheryear_month_day(stored inymdabove).You can check if this resulted in a valid date or not with
.ok(). If it is an invalid date, that means you overflowed the days field of theyear_month_day. I see in the comments that if this happens, you want the last day of the month. So just extract theyearandmonthand uselastto resetymdto the last day of the month for that year.Finally convert the
ymdback into asys_days(time_pointwithdaysprecision) and add thetime_of_dayback to it.The result is
sys_seconds(time_pointwithsecondsprecision).I just ran this with this driver:
And the output was:
Convenience link to documentation.