Getting local and greenwich time
In the following code, I try to get the local time and greenwich time and find the difference between them. But the output shows both the time values are equal:
diff=0 iTm1=16:34 iTm2=16:34 <-----[gmtime is 13:34 actualy]
When I just retreive gmtime, it works correctly. But when I retreive both local and gmtime, gmtime becomes equal to localtime.
#include <stdio.h>
#include <time.h>
int main()
{
time_t iTime;
struct tm * iTm1;
struct tm * iTm2;
int iTimeDifferenc开发者_StackOverflow中文版eInMinutes;
time(&iTime);
iTm1=gmtime(&iTime);
iTm2=localtime(&iTime);
iTimeDifferenceInMinutes=(int)((iTm2->tm_hour - iTm1->tm_hour)) * 60;
printf("diff=%d iTm1=%d:%d iTm2=%d:%d\n", iTimeDifferenceInMinutes,
iTm1->tm_hour, iTm1->tm_min,
iTm2->tm_hour, iTm2->tm_min);
}
I have a mistake but I couldn't find it... May someone show me my fault please..?
The gmtime
and localtime
functions each return a pointer to a fixed buffer. It seems that on your implementation, they use the same buffer, so the call to gmtime
fills that buffer, and then the call to localtime
fills that buffer with different data.
If you have gmtime_r
and localtime_r
, use them. (You may need to include the line #define _POSIX_SOURCE
or something similar before #include <time.h>
) You'll need to allocate memory for the two struct tm
objects.
struct tm local_tm, gm_tm;
time(&iTime);
gmtime_r(&iTime, &gm_tm);
localtime_r(&iTime, &local_tm);
Older systems don't have the _r
versions (they were added because the plain versions can't easily be used in a multithreaded program). Then you have to copy the data before the next call to either of the two functions.
struct tm local_tm, gm_tm;
time(&iTime);
memcpy(&gm_tm, gmtime(&iTime), sizeof(gm_tm));
memcpy(&local_tm, localtime(&iTime), sizeof(local_tm));
Your mistake in using pointers to struct tm
without actually having a variable holding the memory. Here is a repaired version:
#include <stdio.h>
#include <time.h>
int main()
{
time_t iTime;
struct tm iTm1;
struct tm iTm2;
int iTimeDifferenceInMinutes;
time(&iTime);
iTm1=*gmtime(&iTime);
iTm2=*localtime(&iTime);
iDiff=(int)((iTm2.tm_hour - iTm1.tm_hour)) * 60;
printf("diff=%d iTm1=%d:%d iTm2=%d:%d\n", iDiff,
iTm1.tm_hour, iTm1.tm_min,
iTm2.tm_hour, iTm2.tm_min);
}
Both localtime and gmtime use static memory in the clib for their processing. So when you use one, it overwrites the previous call.
You need to call gmtime, then pull the variables you want out and store it in a separate location. Then call localtime, and do your comparison.
OR, you can use the reentrant versions of these calls (localtime_r, gmtime_r) which you have to supply your own memory, but there won't be any overwriting of data.
I recommend getting used to using the reentrant versions of these calls, then bugs like this won't show their ugly head!
Quote from the Linux man page:
The gmtime() function [...snip...] The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions. The gmtime_r() function does the same, but stores the data in a user-supplied struct.
The localtime() function [...snip...] The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions. The localtime_r() function does the same, but stores the data in a user-supplied struct. It need not set tzname.
Thank you all! I understand my problem.I think it would be better if I do not use _r versions of the time functions because I the program will work on an embedded device(several platforms) and I don't know if the toolchains's support for reentrant functions are enough.
Thanks again.
精彩评论