C tzset和daylight全局变量在time.h中的解释

C tzset和daylight全局变量在time.h中的解释,c,timezone,dst,C,Timezone,Dst,daylight全局变量的time.h标题中显示: “如果适用夏令时规则,则此变量的值为非零值。非零值不一定表示夏令时现在生效;它仅表示夏令时有时生效。” 现在我注意到,在Solaris 11.2和Linux中,“daylight”变量都被设置为1,即使我的时区根本不使用夏令时(澳大利亚/布里斯班) 示例代码证实了这一点,如果我运行tzset并输出我们得到的全局变量: 日光=1 tz[0]=[AEST]tz[1]=[AEDT]时区=[-36000] 但据我所知,日光应设置为0,因为我所在的区域在

daylight全局变量的time.h标题中显示: “如果适用夏令时规则,则此变量的值为非零值。非零值不一定表示夏令时现在生效;它仅表示夏令时有时生效。”

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

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

但据我所知,日光应设置为0,因为我所在的区域在一年中的任何时候都没有夏令时

我还注意到,当设置为当前时间时,struct 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 = %d\n",tms->tm_isdst);
}

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

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


(我现在还不清楚一个从未观测过DST,但随着时间推移其标准UTC偏移量发生变化的时区是否会将日光设置为1。我想设置它是完全错误的,但出于上述原因,这样做是可行的…)

关于C标准
tm_isdst
成员

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

这与*nix全局变量的*nix规范略有不同
daylight

日光
不是标准C的一部分


报告

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


tm_isdst
指的是
struct tm
时间戳。它仅表示该时间戳有效

日光!=0
表示有时在时区的时间戳中使用DST

正如澳大利亚/布里斯班在1972年之前曾观察到的DST(),拥有
日光==1
是合理的,因为
日光
意味着DST在该时区的某些时间段内有效(可能自1970年起)

OP的“…即使我的时区根本不使用夏令时”是不正确的


下面的代码显示,自1970年以来,DST在“澳大利亚/布里斯班”中已经使用了几年(至少政府认为是这样)


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

有些文档似乎也过时了,因为它没有明确说明tzset()如何在其外部变量中表示更现代/复杂的时区定义,但了解tzset()的作用,基本上可以清楚地看到它的作用


“daylight”和“timezone”以及一些文档的问题在于,它们是在很早的时候创建的,当时时区定义只不过是一个TZ字符串,它的语法可以指定名称和时间偏移以及类似“DST从3月1日星期日开始,到10月3日星期日结束”之类的内容。它不包含历史信息,如果时区的规则更改了,那么您只需更改TZ变量来实现新规则。我们现在有了类似于zoneinfo数据库的历史信息,不幸的是tzset()的定义没有跟上这一点。内部很好:当tzset()加载复杂时区时,localtime()等将做正确的事情,但简单的外部变量不能总是给出准确的摘要。“日光”并不太坏:因为TZSETE()不考虑任何特定的日期/时间,如果在时区数据中定义了任何日光节约时间,则再次设置“日光”是合理的,本质上,如果定义了TZ(1)。原则上,时区中的任何东西都可能随着年份的变化而变化,包括时区名称和基本时区偏移量。这种情况很少发生,但一些实时时区有着不同寻常的历史,尤其是在国际日期线附近。

谢谢。这个变量的描述是模糊的,我还没有找到一个明确的答案。但我想你一定是对的。我遇到这个问题是因为一家大型软件供应商使用这个变量来确定在一年中的某个时候是否应该遵守夏令时。因此,他们的软件错误地识别了Bris中的服务器
date and time : Mon Nov 30 16:41:01 2015
daylight = 1 tz[0] = [AEST] tz[1] = [AEDT] timezone = [-36000]
tm_isdst = 0
#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