【问题标题】:localtime(_r) inversed behaviorlocaltime(_r) 反转行为
【发布时间】:2019-01-24 08:53:23
【问题描述】:

我编写了一个小程序来显示相对于 GMT(或 UTC)的当地时间:

struct tm l;    
time_t stamp = 1534435540;

// No TZ set
printf("TZ=%s\n",getenv("TZ"));
gmtime_r(&stamp, &l);
printf("UTC: %0u:%0u:%0u - %0u.%0u.%0u\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);
localtime_r(&stamp, &l);
printf("Local: %0u:%0u:%0u - %0u.%0u.%0u\n\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);

// Positive TZ: east to Greenwich (e.g. China)
setenv("TZ", "UTC+6:00", 1);    
printf("TZ=%s\n",getenv("TZ"));     
tzset();    
gmtime_r(&stamp, &l);
printf("UTC: %0u:%0u:%0u - %0u.%0u.%0u\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);
localtime_r(&stamp, &l);
printf("Local: %0u:%0u:%0u - %0u.%0u.%0u\n\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);

// Negative TZ: west to Greenwich (e.g. US/Canada)
setenv("TZ", "UTC-6:00", 1);    
printf("TZ=%s\n",getenv("TZ"));
tzset();    
gmtime_r(&stamp, &l);
printf("UTC: %0u:%0u:%0u - %0u.%0u.%0u\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);
localtime_r(&stamp, &l);
printf("Local: %0u:%0u:%0u - %0u.%0u.%0u\n\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);

这个程序的输出如下:

TZ=<null>
UTC: 16:5:40 - 16.8.2018
Local: 16:5:40 - 16.8.2018

TZ=UTC+6:00
UTC: 16:5:40 - 16.8.2018
Local: 10:5:40 - 16.8.2018

TZ=UTC-6:00
UTC: 16:5:40 - 16.8.2018
Local: 22:5:40 - 16.8.2018

看起来很奇怪,不是吗?根据Wiki

例如,如果所描述的时间比 UTC 时间早一小时(例如柏林冬季的时间),则区域指示符将是“+01:00”、“+0100”或简单的“+ 01"

所以 GMT+6 意味着我在 GMT 基础上加上 6 小时来获取当地时间。

this article about TZ variable 却相反:

如果当地时区在本初子午线以西,则为正数,如果在东,则为负数。

我是否遗漏了什么或 linux 的行为与标准相反?

【问题讨论】:

  • 责备美国的 Unix 创造者。他们不喜欢他们的时区偏移为负数。
  • @IanAbbott 还可以创建使用国际时间概念的 UNIX 创建者,例如 GMT,而不是将系统时间设置为本地时间,例如 DOS
  • @chux 我想,但是什么样的白痴会让系统时间受到 DST 变化的影响?此外,UNIX 系统是多用户的,用户可能位于不同的时区。
  • 现在更加混乱了,因为一些 Olsen 风格的时区标识符有数字缩写,并且数字缩写的符号与 ISO 8601 匹配,而不是 POSIX TZ 偏移的符号。跨度>

标签: c linux localtime


【解决方案1】:

Unix 创建者在 TZ 环境变量中使用了相反的符号约定,与在其他地方(包括在 ISO 8601 中)描述时区的方式相比。

Unix 的怪癖在 POSIX.1 中被标准化,这就是 Linux 遵循的标准。

所以是的,如果您想将时区设置为 UTC-04:00(例如,EDT,或者加拿大东部或美国某处的东部夏令时间),您可以将 TZ 设置为 UTC+04:00

【讨论】:

  • 谢谢。很高兴知道
猜你喜欢
  • 1970-01-01
  • 2013-04-17
  • 1970-01-01
  • 1970-01-01
  • 2016-01-10
  • 1970-01-01
  • 1970-01-01
  • 2010-09-09
  • 2018-01-20
相关资源
最近更新 更多