Попытка рассчитать разницу между двумя датами с использованием библиотеки time.h

Я пытаюсь рассчитать точную разницу между двумя датами, которые я даю, используя свою собственную структуру Date, сейчас я тестирую функции, которые возвращают разницу:

Date dateDifference(Date a, Date b){
    time_t rawtime,timeA,timeB;
    struct tm* tA,*tB;
    double difference;

    time(&rawtime);
    tA = tB = localtime(&rawtime);

    tA->tm_mday = 20;
    tA->tm_mon = 1;
    tA->tm_year = 115;

    tB->tm_mday = 3;
    tB->tm_mon = 10;
    tB->tm_year = 89;

    timeA = mktime(tA);
    timeB = mktime(tB);

    difference = difftime(timeA, timeB);
}

Как вы можете видеть, я дал несколько ручных чисел в две структуры 'tm', чтобы проверить это. Когда я отлаживаю, я получаю одно и то же значение как в «timeA», так и в «timeB». Я не совсем знаком с функциями time.h, поэтому я делаю это, используя знания, которые нахожу в Интернете, и это лучшее, чего мне удалось достичь.

Что я делаю не так?


person argamanza    schedule 20.01.2015    source источник


Ответы (3)


У вас две проблемы:

localtime() возвращает указатель на структуру в собственной статической памяти. Вы должны скопировать структуру перед повторным вызовом localtime().

Вы не выделили памяти для двух структур tm — я заменил их указателями на простые структуры.

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

int main()
{
    time_t timeA, timeB;
    struct tm tA, tB, *tptr;
    double difference;

    time(&timeA);
    time(&timeB);
    tptr = localtime(&timeA);
    tA = *tptr;
    tptr = localtime(&timeB);
    tB = *tptr;

    tA.tm_mday = 20;
    tA.tm_mon = 1;
    tA.tm_year = 115;

    tB.tm_mday = 3;
    tB.tm_mon = 10;
    tB.tm_year = 89;

    timeA = mktime(&tA);
    timeB = mktime(&tB);

    difference = difftime(timeA, timeB);
    printf ("Difference is %.0f seconds\n", difference);
    return 0;
}

Вывод программы:

Difference is 798336000 seconds
person Weather Vane    schedule 20.01.2015

Можно подумать, что это вызвано

tA = tB = localtime(&rawtime);

Однако это только половина правды, потому что разделение этого на

tA = localtime(&rawtime);
tB = localtime(&rawtime);

приводит также к тому, что tA и tB оба указывают на один и тот же адрес. Это указано на справочной странице localtime (man 3 localtime): "Возвращаемое значение указывает в статически выделенную строку, которая может быть перезаписана последующими вызовами любой из функций даты и времени».

Поэтому вам нужно скопировать один из двух во вновь выделенный struct tm.

person Sebastian Dressler    schedule 20.01.2015

И tA, и tB должны использовать struct tm, а не указатель, как в struct tm *. Таким образом, у каждого из них есть собственная память, которой можно манипулировать.

В исходном коде использовались указатели на ту же ячейку памяти. Таким образом, изменение одного также изменило другое.

Date dateDifference(Date a, Date b){
    time_t rawtime,timeA,timeB;
    // struct tm* tA,*tB;
    struct tm tA, tB;
    double difference;

    time(&rawtime);
    // tA = tB = localtime(&rawtime);
    tA = tB = *localtime(&rawtime);

    tA.tm_mday = 20;
    tA.tm_mon = 1;
    tA.tm_year = 115;

    tB.tm_mday = 3;
    tB.tm_mon = 10;
    tB.tm_year = 89;

    timeA = mktime(&tA);
    timeB = mktime(&tB);

    difference = difftime(timeA, timeB);
    ...
}

У кода, вероятно, есть еще одна тонкая проблема. Предполагая, что следующий день является сегодняшним, есть ошибка off-by-1

    tA.tm_mday = 20;
    // tA.tm_mon = 1;
    tA.tm_mon = 1 - 1;  // months since January
    tA.tm_year = 115;   // years since 1900
person chux - Reinstate Monica    schedule 20.01.2015