我想在微控制器上使用mktime
(或者至少使用32位宽的时间戳)。我从avr libc source files添加了所需的文件(在Atmel Studio 7中,时间函数不可用),没有更改算法。但是对于2016. 06. 08. 23:34:00(UTC + 1,EU dst),mktime
返回518736960
,但它应该返回1465425240
。
set_zone(ONE_HOUR);
set_dst(eu_dst);
struct tm myTime;
myTime.tm_sec = 0;
myTime.tm_min = 36;
myTime.tm_hour = 23;
myTime.tm_mday = 8;
myTime.tm_mon = 5;
myTime.tm_year = 116;
myTime.tm_isdst = ONE_HOUR;
time_t tim = mktime(&myTime);
我做错了什么?这些功能应该可以正常工作。
答案 0 :(得分:6)
518736960对应 Unix纪元时间 1986年6月9日21:36:00;它看起来好像这个实现使用了一个不同的时代,从2000年1月1日开始,而不是从1970年1月1日开始。
时差可归因于TZ和DST偏移。一个接一个的日期差异可归因于2000年不是闰年,而是1970年。
修改强>
文件here明确指出,纪元开始是2000年:
虽然未在标准中指定,但通常预期time_t是一个有符号整数,表示从1970年1月1日午夜起的偏移量(以秒为单位),即' Unix时间'。此实现使用2000年1月1日午夜的无符号32位整数偏移量。使用这个'时代'有助于简化转换功能,而32位值允许时间正确表示,直到星期二2月7日06:28:15 2136 UTC。定义宏UNIX_OFFSET和NTP_OFFSET以帮助转换为Unix和NTP时间戳。
没有标准的纪元,也没有time_t
的特定基础宽度或签名。但是,如果您将mktime()
的结果与localtime()
一起往返,例如使用相同的库,则会生成正确的结果。一个库或系统的time_t
值不需要与另一个值兼容,因此在系统之间交换time_t
值有点问题。
在这种情况下,您可以通过添加UNIX_OFFSET
或NTP_OFFSET
转换为公认的事实标准,并在必要时确保在接收系统上执行任何相应的调整原则类似于<的原则em> network byte order 例如,通过使用商定的中间表示来交换具有不同终端的系统之间的数据(这也是交换time_t
时需要考虑的事项)。
通常,更换指定格式的字符串(例如ISO 8601)以避免纪元,数据类型和字节序差异更为简单。另一方面,字符串表示的转换比纯粹的算术操作更昂贵。