Day Validation is always returning the illegal argument exception and never setting the day as inputed especially when trying to input 29 for february in a leap year. i've been trying to find the error for a long time now and just gave up. thanks for your help in advance.
import java.util.Calendar;
public class DateOfBirth
{
private int day;
private int month;
private int year;
private Calendar cld = Calendar.getInstance();
public DateOfBirth()
{
this(0,0,0);
}
public DateOfBirth(int a,int b,int c)
{
setDay(c);
setMonth(a);
setYear(b);
}
public void setDay(int a)
{
if( getMonth()==2 && (getYear() % 4 == 0 && (getYear() % 100 != 0 || getYear() % 400 == 0))&& a == 29)
day = a;
else if(getMonth() == 2 && a <= 28)
day = a;
else if(getMonth() == 1 || getMonth() == 3 || getMonth() == 5 || getMonth() == 7 || getMonth() == 8 || getMonth() == 10 || getMonth() == 12 && a < 31)
day = a;
else if(getMonth() == 4 || getMonth() == 6 || getMonth() == 9 || getMonth() == 11 && a < 30)
day = a;
else
throw new IllegalArgumentException("Day Out Of Bounds.");
}
public void setMonth(int b)
{
if( b > 0 && b <= 12)
month = b;
else
throw new IllegalArgumentException("Month Out of Bounds.");
}
public void setYear(int c)
{
if( c > (cld.get(Calendar.YEAR) - 150) && c < cld.get(Calendar.YEAR))
year = c;
else
throw new IllegalArgumentException("Year Out of Bounds.");
}
public int getDay()
{
return day;
}
public int getMonth()
{
return month;
}
public int getYear()
{
return year;
}
@Override
public String toString()
{
return String.format("Date Of Birth: %02d/%02d/%d",getDay(),getMonth(),getYear());
}
}
You're calling setDay
first, before you call setMonth
or setYear
... which means setDay
doesn't know which month and year you're talking about. It can't possibly validate that the day is correct without that information.
You could just switch the order of the setter calls:
setYear(b);
setMonth(a);
setDay(c);
However:
b
represents the year, for example?)I would suggest that you make your class immutable if at all possible. Then you just need to validate in the constructor. Consider refactoring it to:
// TODO: Think of a decent name. Not DateOfBirth because it's just representing
// a date, and not Date as that conflicts with java.util.Date.
public final class GregorianDate {
private final int year, month day;
public GregorianDate(int year, int month, int day) {
validate(year, month, day);
this.year = year;
this.month = month;
this.day = day;
}
private static void validate(int year, int month, int day) {
// TODO: The validation
}
// getters, toString, hashCode, equals, and possibly implement
// Comparable<GregorianDate> too.
}
Of course, this is assuming this is just an exercise - normally you'd use appropriate date/time APIs that are already provided to you - ideally avoiding java.util.Date/Calendar
and using Joda Time or the Java 8 java.time
API.
See more on this question at Stackoverflow