Gregorian calendar project

Difficulty calculating the number of days between two dates.

Page 1 of 1

2 Replies - 3968 Views - Last Post: 01 December 2009 - 08:29 PM Rate Topic: -----

#1 riadfodig  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 21
  • Joined: 01-November 09

Gregorian calendar project

Post icon  Posted 01 December 2009 - 04:32 PM

The assignment instructions are included as comments in the code.

public class SimpleDate { 
  private int myYear;
  private int myMonth;
  private int myDayOfMonth;
   
  public SimpleDate(int year, int month, int dayOfMonth) {
	myYear = year;
	myMonth = month;
	myDayOfMonth = dayOfMonth;
	}
 
  /* numberOfDaysTo returns the number of days */ 
  /* from this SimpleDate to the other SimpleDate. */ 
  /* Note that the keyword 'this' refers to the first date, */ 
  /* and the variable 'other' refers to the second date. */ 
  
  public int numberOfDaysTo(SimpleDate other) {
	int numberOfDays = 0;
	   
	SimpleDate copy = new SimpleDate(0, 0, 0);
	copy = this.copyDate();
	System.out.println("From numberOfDaysTo, copy = " + copy);
	int compare = copy.compareTo(other);
	
	while( compare == 1 ) {
	  compare = copy.compareTo(other);
	  copy.changeToYesterday();
	  if (! this.equalDate(other) ) numberOfDays --;
	}
	System.out.println("compare after Yesterday = " + compare);
	while ( compare == -1 ) {
	  compare = copy.compareTo(other);
	  copy.changeToTomorrow();
	  if (! this.equalDate(other) ) numberOfDays ++;
	}
	System.out.println("compare after Tomorrow = " + compare);
	if ( compare == 0 ) return numberOfDays;
	
	
	return numberOfDays;
	
  }
  /* Change this date to tomorrow's date.  
   * Do this by incrementing myDayOfMonth. 
   * How do you know if myDayOfMonth is too large? 
   * What should you do in this case?  
   * If you increment myMonth so it changes to 13, what do you need to do? */ 
  public void changeToTomorrow( ) {
	this.myDayOfMonth ++;
	if (this.myDayOfMonth > this.getDaysInMonth() ) {
	  this.myMonth ++;
	  if (this.myMonth > 12) {
		this.myYear ++;
		this.myMonth = 1;
	  }
	}
  }
  
  /* Change this date to yesterday's date.  
   * Do this by decrementing myDayOfMonth. 
   * If this changes myDayOfMonth to zero, what do you need to do? 
   * What should be assigned to myDayOfMonth in this case? 
   * If you decrement myMonth so it changes to zero, what do you need to do? */ 
  public void changeToYesterday( ) {
	this.myDayOfMonth --;
	if (this.myDayOfMonth < 1) {
	  this.myMonth --;
	  this.myDayOfMonth = this.getDaysInMonth();
	  if (this.myMonth < 1) {
		this.myMonth = 12;
		this.myDayOfMonth = this.getDaysInMonth();
		this.myYear --;
	  }
	}
  }
  
  
  /* Return a copy of this SimpleDate, i.e., 
   * construct and return a SimpleDate object using myYear, myMonth, and myDayOfMonth. */ 
  public SimpleDate copyDate( ) {
	SimpleDate copy = new SimpleDate(this.myYear, this.myMonth, this.myDayOfMonth);
	return copy;
	
  }  
  
  /* leapYear returns true if myYear is a leap year in the Gregorian calendar.
   * 
   If myYear is divisible by 400 ( myYear % 400 == 0 ),
   then myYear is a leap year.
   
   If myYear is divisible by 100, but is not divisible by 400,
   then myYear is not a leap year.
   
   If myYear is divisible by 4, but is not divisible by 100,
   then myYear is a leap year.
   
   If myYear is not divisible by 4, then myYear is not a leap year.
   */
  public boolean leapYear( ) {
	
	if( myYear % 400 == 0 ) return true;
	else if( myYear % 100 == 0 && myYear % 400 == 0 ) return false;
	else if( myYear % 4 == 0 ) return true;
	else return false;
  }
  
  /* getDaysInMonth returns the number of days in myMonth, taking leap
   years into account.  If myMonth is not between 1 and 12, return 0.
   E.g.,
   
   if ( myMonth == 1 ) return 31;
   else if ( myMonth == 2 && leapYear() ) return 29;
   else if ( myMonth == 2 && ! leapYear() ) return 28;
   ...
   */
  public int getDaysInMonth( ) {
	
	if ( myMonth == 1 ) return 31;
	else if ( myMonth == 2 && leapYear() ) return 29;
	else if ( myMonth == 2 && ! leapYear() ) return 28;
	else if ( myMonth == 3 ) return 31;
	else if ( myMonth == 4 ) return 30;
	else if ( myMonth == 5 ) return 31;
	else if ( myMonth == 6 ) return 30;
	else if ( myMonth == 7 ) return 31;
	else if ( myMonth == 8 ) return 31;
	else if ( myMonth == 9 ) return 30;
	else if ( myMonth == 10 ) return 31;
	else if ( myMonth == 11 ) return 30;
	else if ( myMonth == 12 ) return 31;
	else return 0;
	
  }
  /* validDate returns true if the instance fields describe a valid date.
   myDayOfMonth should be between 1 and getDaysInMonth( ).
   myMonth should be between 1 and 12.
   */
  public boolean validDate( ) {
	if( myDayOfMonth > 0 && myDayOfMonth <= this.getDaysInMonth( ) ) {
	  if( myMonth > 0 && myMonth <= 12 ) return true;
	  else return false;
	}
	else return false;
  }
  /* equalDate returns true if this SimpleDate is equal to the other SimpleDate.
   This returns true if all three instance fields are equal to each other.
   */
  public boolean equalDate(SimpleDate other) {
	if( this.myYear == other.myYear ) {
	  if( this.myMonth == other.myMonth ) {
		if( this.myDayOfMonth == other.myDayOfMonth ) {
		  return true; 
		}
		else return false;
	  }
	  else return false;
	}
	else return false;
  }
  /* compareTo returns -1 if this SimpleDate is before the other SimpleDate.
   It returns 0 if this SimpleDate is equal to the other SimpleDate.
   It returns 1 if this SimpleDate is after the other SimpleDate.
   E.g.,
   
   if ( myYear < other.myYear ) return -1;
   else if ( myYear > other.myYear ) return 1;
   else if ( myMonth < other.myMonth ) return -1;
   ...
   */
  public int compareTo(SimpleDate other) {
	if ( this.equalDate(other) ) return 0;
	if ( this.myYear < other.myYear ) return -1;
	else if ( this.myYear > other.myYear ) return 1;
	else if ( this.myMonth < other.myMonth ) return -1;
	else if ( this.myMonth > other.myMonth ) return 1;
	else if ( this.myDayOfMonth > other.myDayOfMonth ) return 1;
	else return -1;
	
  }

}



The main method is short:
import java.util.Scanner;

public class SimpleDateTest {
  public static void main(String[] args) {
	Scanner in = new Scanner(System.in);
	
	System.out.println("Please enter the year, month, and day of month: ");
	int year = in.nextInt();
	int month = in.nextInt();
	int dayOfMonth = in.nextInt();
	SimpleDate date1 = new SimpleDate(year, month, dayOfMonth);
	  
	System.out.println(date1.toString());
	
	SimpleDate date2 = new SimpleDate(2009, 12, 2);
	System.out.println(date1.numberOfDaysTo(date2));
   
  }
  
}



The problem I'm having is getting the numberOfDaysTo() method to work. When the user inputs 2009, 12, 1 (December 1, 2009) the result is 2, while it should be 1. When the user inputs 2009, 1, 1 the result is 42. Because of this I think the problem is in either the changeToTomorrow or the changeToYesterday methods, although I'm not entirely confident in the numberOfDaysTo method itself. I've spent quite some time on this and have changed a lot from how I originally approached the problem, so I'm open to any suggestions regarding other parts of the program.

Thanks in advance!

Is This A Good Question/Topic? 0
  • +

Replies To: Gregorian calendar project

#2 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8378
  • View blog
  • Posts: 31,956
  • Joined: 06-March 08

Re: Gregorian calendar project

Posted 01 December 2009 - 07:32 PM

A lot to say, your stuf is OK but you make it complicated for nothing at many place
simplifying it may save you a lot of trouble and will make it easier to debug

lets start by the most obvious

public boolean leapYear( ) {
	
	if( myYear % 400 == 0 ) return true;
	else if( myYear % 100 == 0 && myYear % 400 == 0 ) return false;
	else if( myYear % 4 == 0 ) return true;
	else return false;
  }


You return true if a multiple of 400 no need to check for 400 another time
and no need to make a else if you returned
public boolean leapYear( ) {
	
	if( myYear % 400 == 0 ) return true;
	if( myYear % 100 == 0) return false;
	return ( myYear % 4 == 0 );
  }



Now the day in month
public int getDaysInMonth( ) {
	
	if ( myMonth == 1 ) return 31;
	else if ( myMonth == 2 && leapYear() ) return 29;
	else if ( myMonth == 2 && ! leapYear() ) return 28;
	else if ( myMonth == 3 ) return 31;
	else if ( myMonth == 4 ) return 30;
	else if ( myMonth == 5 ) return 31;
	else if ( myMonth == 6 ) return 30;
	else if ( myMonth == 7 ) return 31;
	else if ( myMonth == 8 ) return 31;
	else if ( myMonth == 9 ) return 30;
	else if ( myMonth == 10 ) return 31;
	else if ( myMonth == 11 ) return 30;
	else if ( myMonth == 12 ) return 31;
	else return 0;
	
  }


public int getDaysInMonth() {
   int[] days = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
   if(lapYear())
		days[2] = 29;
   return days[myMonth];



This one has a bug
  public void changeToTomorrow( ) {
	myDayOfMonth ++;
	if (myDayOfMonth > getDaysInMonth() ) {
	  myMonth ++;
	  if (myMonth > 12) {
		myYear ++;
		myMonth = 1;
	  }
	}
  }


if you wrap around you have to set the day to 1
also avoid the use of this. when not necessary it just confuses everything
  public void changeToTomorrow( ) {
	myDayOfMonth ++;
	if (this.myDayOfMonth > this.getDaysInMonth() ) {
	  myDayOfMonth = 1;	  // <---- missing
	  myMonth ++;
	  if (this.myMonth > 12) {
		myYear ++;
		myMonth = 1;
	  }
	}
  }



Don't know what you are trying to do here
	SimpleDate copy = new SimpleDate(0, 0, 0);
	copy = this.copyDate();


you create a new SimpleDate object with 0,0,0
but the next statement to erase/overload it with your copyDate method
copy methodDate which is kind of useless. Simply do
	  SimpleDate copy = new SimpleDate(myYear, myMonth, myDayOfMonth);



Avoid multiple imbricked if like in
  public boolean equalDate(SimpleDate other) {
	if( this.myYear == other.myYear ) {
	  if( this.myMonth == other.myMonth ) {
		if( this.myDayOfMonth == other.myDayOfMonth ) {
		  return true; 
		}
		else return false;
	  }
	  else return false;
	}
	else return false;
  }


this could be rewritten
  public boolean equalDate(SimpleDate other) {
	if(myYear != other.myYear ) 
		return false;
	if(myMonth != other.myMonth )
		return false;
	return (myDayOfMonth == other.myDayOfMonth);
  }


And could be even be written assuming that compareTo won't call equalDate() will see later
  public boolean equalDate(SimpleDate other) {	
	 return (compareTo(other) == 0);   



Now your compareTo
  public int compareTo(SimpleDate other) {
	if ( this.equalDate(other) ) return 0;
	if ( this.myYear < other.myYear ) return -1;
	else if ( this.myYear > other.myYear ) return 1;
	else if ( this.myMonth < other.myMonth ) return -1;
	else if ( this.myMonth > other.myMonth ) return 1;
	else if ( this.myDayOfMonth > other.myDayOfMonth ) return 1;
	else return -1;   
  }


Again no need to put else statement if you return in the statement before but what about that ?
public int compareTo(SimpleDate other) {
   int x = myYear * 10000 + myMonth * 100 + dayOfMonth;
   int y = other.myYear * 10000 + other.myMonth * 100 + other.dayOfMonth;
   return y - x;	// or x - y maybe depends on how you see it
}




Have fun

This post has been edited by pbl: 01 December 2009 - 07:36 PM

Was This Post Helpful? 3
  • +
  • -

#3 riadfodig  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 21
  • Joined: 01-November 09

Re: Gregorian calendar project

Posted 01 December 2009 - 08:29 PM

Thanks! I ended up with an off by one error, but was able to correct it with some work.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1