在daylight全局变量的time.h标题中,它说: “如果夏令时规则适用,则此变量具有非零值。非零值并不一定意味着夏令时现在有效;它表示只有夏令时有时生效。”
现在我注意到,在Solaris 11.2和Linux中,“daylight”变量被设置为1,即使我的时区根本不使用夏令时(澳大利亚/布里斯班)。
示例代码确认了这一点,如果我运行tzset并输出我们得到的全局变量: daylight = 1 tz [0] = [AEST] tz [1] = [AEDT] timezone = [-36000]
但根据我的理解,日光应该设置为0,因为我的区域在一年中的任何时候都没有夏令时。
我还注意到,当设置为当前时间时,struct tm返回tm_isdst = 0,这是正确的。
那么为什么daylight变量设置为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);
}
输出是:
date and time : Mon Nov 30 16:41:01 2015
daylight = 1 tz[0] = [AEST] tz[1] = [AEDT] timezone = [-36000]
tm_isdst = 0
答案 0 :(得分:6)
关于C标准tm_isdst
成员。
如果夏令时生效,则
tm_isdst
的值为正,如果夏令时不生效,则为零,如果信息不可用,则为负。 C11dr§7.27.14
这与* nix规范略有不同,关于* nix全局变量daylight
daylight
不属于标准C.
gnu.org报告
变量:int daylight
如果应用夏令时规则,则此变量具有非零值。非零值并不一定意味着夏令时现在生效;这意味着只有夏令时有时才有效。
tm_isdst
指的是struct tm
时间戳。它只表示DST对该时间戳有效。
daylight != 0
表示有时在时区的时间戳中使用DST。
正如澳大利亚/布里斯班曾经观察过DST之前(@Jon Skeet)到1972年,daylight == 1
是合理的daylight
意味着DST在该时区的某段时间内有效(可能自1970年以来)。
OP的“......即使我的时区根本不使用夏令时”也不正确。
以下代码显示自1970年以来“澳大利亚/布里斯班”使用DST(至少timezone 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
答案 1 :(得分:3)
澳大利亚/布里斯班目前不使用夏令时 ,但过去曾有过这样的时间。查看australasia
文件,您会看到它观察到DST的几年。
我对daylight
的解释是,它表明该时区是否曾经曾经观察(或将会遵守现行规则)夏令时。换句话说,如果这是1,那么在执行日期/时间处理时需要小心,而如果它是0,则可以假设一个恒定的UTC偏移。
(我不能立即清楚一个从未观察过DST但是 随时间移动了标准UTC偏移的时区,是否将daylight
设置为1。猜测设置它是完全错误的,但出于上述原因这样做是可行的......)
答案 2 :(得分:0)
如果考虑tzset()会更容易-它会安装时区定义。也就是说,它解释了TZ环境变量的内容,加载了zoneinfo文件或类似文件。 tzset()不会做的一件事就是根据任何特定时间提供信息,例如,它不会查看系统时钟或对当前年份进行假设。有一些标准函数,例如gmtime(),localtime(),mktime()可以处理特定的日期和时间。 tzset()只是为这些功能建立了通用框架,并在外部变量中提供了有关整体时区定义的一些不同的基本信息。 tzset()不会告诉您现在是否有夏令时,因为它不知道或不在乎“现在”是什么。它可以告诉您整个时区定义是否包含有关夏时制的任何信息,例如是否定义tz [1]。
似乎某些文档也已过时,因为它未能明确指定tzset()如何在其外部变量中显示更现代/复杂的时区定义,但了解tzset()的作用大部分后就可以清楚了从它。
“ daylight”和“ timezone”以及一些文档的问题在于,它们是在时区定义仅是TZ字符串的很早就创建的,TZ字符串具有可以指定名称和时间偏移以及诸如“ DST”之类的语法从3月1日星期日开始,至10月3日星期日结束”。它不包含任何历史信息,如果时区的规则已更改,那么您只需更改TZ变量即可实施新规则。现在,我们有了带历史信息的zoneinfo数据库之类的东西,不幸的是tzset()的定义跟不上这个。在内部很好:当tzset()加载复杂的时区时,localtime()等将做正确的事情,但是简单的extern变量不能总是给出准确的摘要。 “夏令时”还算不错:因为tzset()没有考虑任何特定的日期/时间,所以如果在时区数据中的任何地方定义了任何夏令时,则将其设置为“夏令时”是合理的。定义了tz [1]。原则上,时区中的几乎所有内容都可以随时间变化,包括时区名称和基本时区偏移量。这种情况很少发生,但是某些实时时区具有不寻常的历史,尤其是在国际日期变更线附近。