C++ 时间函数gmtime、gmtime_r、localtime、localtime_r

测试环境:vmware 7 + Redhat5.5,系统时间使用UTC,时区为上海。

1、函数功能介绍

使用man gmtimeman 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、总结

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

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
static __time64_t __cdecl _make__time64_t ( struct tm *tb, int ultflag ) { __time64_t tmptm1, tmptm2, tmptm3; struct tm tbtemp; long dstbias = 0; long timezone = 0; _VALIDATE_RETURN( ( tb != NULL ), EINVAL, ( ( __time64_t )( -1 ) ) ) /* * First, make sure tm_year is reasonably close to being in range. */ if ( ((tmptm1 = tb->tm_year) < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR64 + 1) ) goto err_mktime; /* * Adjust month value so it is in the range 0 - 11. This is because * we don't know how many days are in months 12, 13, 14, etc. */ if ( (tb->tm_mon < 0) || (tb->tm_mon > 11) ) { tmptm1 += (tb->tm_mon / 12); if ( (tb->tm_mon %= 12) < 0 ) { tb->tm_mon += 12; tmptm1--; } /* * Make sure year count is still in range. */ if ( (tmptm1 < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR64 + 1) ) goto err_mktime; } /***** HERE: tmptm1 holds number of elapsed years *****/ /* * Calculate days elapsed minus one, in the given year, to the given * month. Check for leap year and adjust if necessary. */ tmptm2 = _days[tb->tm_mon]; if ( _IS_LEAP_YEAR(tmptm1) && (tb->tm_mon > 1) ) tmptm2++; /* * Calculate elapsed days since base date (midnight, 1/1/70, UTC) * * * 365 days for each elapsed year since 1970, plus one more day for * each elapsed leap year. no danger of overflow because of the range * check (above) on tmptm1. */ tmptm3 = (tmptm1 - _BASE_YEAR) * 365 + _ELAPSED_LEAP_YEARS(tmptm1); /* * elapsed days to current month (still no possible overflow) */ tmptm3 += tmptm2; /* * elapsed days to current date. */ tmptm1 = tmptm3 + (tmptm2 = (__time64_t)(tb->tm_mday)); /***** HERE: tmptm1 holds number of elapsed days *****/ /* * Calculate elapsed hours since base date */ tmptm2 = tmptm1 * 24; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_hour); /***** HERE: tmptm1 holds number of elapsed hours *****/ /* * Calculate elapsed minutes since base date */ tmptm2 = tmptm1 * 60; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_min); /***** HERE: tmptm1 holds number of elapsed minutes *****/ /* * Calculate elapsed seconds since base date */ tmptm2 = tmptm1 * 60; tmptm1 = tmptm2 + (tmptm3 = (__time64_t)tb->tm_sec); /***** HERE: tmptm1 holds number of elapsed seconds *****/ if ( ultflag ) { /* * Adjust for timezone. No need to check for overflow since * localtime() will check its arg value */ __tzset(); _ERRCHECK(_get_dstbias(&dstbias;)); _ERRCHECK(_get_timezone(&timezone;)); tmptm1 += timezone; /* * Convert this second count back into a time block structure. * If localtime returns NULL, return an error. */ if ( _localtime64_s(&tbtemp;, &tmptm1;) != 0 ) goto err_mktime; /* * Now must compensate for DST. The ANSI rules are to use the * passed-in tm_isdst flag if it is non-negative. Otherwise, * compute if DST applies. Recall that tbtemp has the time without * DST compensation, but has set tm_isdst correctly. */ if ( (tb->tm_isdst > 0) || ((tb->tm_isdst < 0) && (tbtemp.tm_isdst > 0)) ) { tmptm1 += dstbias; if ( _localtime64_s(&tbtemp;, &tmptm1;) != 0 ) goto err_mktime; } } else { if ( _gmtime64_s(&tbtemp;, &tmptm1;) != 0) goto err_mktime; } /***** HERE: tmptm1 holds number of elapsed seconds, adjusted *****/ /***** for local time if requested *****/ *tb = tbtemp; return tmptm1; err_mktime: /* * All errors come to here */ errno = EINVAL; return (__time64_t)(-1); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值