嵌入式 秒数转换为时间格式Locatime以及gmtime不可以重入

/*localtime 不可以重入*/

#include <stdlib.h>

#include <sttring.h>

#include <time.h>  
#include <stdio.h>  
  
  
int main(int argc, char *argv[])  
{  
    time_t tNow =time(NULL);  
    time_t tEnd = tNow + 1800;  
    //注意下面两行的区别  
    struct tm* ptm = localtime(&tNow);  
    struct tm* ptmEnd = localtime(&tEnd);  
  
    char szTmp[50] = {0};  
    strftime(szTmp,50,"%H:%M:%S",ptm);  
    char szEnd[50] = {0};  
    strftime(szEnd,50,"%H:%M:%S",ptmEnd);  
      
  
    printf("%s /n",szTmp);  
    printf("%s /n",szEnd);  
      
  
    system("PAUSE");  
    return EXIT_SUCCESS;  

}  


最后出来的结果是:

21:18:39

21:18:39

/*可重入函数*/

#include <stdlib.h>  
#include <string.h>  
#include <time.h>  
#include <stdio.h>  
 
int main(int argc, char *argv[])  
{  
    time_t tNow =time(NULL);  
    time_t tEnd = tNow + 1800;  
  
    //在这里修改程序  
    //struct tm* ptm = localtime(&tNow);  
    //struct tm* ptmEnd = localtime(&tEnd);  
    struct tm ptm = { 0 };  
    struct tm ptmEnd = { 0 };  
    localtime_r(&tNow, &ptm);  
    localtime_r(&tEnd, &ptmEnd);  

      
    char szTmp[50] = {0};  
    strftime(szTmp,50,"%H:%M:%S",&ptm);  
    char szEnd[50] = {0};  
    strftime(szEnd,50,"%H:%M:%S",&ptmEnd);  
    printf("%s /n",szTmp);  
    printf("%s /n",szEnd);  
      
  
    system("PAUSE");  
    return EXIT_SUCCESS;  
}  


此外:

跨平台的线程安全的localtime和gmtime


localtime()返回一个内部静态变量指针,是线程不安全的。
localtime_r()是线程安全的版本,可是Windows上没有。

boost::date_time::c_time为localtime和gmtime这些ctime函数提供了一个统一的版本.
定义为c_time中的2个静态成员函数。

头文件:c_time.hpp
命名空间:boost::date_time

struct c_time {
    static tm* localtime(const time_t* t, tm* result);
    static tm* gmtime(const time_t* t, tm* result);
}


 1、函数功能介绍

        使用man gmtime或man localtime都可以的得到这几个函数的介绍。原型如下:

        struct tm *gmtime(const time_t *timep);

        struct tm *gmtime_r(const time_t *timep, struct tm *result);

        struct tm *localtime(const time_t *timep);

        struct tm *localtime_r(const time_t *timep, struct tm *result);

man手册中对它们的解释如下:

        The gmtime() function converts the calendar time timep to broken-down time representation, expressed in Coordinated Universal Time (UTC). It may return NULL when the year does not fit into an integer. 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 converts the calendar time timep to broken-time representation, expressed relative to the user's specified time zone. The function acts as if it called tzset(3) and sets the external variables tzname with information about the current time zone, timezone with  the difference between Coordinated Universal Time (UTC) and local standard time in seconds, and daylight to a non-zero value if daylight savings time rules apply during some part of the year.  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。

翻译如下:

        gmtime() 函数将日历时间timep转换为用UTC时间表示的时间。它可能返回NULL,比如年份不能放到一个整数中。返回值指向一个静态分配的结构,该结构可能会被接下来的任何日期和时间函数调用覆盖。gmtime_r()函数功能与此相同,但是它可以将数据存储到用户提供的结构体中。

        localtime() 函数将日历时间timep转换为用户指定的时区的时间。这个函数的行为好像是它调用了tzset(3) 并且将外部变量tzname设置为当前时区的信息,将timezone设为UTC和本地标准时间的差值,并且,如果在一年的部分时间使用日光节约规则时将daylight设置为非空值。返回值指向一个静态分配的结构,该结构可能会被接下来的任何日期和时间函数调用覆盖。localtime_r()函数功能与此相同,但是它可以将数据存储到用户提供的结构体中。它不需要设置tzname。

 

2、功能测试

程序一:

#include <stdio.h>

#include <time.h>

int main()

{

time_t cur_time=time(NULL);

if( cur_time < 0 )

{

perror("time");

return -1;

}

 

struct tm utc_tm;;

if( NULL == gmtime_r( &cur_time, &utc_tm ) )

{

perror("gmtime" );

return -1;

}

 

struct tm local_tm;

if( NULL == localtime_r( &cur_time, &local_tm ) )

{

perror("localtime" );

return -1;

}

 

printf("UTC = %s", asctime(&utc_tm) );

printf("LOC = %s", asctime(&local_tm) );

printf("LOC = %s", ctime(&cur_time) );

return 0;

}

程序输出:

UTC = Thu Oct 27 09:16:10 2011

LOC = Thu Oct 27 17:16:10 2011

LOC = Thu Oct 27 17:16:10 2011

由于系统时间使用了UTC,可以看到“本地时间= UTC时间 + 8”,输出正确。

 

程序二:

#include <stdio.h>

#include <time.h>

int main()

{

time_t cur_time=time(NULL);

if( cur_time < 0 )

{

perror("time");

return -1;

}

 

struct tm *utc_tm = gmtime( &cur_time );

if( NULL == utc_tm )

{

perror("gmtime" );

return -1;

}

 

printf("UTC = %s", asctime(utc_tm) );

 

struct tm *local_tm = localtime( &cur_time );

if( NULL == local_tm )

{

perror("localtime" );

return -1;

}

 

printf("LOC = %s", asctime(local_tm) );

printf("LOC = %s", ctime(&cur_time) );

return 0;

}

程序输出:

UTC = Thu Oct 27 09:20:45 2011

LOC = Thu Oct 27 17:20:45 2011

LOC = Thu Oct 27 17:20:45 2011

同样是正确的。

 

程序三:

#include <stdio.h>

#include <time.h>

int main()

{

time_t cur_time=time(NULL);

if( cur_time < 0 )

{

perror("time");

return -1;

}

 

struct tm *utc_tm = gmtime( &cur_time );

if( NULL == utc_tm )

{

perror("gmtime" );

return -1;

}

 

struct tm *local_tm = localtime( &cur_time );

if( NULL == local_tm )

{

perror("localtime" );

return -1;

}

 

printf("UTC = %s", asctime(utc_tm) );

printf("LOC = %s", asctime(local_tm) );

printf("LOC = %s", ctime(&cur_time) );

return 0;

}

程序输出:

UTC = Thu Oct 27 17:21:59 2011

LOC = Thu Oct 27 17:21:59 2011

LOC = Thu Oct 27 17:21:59 2011

这程序输出有错,UTC时间和本地时间相同了,这应该就是由于man文档中描述的“可能会被接下来的任何日期和时间函数调用覆盖”造成的。为验证这个设想,使用程序四:

 

程序四:

#include <stdio.h>

#include <time.h>

int main()

{

time_t cur_time=time(NULL);

if( cur_time < 0 )

{

perror("time");

return -1;

}

 

struct tm *local_tm = localtime( &cur_time );

if( NULL == local_tm )

{

perror("localtime" );

return -1;

}

 

struct tm *utc_tm = gmtime( &cur_time );

if( NULL == utc_tm )

{

perror("gmtime" );

return -1;

}

 

printf("UTC = %s", asctime(utc_tm) );

printf("LOC = %s", asctime(local_tm) );

printf("LOC = %s", ctime(&cur_time) );

return 0;

}

程序输出:

UTC = Thu Oct 27 09:24:23 2011

LOC = Thu Oct 27 09:24:23 2011

LOC = Thu Oct 27 17:24:23 2011

验证了该设想。

 

3、总结

        使用gmtime和localtime后要立即处理结果,否则返回的指针指向的内容可能会被覆盖,一个好的方法是使用gmtime_r和localtime_r,由于使用了用户分配的内存,这两个函数是不会出错的


你可能感兴趣的:(嵌入式 秒数转换为时间格式Locatime以及gmtime不可以重入)