I've been searching a lot about how to get the difference in months between two dates using C but I've not been able to solve it. So I figured I start simple to get an understanding of it and go from there.
Building from some of the examples I've seen that is supposed to calculate the hours between two dates, this is the code I came up with:
#define _XOPEN_SOURCE
#include <time.h>
#include <stdio.h>
int main()
{
char *time1 = "2015-08-10";
char *time2 = "2017-05-16";
struct tm tm1;
struct tm tm2;
time_t t1;
time_t t2;
double hours;
strptime(time1, "%Y-%m-%d", &tm1);
strptime(time2, "%Y-%m-%d", &tm2);
printf("time1: %s\n", time1);
printf("tm1.year: %d\n", tm1.tm_year);
printf("tm1.mon : %d\n", tm1.tm_mon);
printf("tm1.day : %d\n", tm1.tm_mday);
printf("time2: %s\n", time2);
printf("tm2.year: %d\n", tm2.tm_year);
printf("tm2.mon : %d\n", tm2.tm_mon);
printf("tm2.day : %d\n", tm2.tm_mday);
t1 = mktime(&tm1);
t2 = mktime(&tm2);
hours = difftime(t2, t1) / 60 / 60;
printf("diff: %lf\n", hours);
return 0;
}
It compiles and runs but it gives me different hours every time I execute it? Can't understand why?
Compile:
$ gcc -Wall main.c -o timespan
And executions:
$ ./timespan
time1: 2015-08-10
tm1.year: 115
tm1.mon : 7
tm1.day : 10
time2: 2017-05-16
tm2.year: 117
tm2.mon : 4
tm2.day : 16
diff: -1885271229.700556
$ ./timespan
time1: 2015-08-10
tm1.year: 115
tm1.mon : 7
tm1.day : 10
time2: 2017-05-16
tm2.year: 117
tm2.mon : 4
tm2.day : 16
diff: -652404645.977222
The strings you're reading in don't have a time component, so those fields aren't set by strptime
.
From the man page :
Notes
In principle, this function does not initialize tm but only stores the values specified. This means that tm should be initialized before the call. Details differ a bit between different UNIX systems. The glibc implementation does not touch those fields which are not explicitly specified, except that it recomputes the tm_wday and tm_yday field if any of the year, month, or day elements changed.
When you then call mktime
, it reads those uninitialized fields, invoking undefined behavior .
You need to initialize these structs:
struct tm tm1 = {0};
struct tm tm2 = {0};
Then you'll get consistent results:
time1: 2015-08-10
tm1.year: 115
tm1.mon : 7
tm1.day : 10
time2: 2017-05-16
tm2.year: 117
tm2.mon : 4
tm2.day : 16
diff: 15480.000000
Also, for printing values of type double
, use the %f
format specifier. %lf
is valid, but has no effect.
Thanks for all the help. I managed to solve the initial problem (diff in months) and for those interested, this is the product.
#define _XOPEN_SOURCE 800
#include <time.h>
#include <stdio.h>
struct date_stamp {
int yer;
int mon;
int day;
int hrs;
int min;
int sec;
};
int main()
{
char *time1 = "2015-08-10";
char *time2 = "2016-08-10";
struct tm tm1 = {0}; /* tm structs need to be initialized */
struct tm tm2 = {0};
struct date_stamp diff_date;
time_t t1;
time_t t2;
double diff;
/* convert the time strings into tm structs */
strptime(time1, "%Y-%m-%d", &tm1);
strptime(time2, "%Y-%m-%d", &tm2);
/* make the time_t variables*/
t1 = mktime(&tm1);
t2 = mktime(&tm2);
/* calculate the diffrence in seconds */
diff = difftime(t2, t1);
/*
* appearently there goes 2629746 seconds
* in one gregorian month
*/
diff_date.sec = diff;
diff_date.min = diff / 60;
diff_date.hrs = diff / 60 / 60;
diff_date.day = diff / 60 / 60 / 24;
diff_date.mon = diff / 2629746;
diff_date.yer = diff / 60 / 60 / 24 / 365;
printf("start : %s\n", time1);
printf("end : %s\n", time2);
puts( "-------+-----------");
printf("Year : %d\n", diff_date.yer);
printf("Months : %d\n", diff_date.mon);
printf("Days : %d\n", diff_date.day);
printf("Hours : %d\n", diff_date.hrs);
printf("Minutes: %d\n", diff_date.min);
printf("Seconds: %d\n", diff_date.sec);
return 0;
}
Don't think the calculations are rock solid thou (366 days in a year ?!?). But I'll tweak that later, at least I have a base to build from.
$ gcc -Wall main.c -o timespan
$ ./timespan
start : 2015-08-10
end : 2016-08-10
-------+-----------
Year : 1
Months : 12
Days : 366
Hours : 8784
Minutes: 527040
Seconds: 31622400
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.