Неожиданное возвращение базы данных mktime или tz за 1941 год

Возврат mktime за 3 июля 1941 г. (00:00:00) и 4 июля 1941 г. (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 ответ

Решение

Обычно, когда вы видите разницу во времени в 1 час, это означает, что вам следует взглянуть на настройки летнего времени.

Обе даты, 3 июля 1941 г. и 4 июля 1941 г., во Франции действовало летнее время. Вы указываетеtm_isdst = 0, это означает, что летнее время не действует для ваших дат. Значит, ваши даты недействительны - не было такого времени, как 3 июля 1941 года с 00:00:00 без летнего времени.

Glibc mktime старается лучше всего определить, какое время вы имеете в виду. Фактически он определяет первую из дат как 3 июля 1941 года 02:00:00, а вторую из дат как 4 июля 1941 года 01:00:00. Разница составляет один день минус один час.

Либо установить isdst=-1 позволить mktime"автоматически" определить текущее летнее время для времени ввода. Во Франции в 1941 году все время было летнее время, это определитisdst=1. Или явно укажите, что вы хотите DST, установивdate.isdst=1.

Другие вопросы по тегам