I have a lot of respect for what Howard has put together, but I needed something that would execute as fast as possible and worried about including the entire date library when all I needed was an int
to date
.
Here is what I came up with:
string GetDateFromDaysSincePointInTime(int days)
{
int a, b, c, d, e, m, dd, mm, yyyy;
a = days + 2374475;
b = (4 * a + 3) / 146097;
c = -b * 146097 / 4 + a;
d = (4 * c + 3) / 1461;
e = -1461 * d / 4 + c;
m = (5 * e + 2) / 153;
dd = -(153 * m + 2) / 5 + e + 1;
mm = -m / 10 * 12 + m + 3;
yyyy = b * 100 + d - 4800 + m / 10;
return to_string(yyyy) + "-" + to_string(mm) + '-' + to_string(dd);
}
To use this, simply call it with an int GetDateFromDaysSincePointInTime(113908)
. That will give you a date. Assuming my starting point is different from your starting point, go to the site https://www.timeanddate.com/date/dateadd.html and add/subtract your desired date from the date that was output. Then alter the int value on variable a
by that amount and run again to get your corrected date.
From there, it should be able to be easily altered to have leading zeros if desired:
std::ostringstream month;
month << std::setw(2) << std::setfill('0') << mm;
std::ostringstream day;
day << std::setw(2) << std::setfill('0') << dd;
return to_string(yyyy) + "-" + month.str() + '-' + day.str()
Alternate way
Here is another way that is more readable, and there doesn't seem to be any real performance hit on 30,000 records:
string GetDateFromInt(int days)
{
int startYear = 1600;
int year = days / 365.2421875;
float peryear = 365.2421875;
int remainder = fmod(days, peryear); // here you could add what day of the year to get a date in the middle of the year
bool leapyear= ((year & 3) == 0 && (year % 100 != 0));
int leapYearIndex = leapyear ? 1 : 0;
int daysInYear = leapYearIndex ? 366 : 365;
const unsigned short int __mon_yday[2][13] =
{
/* Normal years. */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
/* Leap years. */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
int dayOfYear = remainder;
if (dayOfYear >= 1 && dayOfYear <= daysInYear) {
for (int mon = 0; mon < 12; mon++) {
if (dayOfYear <= __mon_yday[leapYearIndex][mon + 1]) {
int month = mon + 1;
int dayOfMonth = dayOfYear - __mon_yday[leapYearIndex][mon];
std::ostringstream months;
months << std::setw(2) << std::setfill('0') << month;
std::ostringstream day;
day << std::setw(2) << std::setfill('0') << dayOfMonth;
return to_string(startYear + year) + "-" + months.str() + '-' + day.str();
}
}
}
}