第一步:选择任何一个time_t
(当前时间就可以了)作为参考点;叫它t0
。
第 2 步:调用gmtime
并t0
以分解的struct tm
形式计算结果与 epoch 之间的差异。
第 3 步:调用并将第 2 步localtime
中t0
的细分差异应用于结果struct tm
。然后调用mktime
它来取回一个time_t
.
结果应该是time_t
代表时代的。
当本地时间偏移量随时间变化时,我第一次尝试实现这一点时遇到问题,例如在添加或放弃日光时间或从观察一个区域切换到另一个区域的地方。这似乎是因为struct tm
时区信息所基于的数据发生了变化。这是原始实现,但存在问题:
time_t get_epoch(time_t t0)
{
struct tm gmt = *gmtime(&t0);
struct tm tmp = *localtime(&t0);
tmp.tm_sec -= gmt.tm_sec;
tmp.tm_min -= gmt.tm_min;
tmp.tm_hour -= gmt.tm_hour;
tmp.tm_mday -= gmt.tm_mday-1;
tmp.tm_mon -= gmt.tm_mon;
tmp.tm_year -= gmt.tm_year-70;
return mktime(&tmp);
}
和一个改进的版本,其中是使用 POSIX 公式(http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15)posix_time
计算给定纪元以来秒数的函数,还有额外的工作struct tm
如果需要,处理 1970 年之前的年份等:
time_t get_epoch(time_t t0)
{
struct tm gmt = *gmtime(&t0);
struct tm tmp = *localtime(&t0);
long long offset = posix_time(&gmt);
while (offset > INT_MAX) {
offset -= INT_MAX;
tmp.tm_sec -= INT_MAX;
mktime(&tmp);
}
while (offset < -INT_MAX+61) {
offset -= -INT_MAX+61;
tmp.tm_sec -= -INT_MAX+61;
mktime(&tmp);
}
tmp.tm_sec -= offset;
return mktime(&tmp);
}
对于 C89 兼容性,long long
必须放弃,并且所需的mktime
调用数量急剧增加;offset
不能计算为单个值,但需要一个循环来mktime
每年调用多次。