Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Calculating days between two dates in C
#1
Okay, so with the help of Alex and a few others for the past couple of days I managed to produce:

Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int check_and_assign_input(char *date, int *month, int *day, int *year)
{
    int slashcheck = 0;
    char *stepper = date;
    while(*stepper)
    {
        if(*stepper == '/')
        {
            slashcheck++;
            stepper++;
        }
        else stepper++;
    }


    if(slashcheck != 2)
        return 0;


  *month = atoi(strtok(date, "/"));
  *day =  atoi(strtok(NULL, "/"));
  *year = atoi(strtok(NULL, "/"));
        return 1;


}


int check_chron(int year1, int year2, int month1, int month2, int day1, int day2)
{
    if(year1 < year2)
        return 1;
    else if(year1 > year2)
        return 0;
    else if(year1 = year2)
    {
        if(month1 < month2)
            return 1;
        else if(month1 > month2)
            return 0;
        else if(month1 = month2)
        {
            if(day1 < day2)
                return 1;
            else if(day1 > day2)
                return 0;
            else if(day1 = day2)
            {
                printf("There are zero days between the two dates.");
                exit(1);
            }
        }
    }
}


int check_days_in_month(int month_check, int year_check)
{
    int days;
    switch(month_check)
    {
        case 1: case 3: case 5: case 7: case 8: case 10: case 12:
            days = 31;
            break;
        case 4: case 6: case 9: case 11:
            days = 30;
            break;
        case 2:
            if((year_check % 100 == 0) && (year_check % 400 != 0))
            {
                days = 28;
                break;
            }
            else if((year_check % 400 == 0) || (year_check % 4 == 0))
            {
                days = 29;
                break;
            }
            else
            {
                days = 28;
                break;
            }


    }


    return days;
}


int if_leap(int year_check)
{
    if((year_check % 100 == 0) && (year_check % 400 != 0))
        return 0;
    else if((year_check % 4) == 0)
        return 1;
    else
        return 0;
}


int calc_days(int year1, int year2, int month1, int month2, int day1, int day2, int days_in_month1, int days_in_month2)
{
    int days_until = 0;
    int month_days = 0;
    int days_in_year = 0;
    
    if(year1 < year2)
    {
        while(year1 < year2)
        {
            days_in_year = if_leap(year1);
            if(days_in_year == 1)
                days_until += 366;
            else days_until += 365;
            ++year1;
        }
        if(month1 < month2)
        {
            while(month1 < month2)
            {
                month_days = check_days_in_month(month1, year1);
                days_until += month_days;
                ++month1;
            }
        }
        if(month1 = month2)
        {
            month_days = check_days_in_month(month1, year1);
            days_until += (month_days - day2 - 5);
        }
    }


    else if(year1 = year2)
    {
        while(month1 < month2)
        {
            month_days = check_days_in_month(month1, year1);
            days_until += month_days;
            ++month1;
        }
        if(month1 = month2)
        {
            days_until += (day2 - day1);
        }
    }


    return days_until;
}


int main(void)
{
  char first_date[12];
  char second_date[12];
  int day1, month1, year1, day2, month2, year2;
  int days_in_month1, days_in_month2, chronology;
  int days_between, slashcheck;


  /* Get first date string */


  printf("Enter your first date: ");
  scanf("%s", first_date);

  slashcheck = check_and_assign_input(first_date, &month1, &day1, &year1);
  if(slashcheck == 0)
  {
      printf("Invalid input in first date.");
      exit(1);
  }  


  /*Call check_days_in_month function to test input day data against norm*/


  days_in_month1 = check_days_in_month(month1, year1);

  printf("Enter your second date: ");
  scanf("%s", second_date);


  slashcheck = check_and_assign_input(second_date, &month2, &day2, &year2);
  if(slashcheck == 0)
  {
      printf("\nInvalid input in second date.");
      exit(1);
  }  


  /*Call check_days_in_month function to test input day data against norm*/
  days_in_month2 = check_days_in_month(month2, year2);


  if((day1 > days_in_month1) || (day2 > days_in_month2))
  {
      printf("\nInvalid input day of first or second date.");
      exit(1);
  }
  
  chronology = check_chron(year1, year2, month1, month2, day1, day2);


  if(chronology == 0)
  {
      printf("\nInvalid input in chronology == 0.");
      exit(1);
  }


  days_between = calc_days(year1, year2, month1, month2, day1, day2, days_in_month1, days_in_month2);
  printf("\nThere are %d days between your two dates.", days_between);


    return 0;


}

I run into a problem whenever the dates input into the program are not in the same year, though, with the program usually being about 6 or more days over what the actual day count is.

I figure it has something to do with the algorithm of my calc_days function, but I can't seem to find the error.

If you can help in any way I would greatly appreciate it.

For ease of access, here's the calc_days function:
Code:
int calc_days(int year1, int year2, int month1, int month2, int day1, int day2, int days_in_month1, int days_in_month2){
    int days_until = 0;
    int month_days = 0;
    int days_in_year = 0;
    
    if(year1 < year2)
    {
        while(year1 < year2)
        {
            days_in_year = if_leap(year1);
            if(days_in_year == 1)
                days_until += 366;
            else days_until += 365;
            ++year1;
        }
        if(month1 < month2)
        {
            while(month1 < month2)
            {
                month_days = check_days_in_month(month1, year1);
                days_until += month_days;
                ++month1;
            }
        }
        if(month1 = month2)
        {
            month_days = check_days_in_month(month1, year1);
            days_until += (month_days - day2 - 5);
        }
    }


    else if(year1 = year2)
    {
        while(month1 < month2)
        {
            month_days = check_days_in_month(month1, year1);
            days_until += month_days;
            ++month1;
        }
        if(month1 = month2)
        {
            days_until += (day2 - day1);
        }
    }


    return days_until;
}
Reply
#2
C has a function, mktime(), for converting from a struct with year/month/day/hour/minute/second fields to a single long int (seconds since the epoch).
Use that to convert both dates, subtract the ints, divide by seconds in a day.
Reply
#3
We just learned about structs last week so I'll give it a shot when I get back home from class today.
Reply
#4
What is the reason for this?
Code:
days_until += (month_days - day2 - 5);

Also you're assuming month1 < month2. Your code wouldn't work for inputs like
date1 = 12/31/2011
date2 = 1/1/2012

But yeah SaptaZapta's way is much easier.
Reply
#5
Oh, that was me just messing around, thinking that it might be easier to subtract five if my results were consistently five over what they're supposed to be.

I'm currently stuck on the structure part, and I'll elaborate when I get home.

Edit: You weren't wrong about that second part, either. I get 390 days between 12/31/2011 and 1/1/2012. Blah.
Reply
#6
I was able to get it working correctly once I corrected the algorithm I was using.

Thanks for the help all.
Reply
#7
this is more about coding style
Code:
while(year1 < year2)
        {
[B]            days_in_year = if_leap(year1);
            if(days_in_year == 1)[/B]
                days_until += 366;
            else days_until += 365;
            ++year1;
        }

I'd prefer
Code:
while(year1 < year2)
        {
[B]            if(isLeap(year1))[/B]
                days_until += 366;
            else days_until += 365;
            ++year1;
        }

I could be wrong, I coded c++ before but not C



add on:
say comparing 2011 Dec 1 and 2012 Jan 1
You cannot just add 365/366 days base on the year2 > year1
Reply
#8
C style would be more like
Code:
while (year1 < year2)
  days_until += 365 + if_leap(year1++);
Reply
#9
SaptaZapta Wrote:C style would be more like
Code:
while (year1 < year2)
  days_until += 365 + if_leap(year1++);

more like
Code:
int i;
for (i = year1; i < year2; i++)
  days_until += 365 + if_leap(i);

Unless you actually want to modify the contents of year1, that is.
Reply
#10
Nikkey Wrote:more like
Code:
int i;
for (i = year1; i < year2; i++)
  days_until += 365 + if_leap(i);

Unless you actually want to modify the contents of year1, that is.

Look at the original code. It modifies year1.
Reply
#11
SaptaZapta Wrote:Look at the original code. It modifies year1.

I know that - but while we're here, some code style should be learnt, shouldn't it? There's no reason to modify year1 in this case, thus you shouldn't want to - it makes it harder to reason around the code for others later on.
Reply
#12
My professor never really went over style, to my knowledge... just more of, "This is what the finished product looks like" and sent us on our way.

I know my coding/style are messy - that's my thought process, or understanding of it.
Reply
#13
Panacea Wrote:My professor never really went over style, to my knowledge... just more of, "This is what the finished product looks like" and sent us on our way.

I know my coding/style are messy - that's my thought process, or understanding of it.

I think the idea is not to change things unnecessarily. If you have a function that does X, it shouldn't do Y if Y doesn't serve any practical purpose towards X, especially changing global values.
Reply
#14
Kalovale Wrote:I think the idea is not to change things unnecessarily. If you have a function that does X, it shouldn't do Y if Y doesn't serve any practical purpose towards X, especially changing global values.

But it's not a global value. It's an argument to the function, passed by value, so the function can do whatever it pleases with it.
Reply
#15
SaptaZapta Wrote:But it's not a global value. It's an argument to the function, passed by value, so the function can do whatever it pleases with it.

Yeah, but then, what does the variable year1 represent? What if someone later on came and had to edit the code, thinking that year1 is the first year? They would get pretty confused when year1 and year2 were equal (unless it's specifically mentioned in the code). It's just good code practise to avoid changing state unless you really have to.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)