tags:

views:

184

answers:

5

I am trying to make a Date() class, however I think my variables may not be working correctly or I am breaking some obscure class rule? One clue I got was during debugging...it directed me to the "thread.Class" and displayed the following code:

private void exit() {
    if (group != null) {
        group.remove(this);
        group = null;
    }

I am not sure what this means. This is my first time creating my own class. I think this might be causing "System.out.println(today.daysTo(yearFromNow));" to return zero. It may also be related to the scope of some of my variables. My professor told us we should use private variables, but he wasn't entirely clear about it, at least to me. Here is the code that I have so far:

public class Date {

private int year;
private int month;
private int day;

public static void main(String[] args) {
    Date today       = new Date(2010,10,22);
    Date today2      = new Date(2010,10,22);
    Date yearFromNow = new Date(2011,10,22);
    System.out.println(today.daysTo(yearFromNow));
    System.out.println(today.getMonth());
    System.out.println(today.getYear());
    System.out.println(today.equals(today2));
    System.out.println(today.compareTo(yearFromNow));
    System.out.println(today.toString());
}

public Date (int year1, int month1, int day1){

    if (year1 <= 0 || month1 <= 0 || month1 > 12 || day1 <= 0 || day1 > 31){
        throw new IllegalArgumentException("Input a valid d/m/y.");
    }       
    year = year1;
    month = month1;
    day = day1;
}

//Modifies current date by adding specified number of days; Not completed yet.
public void addDays (int days){
    int numberOfDays = daysBeforeMonth(this.month, this.year)+this.day+days;
    if (numberOfDays <= 31){
        this.month = 1;
    }
}

//Returns number of days to specified date.
public int daysTo (Date d){
    int presentDate = dayOfYear(this.day, this.month, this.year);
    int futureDate  = dayOfYear(d.day, d.month, d.year);
    return (futureDate - presentDate);
}

//Returns the number of the month in specified Date;
public int getMonth(){
    return this.month;
}

//Returns the number of the year in specified Date;
public int getYear (){
    return this.year;
}

// Reports whether or not this and d represent the same date.
public boolean equals (Date d){
    return this.day == d.day &&
       this.month   == d.month &&
       this.year    == d.year;
}

// Returns negative if this is earlier than d, returns positive
// if this is later than d, and returns zero otherwise.
public int compareTo (Date d){
    if (this.month < d.month || this.day < d.day || this.year < d.year){
        return -1;
    }
    if (this.month > d.month || this.day > d.day || this.year > d.year){
        return 1;
    }
    else return 0;
}

// Converts this Date into string form, using the format
// mm/dd/yyyy, as in 07/22/2006.
public String toString (){
    String stringDate = month+"/"+day+"/"+year;
    return stringDate;
}

// takes an int year and tests whether year is divisble by 4, but
// not 100 OR if it's divisible by 400 => is leap year, else not.
public static boolean isLeapYear(int year) {
    if (year % 4 == 0 && year % 100 != 0) {
        return true;
    }

    else if (year % 400 == 0) {
        return true;
    }

    else {
        return false;
    }
}

//Returns how many days before a certain month, else returns 0.
public static int daysBeforeMonth(int month, int year) {
    int Feb = 28;
    if (isLeapYear(year) == true) {
        month = 29;
    }
    if (month == 1) {
        return 0;
    } else if (month == 2) {
        return 31;
    } else if (month == 3) {
        return Feb + 31;
    } else if (month == 4) {
        return Feb + 61;
    } else if (month == 5) {
        return Feb + 92;
    } else if (month == 6) {
        return Feb + 122;
    } else if (month == 7) {
        return Feb + 153;
    } else if (month == 8) {
        return Feb + 184;
    } else if (month == 9) {
        return Feb + 215;
    } else if (month == 10) {
        return Feb + 245;
    } else if (month == 11) {
        return Feb + 276;
    } else if (month == 12) {
        return Feb + 306;
    }

    else {
        return 0;
    }
}
//Returns how many days have passed in reference to a specific date.
public static int dayOfYear(int day, int month, int year){
    return daysBeforeMonth(month, year) + day;
}

}

If someone could please explain to me where I am wrong in my logic that would be great! Thanks!

A: 

I think the issue is that it rounds down, the year is 364.25 days. Which means your threshold wouldn't be hit until 365 days. Take a look at Joda time.

Woot4Moo
I presume the OP is to write his/her own class, not to use a ready-made library.
Péter Török
I agree that this is most likely the OP's assignment as well. However, it does not take away from the wise choice to look at a properly implemented calendar for the purposes of pedagogy.
Woot4Moo
Also you can create a Date for 2010-02-31, which is a bit weird.
Douglas Leeder
isn't that European?
Woot4Moo
@Woot4Moo I was thinking of February 31st rather than a particular date format.
Douglas Leeder
Oh, ok! Sorry, I had already written the daysBeforeMonth method a couple weeks ago and realized it would be easier just to edit it so that the month parameter was taken as an integer instead of the previous String ("Jan","Feb", "Mar", etc...). I probably just got confused or forgot to edit that part. I will fix that little issue and it should work fine. Thanks everyone for the speedy responses! I will post my final solution when I am finished. I have to go to class now, but I will fix it as soon as I get out around 1pm.
Cryptologica
don't forget to accept an answer
Woot4Moo
+1  A: 

Here

public int daysTo (Date d){
    int presentDate = dayOfYear(this.day, this.month, this.year);
    int futureDate  = dayOfYear(d.day, d.month, d.year);
    return (futureDate - presentDate);
}

you calculate the day of year for each dates - which will be the same for both, as each date is Oct 22 (or Nov 22?), [update] albeit from different years [/update] - then return the difference, which is obviously 0.

Moreover, here

public static int daysBeforeMonth(int month, int year) {
    int Feb = 28;
    if (isLeapYear(year) == true) {
        month = 29;
    }
    if (month == 1) {
        return 0;
    } else if ... {
    } else if (month == 12) {
        return Feb + 306;
    }
    else {
        return 0;
    }
}

you change month to an invalid value in leap years, thus the method will return 0.

I guess you want to set Feb, not month.

(Btw the Java convention is to start variable names with lowercase.)

Péter Török
maybe I am confused, but what does Feb + 306 do? 364- 59 = 305
Woot4Moo
@Downvoter, care to explain?
Péter Török
@Woot4Moo, why ask me? This is a copy straight from the OP :-)
Péter Török
I was an upvote. Fair enough on it being ops code
Woot4Moo
Your answer ignores that he is comparing dates from different years and this one day is the least of his problems.
Jacob Tomaw
@Jacob Tomaw, beg your pardon? It is the OP's code which ignores that the dates are from different years, and my answer is pointing this out. I edited my sentence to make it clearer though. Could you explain what "one day" are you talking about?
Péter Török
@Péter Török When I commented, your answer appeared to only be correct his leap year calculation.
Jacob Tomaw
+3  A: 

Aside:

if (isLeapYear(year) == true) {
    month = 29;
}

should be:

if (isLeapYear(year) == true) {
    Feb = 29;
}

I think.

But I think the primary problem is that you are comparing dayOfYear for the two dates.

Consider dayOfYear for January 1st:

  • 2010-01-01: dayOfYear is 1.
  • 2011-01-01: dayOfYear is 1.

So the difference is 0.

Douglas Leeder
all things considered his Date object should know if its a leap year, which would remove the needless call to `isLeapYear(year)`
Woot4Moo
When your debugging I find it best to start with unrelated data (Dates), like january 1st 2010 and June 15 2011, the day/month/year is all unrelated. And then afterwards try using special cases like exactly 1 year or leap years etc.
Valchris
@Valchris You don't think it would be better to start with (say) 2010-01-01 - 2010-01-02, and work up from there? Testing the shortest path first?
Douglas Leeder
@Douglas Leeder, What if you had an error in your algorithm that accidentally returned 1 less then the difference? 0 would be a very confusing response..I'd prefer to test the midpoint of a data set instead of it's boundaries first.
Valchris
+1  A: 

In daysTo() you calculate the day number of the current date and the target date. You ony use the years to check for leap years.

You get a result of 0 because your two days in years 2010 and 2011 have the same day number in the year. You should also take into account the year numbers of the dates.

rsp
A: 

There is a logic problem here:

Your daysTo() function uses your dayOfYear() function, which is relative to only that year. Two days that are 1 year apart will return the same dayOfYear() value, and subtracting will give 0.

To solve this, you could make a method that gets days from the UNIX epoch (January 1, 1970) and compare those.

Also to programmatically get the current date (rather than setting today manually), use System.getCurrentTimeMillis() to get the milliseconds from the UNIX epoch, then just divide the days and add them to 1/1/1970.

Matt Bell