c-tzset与夏令时的全局变量解释



在夏令时全局变量的time.h标头中,它表示:"如果夏令时规则适用,则此变量具有非零值。非零值并不一定意味着夏令时现在生效;它只意味着夏令营有时生效。"

现在我注意到,在Solaris 11.2和Linux中,"夏令时"变量都设置为1,尽管我所在的时区根本不使用夏令时(澳大利亚/布里斯班)。

示例代码证实了这一点,如果我运行tzset并输出我们得到的全局变量:夏令时=1 tz[0]=[AST]tz[1]=[ADT]时区=[-36000]

但根据我的理解,夏令时应该设置为0,因为我所在的区域在一年中的任何时候都没有夏令时。

我还注意到,结构tm在设置为当前时间时返回tm_isdst=0,这是正确的。

那么,为什么日光变量设置为1呢?不应该设置为0吗?还是我误解了这一点?

代码为:

#include <stdio.h>
#include <time.h>
void main()
{
  time_t t;
  struct tm     *tms = { 0 };
  tzset();
  time(&t);
  tms = localtime(&t);
  printf("date and time : %s",ctime(&t));
  printf("daylight = %d tz[0] = [%s] tz[1] = [%s] timezone = [%ld]n", daylight, tzname[0], tzname[1], timezone);
  printf("tm_isdst = %dn",tms->tm_isdst);
}

输出为:

date and time : Mon Nov 30 16:41:01 2015
daylight = 1 tz[0] = [AEST] tz[1] = [AEDT] timezone = [-36000]
tm_isdst = 0

关于C标准tm_isdst成员。

如果夏令时有效,则tm_isdst的值为正;如果夏令时无效,则为零;如果信息不可用,则为负。C11dr§7.27.1 4

这与*nix关于*nix全局变量daylight的规范略有不同
daylight不是标准C.的一部分


gnu.org报告

变量:int夏令时
如果夏令时规则适用,则此变量的值为非零值。非零值并不一定意味着夏令时现在生效;这只意味着夏令时有时是有效的。


tm_isdst是指struct tm的时间戳。这只意味着夏令时对该时间戳有效。

daylight != 0意味着有时在时区的时间戳中使用DST。

正如澳大利亚/布里斯班在1972年之前(@Jon Skeet)曾经观测到的夏令时,具有daylight == 1是合理的,因为daylight意味着夏令时在该时区的一段时间内有效(可能自1970年以来)。

OP的"…尽管我的时区根本不使用夏令时"是不正确的。


以下代码显示,自1970年以来,夏令时在"澳大利亚/布里斯班"已经使用了几年(至少时区DB是这么认为的)。

#include<time.h>
#include<stdlib.h>
#include<sys/time.h>
int main(void) {
  setenv("TZ", "Australia/Brisbane", 1);
  tzset();
  time_t now;
  time(&now);
  struct tm tm;
  int isdst = 42; // See Hitchhiker's_Guide_to_the_Galaxy
  time_t t;
  for (t = 0; t < now; t += 3600) {
    tm = *localtime(&t);
    if (tm.tm_isdst != isdst) {
      printf("dst:%d %s", tm.tm_isdst, ctime(&t));
      isdst = tm.tm_isdst;
    }
  }
  printf("dst:%d %s", tm.tm_isdst, ctime(&t));
  return 0;
}

输出

dst:0 Thu Jan  1 10:00:00 1970
dst:1 Sun Oct 31 03:00:00 1971
dst:0 Sun Feb 27 02:00:00 1972
dst:1 Sun Oct 29 03:00:00 1989
dst:0 Sun Mar  4 02:00:00 1990
dst:1 Sun Oct 28 03:00:00 1990
dst:0 Sun Mar  3 02:00:00 1991
dst:1 Sun Oct 27 03:00:00 1991
dst:0 Sun Mar  1 02:00:00 1992
dst:0 Tue Dec  1 16:00:00 2015

澳大利亚/布里斯班目前不使用夏令时,但过去使用过;查看australasia文件,您将看到它观测DST的几年。

我对daylight的解释是,它表明该时区是否曾观察到(或将遵守当前规则)夏令时。换句话说,如果它是1,则在执行日期/时间处理时需要小心,而如果它是0,则可以假设UTC偏移量是恒定的。

(我现在还不清楚一个从未观测到夏令时,但已经随着时间的推移改变了其标准UTC偏移量的时区是否会将daylight设置为1。我想设置它是完全错误的,但出于上述原因,这样做是可行的…)

如果你考虑一下tzset()的作用,它会更容易——它安装了一个时区定义。也就是说,它解释TZ环境变量的内容,加载zoneinfo文件或类似文件。tzset()不做的一件事是提供基于任何特定时间的信息,例如,它不查看系统时钟或对当前年份进行假设。有一些标准函数,如gmtime()、localtime()和mktime(),可以处理特定的日期和时间。tzset()只是为这些函数的工作设置了通用框架,并在外部变量中提供了关于整个时区定义的一些不同的基本信息。tzset()不会告诉你现在是否有夏令时,因为它不知道或不在乎"现在"是什么。它可以告诉你整个时区定义是否包含夏令时的任何信息,例如是否定义了tz[1]。

有些文档似乎也过时了,因为它没有明确说明tzset()如何在其外部变量中显示更现代/更复杂的时区定义,但了解tzset(

"夏令时"one_answers"时区"以及一些文档的问题在于,它们是在很早的时候创建的,当时时区定义只不过是一个TZ字符串,它的语法可以指定名称和时间偏移,比如"夏令时从3月1日星期日开始,到10月3日星期日结束"。它不包含历史信息,如果时区的规则发生了更改,那么您只需更改TZ变量即可实现新规则。我们现在有了类似zoneinfo数据库的历史信息,不幸的是,tzset()的定义跟不上。内部很好:当tzset()加载复杂时区时,localtime()等会做正确的事情,但简单的外部变量不能总是给出准确的摘要。"夏令时"还不错:因为tzset()不考虑任何特定的日期/时间,所以如果时区数据中的任何地方都定义了夏令时,那么它设置"夏令时(夏令时)"是合理的,同样,如果定义了tz[1],那么设置"夏"也是合理的。原则上,时区中的任何东西都可能随着时间的推移而变化,包括时区名称和基准时区偏移量。这种情况很少发生,但一些真实时区有着不同寻常的历史,尤其是在国际日期线附近。

相关内容

  • 没有找到相关文章

最新更新