user979616
user979616

Reputation: 273

Simplify the following code with switch cases?

Im trying to check for date validity. I can only use else and switch cases. Im not sure if the following can be simplified.

if (monthNum<1||monthNum>12){
    validDate=false;
    System.out.println("Invalid Date Entered");
}

else if ((monthNum==1||monthNum==3||monthNum==5||monthNum==7||monthNum==8||monthNum==10||monthNum==12)&&(dayNum<1||dayNum>31)) {
    validDate=false;
    System.out.println("Invalid date entered");
}

else if ((monthNum==4||monthNum==6||monthNum==9||monthNum==11)&&(dayNum<1||dayNum>30)){
    validDate=false;
    System.out.println("Invalid date entered");
}

else if (monthNum==2 &&(dayNum<1||dayNum>28)) {
    validDate=false;
    System.out.println("Invalid date entered");
}

else {
    validDate=true;
}

Upvotes: 0

Views: 476

Answers (8)

rsp
rsp

Reputation: 23373

The following is shorter, it uses the fact that you can add more detailed checks onto checks that always hold (i.e. all months have less than 32 days) and by moving the sysout message to where all tests are done.

boolean validDate = (monthNum >= 1 && monthNum <= 12 && dayNum >= 1 && dayNum <= 31);

if (monthNum == 4 || monthNum == 6 || monthNum == 9 || monthNum == 11) {

    validDate &&= (dayNum <= 30);
}

else if (monthNum == 2) {

    validDate &&= (dayNum <= 28);
}

if (!validDate) {
    System.out.println("Invalid Date Entered");
}

In case it is permitted to use a lookup table, you can simplify further like this:

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

boolean validDate = (monthNum >= 1 && monthNum <= 12 && 
                     dayNum >= 1 && dayNum <= monthDays[monthNum - 1]);

if (!validDate) {
    System.out.println("Invalid Date Entered");
}

Upvotes: 0

Tim Gage
Tim Gage

Reputation: 1381

Adding leap-year handling to the answer from mergeconflict:

private static boolean validateDate(int yearNum, int monthNum, int dayNum) {

if (monthNum < 1 || monthNum > 12) return false;
if (dayNum < 1 ) return false;

switch(monthNum) {
  case 1: case 3: case 5: case 7: case 8: case 10: case 12:
    return dayNum <= 31;
  case 4: case 6: case 9: case 11:
    return dayNum <= 30;
  default: // 2
    boolean leapYear = (yearNum % 4 == 0 && yearNum % 100 != 0) || yearNum % 400 == 0;
    if (leapYear) {
      return dayNum <= 29;
    } else {
      return dayNum <= 28;
    }
}

}

Upvotes: 0

user949300
user949300

Reputation: 15729

First, do one check at the very beginning for a dayNum < 1. I don't know of any month with a day 0. :-)

If you keep the current if/else system, I would at least split the date check from the month check. Also, my personal preference, make the logic positive - this is usually easier to follow. And a comment or two would be nice...

e.g.

// Thirty days hath September, April, June, and November
else if ((monthNum==4||monthNum==6||monthNum==9||monthNum==11)) {
    validDate = dayNum<=30;  // note that logic is now "positive"
    if (!validDate)
       System.out.println("Invalid date entered");
}

I don't know where you are in your coursework, but have you considered using arrays? An array of 12 ints, the maximum day for each of the 12 months, would be useful.

Upvotes: 0

Thom
Thom

Reputation: 15092

1-28 is always valid. Start with that. Only do the switch if the number is > 28.

Upvotes: 0

Ken Wayne VanderLinde
Ken Wayne VanderLinde

Reputation: 19347

Here's some things that you could think about:

In well-designed software, this validation would likely appear in its own method:

bool validateDate(int monthNum, int dayNum) {
     // your code goes here
}

We can also split the month and day validation into their own methods, e.g.:

bool validateMonth(int monthNum) {
    return (1 <= monthNum) && (monthNum <= 12)
}

bool validateDay(int monthNum, int dayNum) {
    // ...
}

For the inside of the validateDay method, any day less than 1 is bad, so we can pull that out front:

if (day < 1)
    return false;

The I would definitely use a switch for the rest:

switch(monthNum) {
    case 1:
    case 3:
    // ...
    case 12:
        return dayNum <= 31;
    // similarly for the other months
    // ...
    case default:
        // should probably do something about invalid monthNum
}

The two method are easily combined by

bool validateDate(int monthNum, int dayNum) {
    return validateMonth(monthNum) && validateDay(dayNum);
}

This isn't a drastic change to your code (it has almost the same flow), but it's more organized, and a switch handles multiples == checks much more conveniently.

Upvotes: 1

mergeconflict
mergeconflict

Reputation: 8276

boolean validateDate(int monthNum, int dayNum) {
    if (dayNum < 1)
        return false;
    switch (monthNum) {
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12:
        return dayNum <= 31;
    case 4:
    case 6:
    case 9:
    case 11:
        return dayNum <= 30;
    case 2:
        return dayNum <= 28;
    }
    return false;
}

Upvotes: 0

smp7d
smp7d

Reputation: 5032

(simplified conditions for brevity)

if (a){
    validDate=false;
    System.out.println("Invalid Date Entered");
}

else if (b) {
    validDate=false;
    System.out.println("Invalid date entered");
}

else if (c){
    validDate=false;
    System.out.println("Invalid date entered");
}

else if (d) {
    validDate=false;
    System.out.println("Invalid date entered");
}

else {
    validDate=true;
}

can be changed to:

boolean validDate = !(a||b||c||d);

does this help?

Upvotes: 2

Jeremiah Orr
Jeremiah Orr

Reputation: 2630

Instead of writing your own date-checking logic, I suggest looking at java.util.Calendar and using setLenient(false).

Check the JavaDocs at http://docs.oracle.com/javase/6/docs/api/java/util/Calendar.html#setLenient(boolean)

Upvotes: 0

Related Questions