1941 年的 mktime 或 tz 数据库意外 return
mktime or tz database unexpected return for 1941
mktime returns 1941 年 7 月 3 日 (00:00:00) 和 1941 年 7 月 4 日 (00:00:00) 是意外的。
两者相差82800秒,差了整整一个小时(3600)。
C 程序 diff1941.c(见下文)显示如下:
$> diff1941
july3=-899337600i
diff:82800 should be 86400
起初我以为是 TZ 数据库小时班,但据我了解,根据 zdump 命令,1941 年没有这样的班次。
zdump -v -c 1940,1943 /etc/localtime
/etc/localtime Sun Feb 25 01:59:59 1940 UT = Sun Feb 25 01:59:59 1940 WET isdst=0 gmtoff=0
/etc/localtime Sun Feb 25 02:00:00 1940 UT = Sun Feb 25 03:00:00 1940 WEST isdst=1 gmtoff=3600
/etc/localtime Fri Jun 14 21:59:59 1940 UT = Fri Jun 14 22:59:59 1940 WEST isdst=1 gmtoff=3600
/etc/localtime Fri Jun 14 22:00:00 1940 UT = Sat Jun 15 00:00:00 1940 CEST isdst=1 gmtoff=7200
/etc/localtime Mon Nov 2 00:59:59 1942 UT = Mon Nov 2 02:59:59 1942 CEST isdst=1 gmtoff=7200
/etc/localtime Mon Nov 2 01:00:00 1942 UT = Mon Nov 2 02:00:00 1942 CET isdst=0 gmtoff=3600
所以在这一点上我很困惑。我的程序有一个我看不到的错误(可能),或者 lib C mktime 函数中有一个错误(不太可能),或者 TZ 数据库中有一些微妙的东西,我找不到它(可能):做什么你想到了吗?
我正在使用:
- Ubuntu 20.04 64 位,
- libc 2.31-0ubuntu9,
- tzdata 2019c-3ubuntu1
- /etc/localtime 点 /usr/share/zoneinfo/Europe/Paris
diff1941.c:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
long int stamp(int d,int m,int y)
{
struct tm date;
memset(&date,0,sizeof(date));
date.tm_mday=d;
date.tm_mon=m-1;
date.tm_year=y-1900;
return mktime(&date);
}
int main(int argc, char **argv)
{
if (argc>1)
setenv("TZ","0",1);
long int july3=stamp(3,7,1941);
long int july4=stamp(4,7,1941);
printf("july3=%ldi\n",july3);
printf("diff:%ld should be 86400\n",july4-july3);
}
通常,当您看到 1 小时的时差时,这意味着您应该查看夏令时设置。
在 1941 年 7 月 3 日和 1941 年 7 月 4 日这两个日期,夏令时在法国生效。您指定 tm_isdst = 0
,这意味着夏令时对您的日期无效。所以您的日期无效 - 没有像 1941 年 7 月 3 日这样 00:00:00 没有夏令时的时间。
glibc mktime
tries it's best 来判断你心中所想的时间。实际上,它将第一个日期确定为 1941 年 7 月 3 日 02:00:00,将第二个日期确定为 1941 年 7 月 4 日 01:00:00。差是一天减一小时。
要么设置 isdst=-1
让 mktime
"automagically" 确定您输入时间的当前夏令时。在法国,1941 年一直是 DST,它将确定 isdst=1
。或者通过设置 date.isdst=1
.
明确指定您想要夏令时
mktime returns 1941 年 7 月 3 日 (00:00:00) 和 1941 年 7 月 4 日 (00:00:00) 是意外的。 两者相差82800秒,差了整整一个小时(3600)。
C 程序 diff1941.c(见下文)显示如下:
$> diff1941
july3=-899337600i
diff:82800 should be 86400
起初我以为是 TZ 数据库小时班,但据我了解,根据 zdump 命令,1941 年没有这样的班次。
zdump -v -c 1940,1943 /etc/localtime
/etc/localtime Sun Feb 25 01:59:59 1940 UT = Sun Feb 25 01:59:59 1940 WET isdst=0 gmtoff=0
/etc/localtime Sun Feb 25 02:00:00 1940 UT = Sun Feb 25 03:00:00 1940 WEST isdst=1 gmtoff=3600
/etc/localtime Fri Jun 14 21:59:59 1940 UT = Fri Jun 14 22:59:59 1940 WEST isdst=1 gmtoff=3600
/etc/localtime Fri Jun 14 22:00:00 1940 UT = Sat Jun 15 00:00:00 1940 CEST isdst=1 gmtoff=7200
/etc/localtime Mon Nov 2 00:59:59 1942 UT = Mon Nov 2 02:59:59 1942 CEST isdst=1 gmtoff=7200
/etc/localtime Mon Nov 2 01:00:00 1942 UT = Mon Nov 2 02:00:00 1942 CET isdst=0 gmtoff=3600
所以在这一点上我很困惑。我的程序有一个我看不到的错误(可能),或者 lib C mktime 函数中有一个错误(不太可能),或者 TZ 数据库中有一些微妙的东西,我找不到它(可能):做什么你想到了吗?
我正在使用:
- Ubuntu 20.04 64 位,
- libc 2.31-0ubuntu9,
- tzdata 2019c-3ubuntu1
- /etc/localtime 点 /usr/share/zoneinfo/Europe/Paris
diff1941.c:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
long int stamp(int d,int m,int y)
{
struct tm date;
memset(&date,0,sizeof(date));
date.tm_mday=d;
date.tm_mon=m-1;
date.tm_year=y-1900;
return mktime(&date);
}
int main(int argc, char **argv)
{
if (argc>1)
setenv("TZ","0",1);
long int july3=stamp(3,7,1941);
long int july4=stamp(4,7,1941);
printf("july3=%ldi\n",july3);
printf("diff:%ld should be 86400\n",july4-july3);
}
通常,当您看到 1 小时的时差时,这意味着您应该查看夏令时设置。
在 1941 年 7 月 3 日和 1941 年 7 月 4 日这两个日期,夏令时在法国生效。您指定 tm_isdst = 0
,这意味着夏令时对您的日期无效。所以您的日期无效 - 没有像 1941 年 7 月 3 日这样 00:00:00 没有夏令时的时间。
glibc mktime
tries it's best 来判断你心中所想的时间。实际上,它将第一个日期确定为 1941 年 7 月 3 日 02:00:00,将第二个日期确定为 1941 年 7 月 4 日 01:00:00。差是一天减一小时。
要么设置 isdst=-1
让 mktime
"automagically" 确定您输入时间的当前夏令时。在法国,1941 年一直是 DST,它将确定 isdst=1
。或者通过设置 date.isdst=1
.