In principle, the combination of localtime()
and mktime()
will allow you to do it:
time_t now = time(0);
struct tm *tp = localtime(&now);
tp->tm_mon += 3;
time_t then = mktime(tp);
The mktime()
function will also adjust the members of tp
to be appropriate. Experiment with what happens at the ends of the month (e.g. November 30th + 3 months). There's an element of "you get what you get" (or maybe "you get what you deserve"); adding months to a date is an ill-defined operation. If your mktime()
does not do what you think you need, then you'll need to consider whether to write your own or search for one that does what you want. You should definitely have a comprehensive suite of test cases with known answers and validate that your mktime()
produces the answer you want it to produce.
For example:
#include <stdio.h>
#include <time.h>
static void check_time(time_t now, int n_months)
{
struct tm *tp = localtime(&now);
char time_buf[64];
printf("%10lu + %d months\n", (unsigned long)now, n_months);
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", tp);
printf(" %10lu = %s\n", (unsigned long)now, time_buf);
tp->tm_mon += n_months;
time_t then = mktime(tp);
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", tp);
printf(" %10lu = %s\n", (unsigned long)then, time_buf);
}
int main(void)
{
time_t times[] =
{
1322504430, // 2011-11-28 10:20:30 -08:00
1322590830, // 2011-11-29 10:20:30 -08:00
1322677230, // 2011-11-30 10:20:30 -08:00
1417198830, // 2014-11-28 10:20:30 -08:00
1417285230, // 2014-11-29 10:20:30 -08:00
1417371630, // 2014-11-30 10:20:30 -08:00
1391192430, // 2014-01-31 10:20:30 -08:00
};
enum { NUM_TIMES = sizeof(times) / sizeof(times[0]) };
for (int i = 0; i < NUM_TIMES; i++)
check_time(times[i], 3);
return 0;
}
Example output from Mac OS X 10.10:
1322504430 + 3 months
1322504430 = 2011-11-28 10:20:30
1330453230 = 2012-02-28 10:20:30
1322590830 + 3 months
1322590830 = 2011-11-29 10:20:30
1330539630 = 2012-02-29 10:20:30
1322677230 + 3 months
1322677230 = 2011-11-30 10:20:30
1330626030 = 2012-03-01 10:20:30
1417198830 + 3 months
1417198830 = 2014-11-28 10:20:30
1425147630 = 2015-02-28 10:20:30
1417285230 + 3 months
1417285230 = 2014-11-29 10:20:30
1425234030 = 2015-03-01 10:20:30
1417371630 + 3 months
1417371630 = 2014-11-30 10:20:30
1425320430 = 2015-03-02 10:20:30
1391192430 + 3 months
1391192430 = 2014-01-31 10:20:30
1398968430 = 2014-05-01 11:20:30
If you don't like 3 months after 31st January being 1st May (as well as 3 months after 1st February), then the Mac OS X 10.10 version of mktime()
is not the one for you.