Assuming you've already parsed the date into its component day, month, and year. We can "add days" with a very simple algorithm. And we can even subtract days (or add negative days).
Nothing below uses any of the standard libraries for managing date and time. Nothing against those solutions or the standard libraries. But I wanted to present a simple portable way with the Gregorian calendar that also takes leap years into account.
First a struct to indicate a Date:
struct Date
{
int day;
int month;
int year;
};
Then we need a little helper for leap years.
bool isLeapYear(int year)
{
// leap years happen on 4 year boundaries unless year is divisible by 100 and not 400
// 2000 was a leap year, but 2100 is not
if (year % 400 == 0) return true;
if (year % 100 == 0) return false;
return (year % 4 == 0);
}
And with this data structure for a Date and a leap year detection function, we can build a very simple solution. The basic algorithm is to increment a given date "one day at a time" until the number of added days has been achieved. Each time we increment the day member past the number of days in a month, it gets reset to 1 and the month member gets incremented. And similarly, we handle incrementing to the next year. And then adjust for leap years as well.
// adds "numberOfDays" to the date object pointed to by "d"
void AddDays(Date* d, int numberOfDays)
{
static const int daysInMonths[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static const int daysInMonthsLeap[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int* monthTable = isLeapYear(d->year) ? daysInMonthsLeap : daysInMonths;
// handle the case where we are adding a positive number of days to "d"
while (numberOfDays > 0)
{
d->day++;
if (d->day > monthTable[d->month])
{
d->month++;
if (d->month > 12)
{
d->month = 1;
d->year++;
monthTable = isLeapYear(d->year) ? daysInMonthsLeap : daysInMonths;
}
d->day = 1;
}
numberOfDays--;
}
// handle the case where we are adding a negative number of days to "d".
while (numberOfDays < 0)
{
d->day--;
if (d->day <= 0)
{
d->month--;
if (d->month <= 0)
{
d->year--;
d->month = 12;
monthTable = isLeapYear(d->year) ? daysInMonthsLeap : daysInMonths;
}
d->day = monthTable[d->month];
}
numberOfDays++;
}
}
The above isn't the most efficient - especially if you are adding millions of days onto a given Date object. But for dealing with time adjustments in terms of a small number of days, weeks, or even less than a couple thousand years, you could do a lot worse. A quick benchmark in an optimized build shows that the above works reasonably fast for adding 5 million days to today's date to get to the year 16000 and later.
There's also plenty of opportunities for optimizations in the loops above.