Сравнение дат в 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
сам.