本地时间(_r)违规行为

时间:2018-08-17 10:19:03

标签: c linux localtime

我编写了一个小程序来显示相对于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

看起来很奇怪,不是吗?根据{{​​3}}:

  

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

因此,格林尼治标准时间+6表示我将格林尼治标准时间加6个小时以获取当地时间。

但是Wiki却相反:

  

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

我会错过某些东西还是linux的行为与标准相反吗?

1 个答案:

答案 0 :(得分:5)

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

该Unix怪癖在ISO 8601中进行了标准化,这就是Linux遵循的标准。

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