Сравнение дат в C

У меня есть какая-то задача создать программу на C, которая сравнивает две даты и возвращает количество промежуточных дней.

Дело в том, что идентификатор для переменных должен быть один из библиотеки time.h, поэтому я не могу использовать строки или целые числа для этих двух дат. Я знаю, что есть переменная time_t для переменных в time.h, но как мне продолжать запрашивать пользовательский ввод для переменной с этим типом? Я не знаю%, что я должен положить в printf или scanf для этого типа. Кроме того, есть ли способ проверить правильность ввода пользователя?

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

В интернете не так много материала, поэтому я прошу помощи. Заранее спасибо!

3 ответа

Решение

Я предполагаю, что вы хотите только количество дней между двумя датами (не время). Как упоминалось в одном из комментариев, выберите любой формат, который вы хотите для пользовательского ввода, а затем проанализируйте его.

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

Так, например, если бы я хотел узнать количество дней от моего дня рождения в этом году (27 мая 2016 года) до Дня независимости (4 июля), я бы включил в программу 20160527 и 20160704.

Как целые числа их относительно легко конвертировать в месяц, день и год.

Объявите структуру tm и установите день и год месяца для каждого из них:

// Lets say the above dates were read into integers indate1 and indate2,
// so indate1 = 20160527 and indate2 = 20160704

#include <time.h>

struct tm dt = {0};
dt.tm_year = (indate1/10000) - 1900;
dt.tm_mon  = (indate1/100)%100;
dt.tm_mday = (indate1%100);

// Now convert to time_t:
time_t dt1 = mktime(&dt);

// Now do the same for indate2:
dt.tm_year = (indate2/10000) - 1900;
dt.tm_mon  = (indate2/100)%100;
dt.tm_mday = (indate2%100);
time_t dt2 = mktime(&dt);

// Now take the difference between the two dates:
double seconds = difftime( dt2, dt1 );

// Now convert to number of days:
unsigned long days = ( seconds / (60*60*24) );
fprintf( stdout, "The number of days between those two dates is %ld\n", days);

В дополнение к ручной упаковке struct tm на основе целочисленного ввода вы можете работать напрямую с string ввод с использованием strptime, strptime преобразует строку символов, указанную в качестве первого параметра, в struct tm в соответствии с предоставленным format строка.

Это может оказаться более удобным в зависимости от типа ввода, с которым вы имеете дело. Коротким примером будет:

#define _XOPEN_SOURCE

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

int main (int argc, char **argv) {

    char *dtstr1 = argc > 1 ? argv[1] : "20160527";
    char *dtstr2 = argc > 2 ? argv[2] : "20160704";
    struct tm dt = {0};
    time_t dt1 = 0, dt2 = 0;

    /* convert input strings to struct tm */
    strptime (dtstr2, "%Y%m%d", &dt);    
    dt2 = mktime (&dt);

    strptime (dtstr1, "%Y%m%d", &dt);    
    dt1 = mktime (&dt);

    /* get difference in calendar time */
    double seconds = difftime (dt2, dt1);

    /* convert to number of days */
    long days = (seconds/(60*60*24));

    if (seconds < 0) /* output difference with occurrence orientation */
        printf ("%s occurs %ld days after %s\n", dtstr1, -days, dtstr2);
    else if (seconds > 0)
        printf ("%s occurs %ld days before %s\n", dtstr1, days, dtstr2);
    else
        printf ("%s and %s are contemporaneous\n", dtstr1, dtstr2);

    return 0;
}

(примечание: хотя это маловероятно, вы можете проверить наличие days преобразование)

Пример использования / Вывод

$ ./bin/time_diff_days
20160527 occurs 38 days before 20160704

$ ./bin/time_diff_days 20160101 20150101
20160101 occurs 365 days after 20150101

$ ./bin/time_diff_days 20150101 20150101
20150101 and 20150101 are contemporaneous

Дайте знать, если у вас появятся вопросы.

Тип time_t это просто счетчик секунд. Вы хотите превратить его в struct tm* призвание localtime(time_t*), char *ctime(time_t*) даст вам строковое представление. Для форматированного ввода и вывода вы должны работать с отдельными членами struct tm сам.

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