Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between two dates in C

Tags:

c

date

I'm a beginner in C.

  • Is there any datatype for dates?
  • In C we have for working with time, is there one for dates too?
  • How can I calculate difference between two dates?
like image 368
Ehsan Avatar asked Dec 18 '12 12:12

Ehsan


2 Answers

The standard C library options for dates and times are pretty poor and loaded with caveats and limitations. If at all possible, use a library such as Gnome Lib which provides GDate and numerous useful date and time functions. This includes g_date_days_between() for getting the number of days between two dates.

The rest of this answer will restrict itself to the standard C library, but if you don't have to limit yourself to the standard, don't torture yourself. Dates are surprisingly hard.


Is there any datatype for dates?

struct tm will serve. Just leave the hour, minutes, and seconds at 0.

Simplest way to ensure all the fields of struct tm are properly populated is to use strptime.

struct tm date;
strptime( "2017-03-21", "%F", &date );

puts( asctime(&date) );  // Mon Mar 21 00:00:00 2017

But that's not a great way to store dates. It turns out it's better to use Julian Days (see below).

In C we have for working with time, is there one for dates too?

If you're referring to time_t, that is also for date-times. It's the number of seconds since "the epoch" which is 1970-01-01 00:00:00 UTC on POSIX systems, but not necessarily others. Unfortunately its safe range is only 1970 to 2037, though any recent version of an operating system will have greatly expanded that range.

How can I calculate difference between two dates?

Depends on what you want. If you want the number of seconds, you could convert the struct tm to time_t using mktime and then use difftime, but that's limited to the 1970-2037 safe range of time_t.

int main() {
    struct tm date1, date2;
    strptime( "2017-03-21", "%F", &date1 );
    strptime( "2018-01-20", "%F", &date2 );

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

If you want the number of days, you'd convert the dates into Julian days, the number of days since November 24, 4714 BC, and subtract. While that might seem ridiculous, this relatively simple formula takes advantage of calendar cycles and only uses integer math.

// The formulas for a and m can be distilled down to these tables.
int Julian_A[12] = { 1, 1, 0 };
int Julian_M[12] = { 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

int julian_day( struct tm *date ) {
    int a = Julian_A[date->tm_mon];
    int m = Julian_M[date->tm_mon];
    int y = date->tm_year + 1900 + 4800 - a;

    return date->tm_mday + ((153*m + 2) / 5) + 365*y + y/4 - y/100 + y/400 - 32045;
}

int main() {
    struct tm date1, date2;
    strptime( "2017-03-21", "%F", &date1 );
    strptime( "2018-01-20", "%F", &date2 );

    // 305 days
    printf("%d days\n", julian_day(&date2) - julian_day(&date1));
}

There are other simple formulas for converting between Julian Dates and calendar dates.

Getting diffs in years, months, and days is difficult because of the number of days in a month varies by month and year, and because it has to be normalized. For example, you wouldn't say 2 years, -1 months, 2 days. You'd say 1 year, 11 months, 29 days (or maybe 28, depends on the month). For this reason, do date math in Julian Days whenever possible.

To get an idea of what's involved, PHP implements this as date_diff. Have a look at the amount of C code required.

like image 199
Schwern Avatar answered Sep 22 '22 08:09

Schwern


Yes,the standard library C Time Library contains structures and functions you want.You can use struct tm to store date and difftime to get the difference.

like image 21
prehistoricpenguin Avatar answered Sep 19 '22 08:09

prehistoricpenguin