Как посчитать количество дней между двумя датами, используя - PullRequest
0 голосов
/ 28 апреля 2019

Я пытаюсь закодировать функцию c, которая вычисляет число дней между двумя датами (формат: гггг-мм-дд), используя time.h.

Дата читается из строки. Мне не нужно учитывать секунды или минуты.

Я знаю, что мне, вероятно, нужно использовать difftime (), но как его использовать в этом формате?

Спасибо,


Это то, что я пытался сделать, но у меня ошибка сегментации.

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

#define CURRDATE "2019-10-5"
#define OTHER "2019-10-10"

void auxDate(struct tm *t, char *date)
{
    struct tm p;

    p.tm_year = atoi(strtok(date, "-")) - 1900;
    p.tm_mon = atoi(strtok(date, "-"));
    p.tm_mday = atoi(date);

    *t = p;
}
int main()
{
    struct tm date1, date2;

    auxDate(&date1, CURRDATE);
    auxDate(&date2, OTHER);

    printf("%.0lf\n", difftime(mktime(&date1), mktime(&date2)));
}

1 Ответ

0 голосов
/ 28 апреля 2019

Сбой кода по разным причинам.

"2019-10-5" - это строковый литерал , который strtok(date, "-") пытается изменить.Это приводит к неопределенному поведению (UB).Конечно, причина ошибки сегментации.

Вместо этого используйте void auxDate(struct tm *t, const char *date) и анализируйте date, не пытаясь изменить его.См. strspn() и strcspn().


mktime(&date1) использует не полностью присвоенный struct tm.Инициализируйте всех struct tm членов с struct tm p = { 0 };.В противном случае неинициализированные члены могут предоставить ошибочные значения для mktime().


.tm_mon - это число месяца с января.Я бы ожидал где-то - 1.


Поскольку difftime() возвращает разницу в секундах, а цель - разница в днях.Отсутствует деление на секунды в день.


Есть еще один ключевой случай, требующий решения, который связан с переходом на летнее время и переопределением смещения часового пояса, который сместит разницу во времени примерно на час.

Для обработки код может использовать время в полдень и установить DST на -1

p.tm_hour = 12;
p.tm_isdst = -1;

Затем округлить деление:

days = round(difftime(...)/(24.0*60*60));

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


С хорошей стороны, ваш опубликованный код компилируется.

...