C program days between two dates

I wrote a program that should find days between two dates, but it has some hiccups. Logic makes perfect sense in my head when I read it, so I assume that I have some syntax errors that I constantly look at or something like that.

Firstly, when you enter two dates in different years, the output always turns off for about one month (31 in most cases, but 32 in one case ... go figure). Secondly, two dates for exactly one month will return the number of days in the second month (i.e., from 1/1/1 to 2/1/1 yield 28). There are some inevitable other strange things this program does, but I hope this is enough information to help you guys figure out what I'm doing wrong. For the life of me, I cannot figure it out on my own. I am relatively new to C, so please be careful =)

thanks

// Calculates the number of calendar days between any two dates in history (beginning with 1/1/1). #include <stdio.h> #include <stdlib.h> void leap(int year1, int year2, int *leap1, int *leap2); void date(int *month1, int *day1, int *year1, int *month2, int *day2, int *year2, int *leap1, int *leap2); int main(void) { int month1, day1, year1, month2, day2, year2, leap1, leap2; int daysPerMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; int daysPerMonthLeap[] = {31,29,31,30,31,30,31,31,30,31,30,31}; leap(year1, year2, &leap1, &leap2); date(&month1, &day1, &year1, &month2, &day2, &year2, &leap1, &leap2); if(year1 == year2) { int i, total; if(month1 == month2) // Total days if month1 == month2 { total = day2 - day1; printf("There are %d days between the two dates.", total); } else { if(leap1 == 1) total = daysPerMonthLeap[month1] - day1; else total = daysPerMonth[month1] - day1; for(i = month1 + 1; i < month2; i++) // Days remaining between dates (excluding last month) { if(leap1 == 1) total += daysPerMonthLeap[i]; else total += daysPerMonth[i]; } total += day2; // Final sum of days between dates (including last month) printf("There are %d days between the two dates.", total); } } else // If year1 != year2 ... { int i, total, century1 = ((year1 / 100) + 1) * 100, falseleap = 0; if(leap1 == 1) total = daysPerMonthLeap[month1] - day1; else total = daysPerMonth[month1] - day1; for(i = month1 + 1; i <= 12; i++) // Day remaining in first year { if(leap1 == 1) total += daysPerMonthLeap[i]; else total += daysPerMonth[i]; } for(i = 1; i < month2; i++) // Days remaining in final year (excluding last month) { if(leap2 == 1) total += daysPerMonthLeap[i]; else total += daysPerMonth[i]; } int leapcount1 = year1 / 4; // Leap years prior to and including first year int leapcount2 = year2 / 4; // Leap years prior to and NOT including final year if(year2 % 4 == 0) leapcount2 -= 1; int leaptotal = leapcount2 - leapcount1; // Leap years between dates for(i = century1; i < year2; i += 100) // "False" leap years (divisible by 100 but not 400) { if((i % 400) != 0) falseleap += 1; } total += 365 * (year2 - year1 - 1) + day2 + leaptotal - falseleap; // Final calculation printf("There are %d days between the two dates.", total); } return 0; } void leap(int year1, int year2, int *leap1, int *leap2) // Determines if first and final years are leap years { if(year1 % 4 == 0) { if(year1 % 100 == 0) { if(year1 % 400 == 0) *leap1 = 1; else *leap1 = 0; } else *leap1 = 1; } else *leap1 = 0; if(year2 % 4 == 0) { if(year2 % 100 == 0) { if(year2 % 400 == 0) *leap2 = 1; else *leap2 = 0; } else *leap2 = 1; } else *leap2 = 0; } void date(int *month1, int *day1, int *year1, int *month2, int *day2, int *year2, int *leap1, int *leap2) { for(;;) // Infinite loop (exited upon valid input) { int fail = 0; printf("\nEnter first date: "); scanf("%d/%d/%d", month1, day1, year1); if(*month1 < 1 || *month1 > 12) { printf("Invalid entry for month.\n"); fail += 1; } if(*day1 < 1 || *day1 > 31) { printf("Invalid entry for day.\n"); fail += 1; } if(*year1 < 1) { printf("Invalid entry for year.\n"); fail += 1; } if(daysPerMonth[month1] == 30 && *day1 > 30) { printf("Invalid month and day combination.\n"); fail += 1; } if(*month1 == 2) { if(*leap1 == 1 && *day1 > 29) { printf("Invalid month and day combination.\n"); fail += 1; } else if(*day1 > 28) { printf("Invalid month and day combination.\n"); fail += 1; } } if(fail > 0) continue; else break; } for(;;) { int fail = 0; printf("\nEnter second date: "); scanf("%d/%d/%d", month2, day2, year2); if(*year1 == *year2) { if(*month1 > *month2) { printf("Invalid entry.\n"); fail += 1; } if(*month1 == *month2 && *day1 > *day2) { printf("Invalid entry.\n"); fail += 1; } } if(*month2 < 1 || *month2 > 12) { printf("Invalid entry for month.\n"); fail += 1; } if(*day2 < 1 || *day2 > 31) { printf("Invalid entry for day.\n"); fail += 1; } if(*year2 < 1) { printf("Invalid entry for year.\n"); fail += 1; } if(daysPerMonth[month2] == 30 && *day2 > 30) { printf("Invalid month and day combination.\n"); fail += 1; } if(*month2 == 2) { if(*leap2 == 1 && *day2 > 29) { printf("Invalid month and day combination.\n"); fail += 1; } else if(*day2 > 28) { printf("Invalid month and day combination.\n"); fail += 1; } } if(fail > 0) continue; else break; } } 
+6
source share
6 answers

First, the leap function seems too complicated; you do not need to do both dates in the same function call, and I am sure that it can be written more briefly so that it is more correct. Here the version that I am storing is not brief, but I am sure it is easy to check the logic:

 int is_leap_year(int year) { if (year % 400 == 0) { return 1; } else if (year % 100 == 0) { return 0; } else if (year % 4 == 0) { return 1; } else { return 0; } } 

You can call it like this:

 int year1, year2, leap1, leap2; year1 = get_input(); year2 = get_input(); leap1 = is_leap_year(year1); leap2 = is_leap_year(year2); 

No pointers and significantly less code duplication. Yes, I know that is_leap_year() can be reduced to a single if(...) , but it's easy to read.

Secondly, I think you have a mismatch between 0-indexed arrays and 1-indexed human months:

  if(*month1 < 1 || *month1 > 12) 

against

  int daysPerMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 

Thirdly, I think that days per month can be calculated a little better:

 int days_in_month(int month, int year) { int leap = is_leap_year(year); /* JFMAMJJASOND */ int days[2][12] = {{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; if (month < 0 || month > 11 || year < 1753) return -1; return days[leap][month]; } 

Here I assume that January is 0; you will need to make the rest of the code match. (I learned this trick with two arrays from Elements of a programming style ( p. 54 ).) The best part of using such a procedure is that it removes the jump condition from the difference calculation.

Fourth, you index arrays outside your borders:

  for(i = month1 + 1; i <= 12; i++) { if(leap1 == 1) total += daysPerMonthLeap[i]; 

This is just another example of a problem with 0-indexed arrays and 1-indexed months - but rest assured that you are correcting this when correcting months too.

I have a fear that I have not found all the problems yet - it may be easier for you to sort the first and second date after entering and delete all this verification code, and then use the before and after names or something to give names that are easier to think through in the complex core of computing.

+6
source

Decrease month indices by 1.

I want to say that January will match daysPerMonth[0] or daysPerMonthLeap[0] , not daysPerMonth[1] or daysPerMonthLeap[1] . The reason for this is that array indices start at 0.

So wherever you use month1 , month2 inside daysPerMonth[] or daysPerMonthLeap[] , use month1-1 and month2-1 .

Hope this is clear enough. Otherwise, feel free to comment.

+3
source

This is not a complete answer. I just wanted to mention the best way to calculate a leap year (this is taken from The C Programming Language - Page # 41)

 if ((year % 4 == 0 && year % 100 != 0) || year % 400 ==0) printf("%d is a leap year \n", year); else printf("%d is not a leap year \n", year); 
+3
source

Edit

 int daysPerMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; int daysPerMonthLeap[] = {31,29,31,30,31,30,31,31,30,31,30,31}; 

to

 int daysPerMonth[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int daysPerMonthLeap[] = {0,31,29,31,30,31,30,31,31,30,31,30,31}; 

i.e. put the arrays at the beginning, since all the code relies on the values โ€‹โ€‹of the array to start at element 1, and not at element 0.

This will save you from the error you complained about.

Another problem is the "one by one" error when you add day2 to the total. In both cases, you should add day2 - 1 , not day2 . This is also related to date indexes starting with 1 instead of 0.

After I made these changes (plus a couple to get the code to compile), it works correctly.

+2
source

There are several problems in the code snippet. But I have to say that this is a very good attempt. There are many short cuts that you are trying to achieve.

I wrote the following program, which finds the number of days between two dates. You can use this as a link.

 #include <stdio.h> #include <stdlib.h> char *month[13] = {"None", "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"}; /* daysPerMonth[0] = non leap year daysPerMonth[1] = leap year */ int daysPerMonth[2][13] = {{-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {-1, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; typedef struct _d { int day; /* 1 to 31 */ int month; /* 1 to 12 */ int year; /* any */ }dt; void print_dt(dt d) { printf("%d %s %d \n", d.day, month[d.month], d.year); return; } int leap(int year) { return ((year % 4 == 0 && year % 100 != 0) || year % 400 ==0) ? 1 : 0; } int minus(dt d1, dt d2) { int d1_l = leap(d1.year), d2_l = leap(d2.year); int y, m; int total_days = 0; for (y = d1.year; y >= d2.year ; y--) { if (y == d1.year) { for (m = d1.month ; m >= 1 ; m--) { if (m == d1.month) total_days += d1.day; else total_days += daysPerMonth[leap(y)][m]; // printf("%d - %5s - %d - %d \n", y, month[m], daysPerMonth[leap(y)][m], total_days); } } else if (y == d2.year) { for (m = 12 ; m >= d2.month ; m--) { if (m == d2.month) total_days += daysPerMonth[leap(y)][m] - d2.day; else total_days += daysPerMonth[leap(y)][m]; // printf("%d - %5s - %d - %d \n", y, month[m], daysPerMonth[leap(y)][m], total_days); } } else { for (m = 12 ; m >= 1 ; m--) { total_days += daysPerMonth[leap(y)][m]; // printf("%d - %5s - %d - %d \n", y, month[m], daysPerMonth[leap(y)][m], total_days); } } } return total_days; } int main(void) { /* 28 Oct 2018 */ dt d2 = {28, 10, 2018}; /* 30 June 2006 */ dt d1 = {30, 6, 2006}; int days; int d1_pt = 0, d2_pt = 0; if (d1.year > d2.year) d1_pt += 100; else d2_pt += 100; if (d1.month > d2.month) d1_pt += 10; else d2_pt += 10; if (d1.day > d2.day) d1_pt += 1; else d2_pt += 1; days = (d1_pt > d2_pt) ? minus(d1, d2) : minus(d2, d1); print_dt(d1); print_dt(d2); printf("number of days: %d \n", days); return 0; } 

The output is as follows:

 $ gcc dates.c $ ./a.out 30 June 2006 28 Oct 2018 number of days: 4503 $ 

Note: this is not a complete program. It does not have input validation.

Hope this helps!

+1
source
 //Difference/Duration between two dates //No need to calculate leap year offset or anything // Author: Vinay Kaple # include <iostream> using namespace std; int main(int argc, char const *argv[]) { int days_add, days_sub, c_date, c_month, b_date, b_month, c_year, b_year; cout<<"Current Date(dd mm yyyy): "; cin>>c_date>>c_month>>c_year; cout<<"Birth Date(dd mm yyyy): "; cin>>b_date>>b_month>>b_year; int offset_month[12] = {0,31,59,90,120,151,181,212,243,273,304,334}; days_add = c_date + offset_month[c_month-1]; days_sub = b_date + offset_month[b_month-1]; int total_days = (c_year-b_year)*365.2422 + days_add - days_sub+1; cout<<"Total days: "<<total_days<<"\n"; int total_seconds = total_days*24*60*60; cout<<"Total seconds: "<<total_seconds<<"\n"; return 0; } 
0
source

Source: https://habr.com/ru/post/914088/


All Articles