我使用tm / mktime是错误的,如果没有,是否有解决方法?
我认为以下程序应该从每年的第一天输出从1970年到1970年的秒数,然后是它编译的系统上的time_t
的大小( CHAR_BIT
是一个宏,所以我认为你不能只复制编译可执行文件并假设它是正确的虽然在实践中一切都使用8位char
这些天)。
#include #include #include #include #include void do_time(int year) { time_t utc; struct tm tp; memset(&tp, 0, sizeof(tp)); tp.tm_sec = 0; tp.tm_min = 0; tp.tm_hour = 0; tp.tm_mday = 1; tp.tm_mon = 0; tp.tm_year = year - 1900; tp.tm_wday = 1; tp.tm_yday = 0; tp.tm_isdst = -1; printf("%d %ld\n",year, mktime(&tp)); } int main(){ printf("time_t is %lu bits\n",sizeof(time_t)*CHAR_BIT); for (int i = 1; i<1971; i++) do_time(i); exit(0); }
但是在OS X(10.11.3 15D21)上,这只能工作多年> = 1902,尽管time_t
是64位签名。 我可能会理解Apple的程序员是否懒惰并且在1970年之前的任何年份都没有支持,但正确的行为可以追溯到1902年然后停止看起来更像是我的错误。
咨询C标准:
clock_t
和time_t
可表示的时间范围和精度是实现定义的。 [..][N1570§7.27.1/ 4](强调我的)
更进一步,关于mktime
:
mktime
函数返回编码为time_t
类型值的指定日历时间。 如果无法表示日历时间,则函数返回值(time_t)(-1)
。[N1570§7.27.2.3/ 3]
因此,只要mktime
的返回值是(time_t)(-1)
多年来它不起作用……你就是自己的。
实际上,IMO,标准对所有这些都有点安静:
[..]
int tm_year; // years since 1900
int tm_year; // years since 1900
[…][N1570§7.27.1/ 4]
这可能意味着自1900年以来的(正)年,但为什么使用有符号整数。
作为旁注:在我的系统上(Linux 3.14.40 x86_64 glibc-2.21),我得到……
time_t is 64 bits 1 -62135600008 ... 1969 -31539600 1970 -3600
考虑到部分工作:您当然可以查看正在执行您想要的操作的libc实现并尝试使用他们的代码(如果可以使用您需要遵守的任何许可证)。 这是我的系统使用的那个。
在UNIX OS中,通常有64位启用的时间函数版本。 OS X可能有类似的东西虽然我用快速搜索找不到它。 有关更多信息,请参阅64位unix时间戳转换 。
编辑:我发现了一个Mac来测试它,不幸的是它似乎没有mktime64function。 我确实找到了这个可以作为解决方法工作的库 ,虽然我没有亲自测试过。