тот же результат mktime() для другой строки даты и времени

У меня есть это:

#include <stdio.h>
#include <time.h>

int main()
{
    struct tm timeinfo;

    strptime( "2016-02-18 09:00:00", "%Y-%m-%d %H:%M:%S", &timeinfo );
    printf( "result 1=%ld\n", mktime( &timeinfo ) );

    strptime( "2016-02-18 08:00:00", "%Y-%m-%d %H:%M:%S", &timeinfo );
    printf( "result 2=%ld\n", mktime( &timeinfo ) );
}

Результат для этого MCVE сводит меня с ума:

result 1=1455778800
result 2=1455778800

1455778800 — это время UTC для 2016-02-18 07:00:00, поэтому оно будет правильным для второй строки даты и времени. Но почему я получаю для двух разных строк один и тот же результат?

А теперь это:

{
    struct tm timeinfo;

    strptime( "2016-02-18 08:00:00", "%Y-%m-%d %H:%M:%S", &timeinfo );
    printf( "result 2=%ld\n", mktime( &timeinfo ) );
    strptime( "2016-02-18 09:00:00", "%Y-%m-%d %H:%M:%S", &timeinfo );
    printf( "result 1=%ld\n", mktime( &timeinfo ) );
}

Вот у меня такой результат:

result 2=1455775200
result 1=1455782400

result 1 теперь правильно, но result 2 на час раньше. Похоже, что внутренние структуры glibc неправильно инициализированы, когда я вызываю их в первый раз.

Я связываю его с другой версией glibc, чем система использует. Когда я связываю его с версией системы, он работает. Что я сделал не так?


person Peter VARGA    schedule 19.02.2016    source источник
comment
Я не могу воспроизвести ваш результат с помощью clang 700.1.81 в OS X. Я живу в другом часовом поясе. Вы, кажется, находитесь в центральноевропейском времени? Возможно, это может вызвать проблему. Попробуйте timegm вместо mktime, чтобы исключить возможность часовых поясов. Не могли бы вы подтвердить свой часовой пояс? Также вы должны распечатать &timeinfo вручную, чтобы проверить, виноват ли strptime или mktime.   -  person Schwern    schedule 19.02.2016


Ответы (1)


Хорошо, решение было на man страницах:

В принципе, эта функция не инициализирует tm, а сохраняет только указанные значения. Это означает, что tm должен быть инициализирован
перед вызовом. Детали немного различаются в разных системах UNIX
. Реализация glibc не затрагивает те поля, которые
не указаны явно, за исключением того, что она пересчитывает поля tm_wday
и tm_yday, если какой-либо из элементов года, месяца или дня изменился.

bzero(&timeinfo, sizeof(timeinfo)); и теперь это работает.

person Peter VARGA    schedule 19.02.2016
comment
@chux Я использую -Wall -Wextra -Werror, и это не работает для gcc. Есть много старых структур, которые я должен инициализировать с помощью bzero() - person Peter VARGA; 20.02.2016
comment
Множество способов обнуления данных. bzero() лучше, чем пытаться обнулить отдельные поля, поскольку общее количество полей struct tm не определено. Хорошо, что это работает для вас. - person chux - Reinstate Monica; 20.02.2016