我该怎么办?有mktime函数,但是将输入视为以本地时间表示,但如果我的输入tm变量恰好是UTC,我该如何执行转换.
使用timegm()而不是mktime()
对于Windows上的用户,可以使用以下功能:
_mkgmtime
链接获取更多信息:https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/mkgmtime-mkgmtime32-mkgmtime64
这是我使用的解决方案(不记得我发现它的位置)当它不是Windows平台时
time_t _mkgmtime(const struct tm *tm) { // Month-to-day offset for non-leap-years. static const int month_day[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // Most of the calculation is easy; leap years are the main difficulty. int month = tm->tm_mon % 12; int year = tm->tm_year + tm->tm_mon / 12; if (month < 0) { // Negative values % 12 are still negative. month += 12; --year; } // This is the number of Februaries since 1900. const int year_for_leap = (month > 1) ? year + 1 : year; time_t rt = tm->tm_sec // Seconds + 60 * (tm->tm_min // Minute = 60 seconds + 60 * (tm->tm_hour // Hour = 60 minutes + 24 * (month_day[month] + tm->tm_mday - 1 // Day = 24 hours + 365 * (year - 70) // Year = 365 days + (year_for_leap - 69) / 4 // Every 4 years is leap... - (year_for_leap - 1) / 100 // Except centuries... + (year_for_leap + 299) / 400))); // Except 400s. return rt < 0 ? -1 : rt; }
以下实现timegm(1)
在Android上运行,也可能适用于其他Unix变体:
time_t timegm( struct tm *tm ) { time_t t = mktime( tm ); return t + localtime( &t )->tm_gmtoff; }
timegm()
可以工作,但并不存在于所有系统上.
这是一个只使用ANSI C的版本.(编辑:不是严格的ANSI C!我在time_t上做数学,假设单位是自纪元以来的秒数.AFAIK,标准没有定义time_t的单位.)注意,它利用黑客,可以说,确定机器的时区,然后相应地调整mktime的结果.
/*
returns the utc timezone offset
(e.g. -8 hours for PST)
*/
int get_utc_offset() {
time_t zero = 24*60*60L;
struct tm * timeptr;
int gmtime_hours;
/* get the local time for Jan 2, 1900 00:00 UTC */
timeptr = localtime( &zero );
gmtime_hours = timeptr->tm_hour;
/* if the local time is the "day before" the UTC, subtract 24 hours
from the hours to get the UTC offset */
if( timeptr->tm_mday < 2 )
gmtime_hours -= 24;
return gmtime_hours;
}
/*
the utc analogue of mktime,
(much like timegm on some systems)
*/
time_t tm_to_time_t_utc( struct tm * timeptr ) {
/* gets the epoch time relative to the local time zone,
and then adds the appropriate number of seconds to make it UTC */
return mktime( timeptr ) + get_utc_offset() * 3600;
}
Loki Astari的答案是一个良好的开端,timegm
是可能的解决方案之一.但是,手册timegm
版本提供了它,因为timegm
它不符合POSIX标准.这里是:
#include#include time_t my_timegm(struct tm *tm) { time_t ret; char *tz; tz = getenv("TZ"); if (tz) tz = strdup(tz); setenv("TZ", "", 1); tzset(); ret = mktime(tm); if (tz) { setenv("TZ", tz, 1); free(tz); } else unsetenv("TZ"); tzset(); return ret; }