How to add one day to a time obtained from time()

Andrew Stein picture Andrew Stein · Nov 21, 2008 · Viewed 39.9k times · Source

I have a time represented as the number of seconds elapsed since midnight, January 1, 1970, UTC (the results of an earlier call to time()). How do I add one day to this time?

Adding 24 * 60 * 60 works in most cases, but fails if the daylight saving time comes on or off in between. In other words, I mostly want to add 24 hours, but sometimes 23 or 25 hours.

To illustrate - the program:

#include <time.h>
#include <iostream>

int main()
{
  time_t base = 1142085600;
  for(int i = 0; i < 4; ++i) {
    time_t time = base + i * 24 * 60 * 60;
    std::cout << ctime(&time);
  }
  return 0;

}

Produces:

Sat Mar 11 08:00:00 2006
Sun Mar 12 09:00:00 2006
Mon Mar 13 09:00:00 2006
Tue Mar 14 09:00:00 2006

I want the times for March 12, 13, ... to also be 8 AM.


The answer provided by FigBug pointed me in the right direction. But I had to use localtime instead of gmtime.

int main()
{
  time_t base = 1142085600;
  for(int i = 0; i < 4; ++i) {
    struct tm* tm = localtime(&base);
    tm->tm_mday += i;
    std::cout << asctime(tm);
 }
 return 0;
}

Give me:

Sat Mar 11 08:00:00 2006
Sat Mar 12 08:00:00 2006
Sat Mar 13 08:00:00 2006
Sat Mar 14 08:00:00 2006

Which is what I want. Using gmtime gives me the times at 14:00:00

However, note that all days are Sat. Also, it goes to March 32, 33, etc. If I throw in the mktime function I am back where I started:

#include <time.h>
#include <iostream>

int main()
{
  time_t base = 1142085600;
  for(int i = 0; i < 4; ++i) {
    struct tm* tm = localtime(&base);
    tm->tm_mday += i;
    time_t time = mktime(tm);
    std::cout << asctime(tm);
 }
 return 0;
}

Gives me:

Sat Mar 11 08:00:00 2006
Sun Mar 12 09:00:00 2006
Mon Mar 13 09:00:00 2006
Tue Mar 14 09:00:00 2006

What am I missing???


OK, I have tried out FigBug's latest suggestion that is to use:

 std::cout << ctime(&time);

instead of asctime, but I get the same results. So I guess that my library and/or compiler is messed up. I am using g++ 3.4.4 on cygwin. I copied the files over to Solaris 5.8 and used g++ 3.3 there to compile. I get the correct results there! In fact I get the correct results whether I use ctime or asctime for output:

Sat Mar 11 08:00:00 2006
Sun Mar 12 08:00:00 2006
Mon Mar 13 08:00:00 2006
Tue Mar 14 08:00:00 2006

I also get the correct results (with both output functions) on Red Hut Linux with g++ 3.4.6.

So I guess that I have come across a Cygwin bug.

Thank you for all your help and advice....

Answer

Roland Rabien picture Roland Rabien · Nov 21, 2008

use gmtime() to convert the time_t to a struct tm

add one to the day (tm_mday)

use mktime() to convert the struct tm back to a time_t

see time.h for more info

Edit:

I just tried it, this works:

int main()
{
  time_t base = 1142085600;
  for(int i = 0; i < 4; ++i) {
    struct tm* tm = localtime(&base);
    tm->tm_mday += i;
    time_t next = mktime(tm);
    std::cout << ctime(&next);
 }
 return 0;
}