Reputation: 45
Can anyone suggest an example on how to handle invalid inputs, I have got the logic wrong for input from the keyboard. So, I need !myScanner.hasNextInt()
or to put that loop in a method which I can reuse for ever.
package dayoftheyear;
import java.util.Scanner;
/**
*
* @author abdal
*/
public class DayOfTheYear {
/**
* Ask the user to enter a month, day, and year as integers
* separated by spaces then display the number of the days since the
* beginning of the year.
* Don’t forget about leap year.
* Sample: user inputs ‘3 1 2000’, output is ‘61’.
* @param args Unused.
*/
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String enter = "A-z";
int a=31;
int b=1;
boolean dateCheck;
int month;
int day;
int year;
do {
System.out.print("Enter a valid month day year separated by spaces");
if (s.hasNextInt()) {
month= s.nextInt();
day=s.nextInt();
year=s.nextInt();
if (month >= b && month <= a || day>=b && day<=a || year>=b) {
int numberOfDay = countDays(month, day, year);
System.out.println(+ month + "/" + day + "/" + year + " is a day number "
+ numberOfDay + " of that year");
dateCheck = true;
} else {
System.out.println("Enter a valid month day year separated by spaces");
dateCheck = false;
}
} else {
System.out.println("Not a date");
month = 0;
day=0;
year=0;
s.next();
dateCheck = false;
}
} while (!dateCheck);
/**
* Get the number of days since the start of the year.
* Declare a 12 element array and initialize it with the number of
* days in each month.
* @param month Month to count from.
* @param day Day of the month to count to.
* @param year The year to count from.
* @return Days since the start of the given year.
*/
} public static int countDays(int month, int day, int year) {
int monthLength[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int days = 0;
if (isLeapYear(year) && month > 2)
days += 1;
for (int i = 0; i < month - 1; i++)
days += monthLength[i];
return days += day;
}
/**
* Check if a year is a leap year.
* @param year Year to check.
* @return True if the year is a leap year.
*/
public static boolean isLeapYear(int year) {
if (year % 4 != 0) return false;
else if (year % 100 != 0) return true;
else return year % 400 == 0;
}
}
Upvotes: 1
Views: 430
Reputation: 79095
Replace
if (month >= b && month <= a || day>=b && day<=a || year>=b)
with
if (month >= 1 && month <= 12 && day >= 1 && day <= 31 && year >= 1)
A sample run after this change:
Enter a valid month day year separated by spaces: 13 1 2000
Enter a valid month day year separated by spaces
Enter a valid month day year separated by spaces: 3 32 2000
Enter a valid month day year separated by spaces
Enter a valid month day year separated by spaces: 3 1 2
3/1/2 is a day number 60 of that year
Update1: the following condition will hold good also for February
if ((month == 2 && day >= 1 && day <= 28 && year >= 1 && !isLeapYear(year))
|| (month == 2 && day >= 1 && day <= 29 && year >= 1 && isLeapYear(year))
|| (month != 2 && month >= 1 && month <= 12 && day >= 1 && day <= 31 && year >= 1))
A sample run:
Enter a valid month day year separated by spaces: 2 29 2001
Enter a valid month day year separated by spaces
Enter a valid month day year separated by spaces: 13 2 2001
Enter a valid month day year separated by spaces
Enter a valid month day year separated by spaces: 1 32 2001
Enter a valid month day year separated by spaces
Enter a valid month day year separated by spaces: 1 2 3
1/2/3 is a day number 2 of that year
Update2: the following code addresses all the issues raised in the comments
int monthLength[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if ((month == 2 && day >= 1 && day <= 28 && year >= 1 && !isLeapYear(year))
|| (month == 2 && day >= 1 && day <= 29 && year >= 1 && isLeapYear(year))
|| (month != 2 && month >= 1 && month <= 12 && day >= 1 && day <= monthLength[month-1] && year >= 1))
A sample run:
Enter a valid month day year separated by spaces: 2 29 2001
Enter a valid month day year separated by spaces
Enter a valid month day year separated by spaces: 13 2 2001
Enter a valid month day year separated by spaces
Enter a valid month day year separated by spaces: 1 32 2001
Enter a valid month day year separated by spaces
Enter a valid month day year separated by spaces: 6 31 2020
Enter a valid month day year separated by spaces
Enter a valid month day year separated by spaces: 7 31 2020
7/31/2020 is a day number 213 of that year
Upvotes: 2
Reputation: 568
You can add edge cases forever. There is a reason why time-related calculations are nightmare outsourced to libraries written by some poor souls that are paid to try to cover them all. Java has such built in, take a look at java.util.Calendar (Gregorian implementation). You set it to year/month/day, and it will puke out an exception if anything is wrong while trying to get the result.
Calendar c = Calendar.getInstance();
c.set(year, month, day);
try {
c.getTime();
} catch (Exception e) {
// wrong date format
}
Upvotes: 1
Reputation: 45
thanks I updated my program and it is working;
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int year = 0;
int month = 0;
int day = 0;
boolean dateCheck;
do {
System.out.print("Enter a valid month day year separated by spaces\n");
if (s.hasNextInt()) month = s.nextInt();
else s.next();
if (s.hasNextInt()) day = s.nextInt();
else s.next();
if (s.hasNextInt()) year = s.nextInt();
else s.next();
int numberOfDaysSinceStart = 0;
if (month >= 1 && month <= 12 && day >= 1 && day <= 31 && year >= 1) {
dateCheck = true;
numberOfDaysSinceStart = countDays(month, day, year);
System.out.println(month + "/" + day + "/" + year + " is a day number "
+ numberOfDaysSinceStart + " of that year");
} else {
dateCheck = false;
}
} while (!dateCheck);
/**
* Get the number of days since the start of the year.
* Declare a 12 element array and initialize it with the number of
* days in each month.
* @param month Month to count from.
* @param day Day of the month to count to.
* @param year The year to count from.
* @return Days since the start of the given year.
*/
} public static int countDays(int month, int day, int year) {
int monthLength[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int days = 0;
if (isLeapYear(year) && month > 2)
days += 1;
for (int i = 0; i < month - 1; i++)
days += monthLength[i];
return days += day;
}
/**
* Check if a year is a leap year.
* @param year Year to check.
* @return True if the year is a leap year.
*/
public static boolean isLeapYear(int year) {
if (year % 4 != 0) return false;
else if (year % 100 != 0) return true;
else return year % 400 == 0;
}
}
Upvotes: 0
Reputation: 129
I think the code below can help you, comment if you have any questions.
while(true) {
try{
System.out.print("Enter a valid month day year separated by spaces");
month= s.nextInt();
day=s.nextInt();
year=s.nextInt();
if (month >= 1 && month <= 12 || day>=1 && day<=31 || year>=1) {
System.out.println(+ month + "/" + day + "/" + year + " is a day number "+ " of that year");
break;
} else {
System.out.println("Enter a valid month day year separated by spaces");
}
} catch(InputMismatchException e) {
System.out.println("Enter a valid month day year separated by spaces");
}
s.next();
}
Upvotes: 0
Reputation: 924
Since date format is not subject to change in real world, it should be appropriate to use some hard coding. Dividing the problem into several methods is always recommended.
You could add following methods to your class:
private static boolean validDate(int month, int day, int year) {
if (year < 1) {
return false; // no B.C.
}
if (month > 1 && month < 13) {
if (month == 2) { // handle February
return validFeb(day, year);
} else if (month % 2 == 1 && month < 8
|| month % 2 == 0 && month >= 8) { // 31-day months
return valid31(day);
} else { // 30 day months
return valid30(day);
}
}
return false;
}
Validate 30-day months:
private static boolean valid30(int day) {
if (day > 1 && day < 31) {
return true;
}
return false;
}
Validate 31-day months
private static boolean valid31(int day) {
if (day > 1 && day < 32) {
return true;
}
return false;
}
Validate February
private static boolean validFeb(int day, int year) {
if (isLeapYear(year)) {
if (day > 1 && day < 30) {
return true;
}
} else {
if (day > 1 && day < 29) {
return true;
}
}
return false;
}
Then your do-while loop should look something like so:
do {
System.out.print("Enter a valid month day year separated by spaces\n");
if (s.hasNextInt()) month = s.nextInt();
else s.next();
if (s.hasNextInt()) day = s.nextInt();
else s.next();
if (s.hasNextInt()) year = s.nextInt();
else s.next();
int numberOfDaysSinceStart = 0;
if (validDate(month, day, year)) {
dateCheck = true;
numberOfDaysSinceStart = countDays(month, day, year);
System.out.println(month + "/" + day + "/" + year + " is a day number "
+ numberOfDaysSinceStart + " of that year");
} else {
dateCheck = false;
}
} while (!dateCheck);
Upvotes: 1