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....
int m2[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int i,k=0; for(i=0;i<m;i++) k=k+m2[i]; k=k+d+ne; From the above source code k is the total number of days on the given date.
typedef . . . time_t. The time_t type is an arithmetic type that represents a date and time. The actual type and the encoding of the date and time are implementation-defined.
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;
}
FigBug's solution will work almost every time, but it needs DST fix: tm->tm_isdst = -1
A positive or 0 value for tm_isdst causes mktime() to presume initially that Daylight Savings Time, respectively, is or is not in effect for the specified time. A negative value for tm_isdst causes mktime() to attempt to determine whether Daylight Saving Time is in effect for the specified time.
(quoted from mktime spec)
int main()
{
time_t base = 1142085600;
for(int i = 0; i < 4; ++i) {
struct tm* tm = localtime(&base);
tm->tm_mday += i;
tm->tm_isdst = -1; // don't know if DST is in effect, please determine
// this for me
time_t next = mktime(tm);
std::cout << ctime(&next);
}
return 0;
}
Otherwise there will be a bug (example for Moscow Daylight Saving Time which starts 29 March 2009 01:59:59):
int main()
{
// 28 March 2009 05:00:00 GMT ( local - 08:00 (MSK) )
time_t base = 1238216400;
std::time_t start_date_t = base;
std::time_t end_date_t = base;
std::tm start_date = *std::localtime(&start_date_t);
std::tm end_date = *std::localtime(&end_date_t);
end_date.tm_mday += 1;
// end_date.tm_isdst = -1;
std::time_t b = mktime(&start_date);
std::time_t e = mktime(&end_date);
std::string start_date_str(ctime(&b));
std::string stop_date_str(ctime(&e));
cout << " begin (MSK) (DST is not active): " << start_date_str;
cout << " end (MSD) (DST is active): " << stop_date_str;
}
Output:
begin (MSK) (DST is not active): Sat Mar 28 08:00:00 2009
end (MSD) (DST is active): Sun Mar 29 09:00:00 2009
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With