Assignment 14

Task

Write a program that asks the user for the month and day of the month and then uses an array to calculate what day of the year it is.

Concepts: Arrays
Textbook: 7.1 - 7.2

Steps

First, declare one array that list the months of the year and another array of the same size that stores the number of days in each of those months. For example:

  String[] months = {"January", "February", "March", "April",
                     "May", "June", "July", "August",
                     "September", "October", "November", "December"};
  int[] daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

(You may give your arrays different variable names if you want to, but I will use these names in describing the problem below.)

Then ask the user to enter a month as an int. This number should be between 1 and the number of entries in the months array. (If the input is invalid, you may gracefully end the program here.)

Next, ask the user for the day of the month. This number should between 1 and the number of days in the month they specified. (Again, you may end now on invalid input.)

If the input is all valid, now print the date in the form of: day month (for example, 1 January, 13 March, etc.) Then, using the data in the arrays, determine and print what day of the year that date corresponds to.

Sample Output

D:\TA\grading\A14>java ZtomaszeA14
This program converts a date to the day of the year.
Enter the month (as an int): March
You must enter the month as a number: 1 for January, 2 for February, etc.
Please try again.

D:\TA\grading\A14>java ZtomaszeA14
This program converts a date to the day of the year.
Enter the month (as an int): 13
Sorry, but the month must be a value between 1 and 12.
Please try again.

D:\TA\grading\A14>java ZtomaszeA14
This program converts a date to the day of the year.
Enter the month (as an int): 2
Enter the day of the month: 29
Sorry, but the day must be a value between 1 and 28.
Please try again.

D:\TA\grading\A14>java ZtomaszeA14
This program converts a date to the day of the year.
Enter the month (as an int): 1
Enter the day of the month: 31
31 January = Day 31 of the year.

D:\TA\grading\A14>java ZtomaszeA14
This program converts a date to the day of the year.
Enter the month (as an int): 3
Enter the day of the month: 1
1 March = Day 60 of the year.

D:\TA\grading\A14>java ZtomaszeA14
This program converts a date to the day of the year.
Enter the month (as an int): 10
Enter the day of the month: 18
18 October = Day 291 of the year.

Rationale

For all bounds checking, you should use the arrays only. So, for example, the word "January" and the numbers 12 or 31 won't appear anywhere in your code except as data within the array. This includes the content of any error messages you print. In other words, except for the values in the daysInMonth array initializer, you should not need any other literal numbers in your code except 0 and 1 (unless you're doing the "st/nd/th" extra credit below, in which case you'll need a few more).

The reason for this is that it makes your program data-driven. You could switch calendars--such as to the Islamic, Chinese, ancient Roman, astrological, etc--by redefining only your arrays. Note that different calendars may not always have 12 months. Despite these differences, you should not have to touch the rest of your code. This will be even more valuable when, later in the semester, we learn how to read data from a file--you could then update your program to load different calendars and still function correctly.

For example, here's an interesting calendar where each "month" is the season:

  String[] months = {"winter", "spring", "summer", "autumn"};
  int[] daysInMonth = {89, 93, 93, 90};

If you only replaced your arrays with these, everything should still work correctly. (Submit the original 12 month calendar though!)

Extra Credit

+0.5: Don't end on bad input, but loop until the user gets that particular input request correct.

+0.5: When printing the day of the year, use the appropriate suffix label, as in 3rd, 11th, 13th, 22nd, 112th, 252nd, etc. (You can do this on the date too, but it won't gain you more extra credit.)

Below is some sample output with these changes made:

D:\TA\grading\A14>java ZtomaszeA14ec
This program converts a date to the day of the year.
Enter the month (as an int): july
You must enter the month as a number: 1 for January, 2 for February, etc
Please try again.
Enter the month (as an int): 17
Sorry, but the month must be a value between 1 and 12.
Please try again.
Enter the month (as an int): 7
Enter the day of the month: 32
Sorry, but the day must be a value between 1 and 31.
Please try again.
Enter the day of the month: thirty one
You must enter the day as a number.
Please try again.
Enter the day of the month: 30
30 July = 211th day of the year.

D:\TA\grading\A14>java ZtomaszeA14ec
This program converts a date to the day of the year.
Enter the month (as an int): 1
Enter the day of the month: 1
1 January = 1st day of the year.

D:\TA\grading\A14>java ZtomaszeA14ec
This program converts a date to the day of the year.
Enter the month (as an int): 4
Enter the day of the month: 4
4 April = 94th day of the year.

D:\TA\grading\A14>java ZtomaszeA14ec
This program converts a date to the day of the year.
Enter the month (as an int): 4
Enter the day of the month: 3
3 April = 93rd day of the year.

What to Submit

Upload your UsernameA14.java file to Tamarin.

Grading [5 points]

1 - Compiles + Coding Standards
Your program compiles successfully (no errors). Your code follows Java coding standards.
1 - Uses two arrays
You use an array of Strings to determine the name of the month and an array of ints to determine the number of days in each month (0.5). You use .length and data retrieved from the arrays in your code's tests and error messages instead of literals (like 12 or 30) (0.5).
1.5 - Asks user for month and then day
You ask the user for the month and then the day as numbers (0.5). The program gracefully handles bad input, including strings or numbers out of range (1.0).
1.5 - Prints date and day of year
Prints the date in day month format, where month is the name of the month (0.5). Prints the correct day of the year for the inputted date (1.0).
+1 - Extra Credit
Loops on the same input request until the user enters valid input (number, in range) (+0.5). Prints out the properly labelled day of the year (st, nd, rd, or th; remember the teens are th numbers.)

FAQs

How do I compute the day of the year?
Pick an example date (such as 4/4) and then trace through how you'd compute the result manually yourself.

For example, to compute what day of the year 04 April is, I'd go through each month before April, totaling the days. So the number of days in Jan + days in Feb + days in Mar. (What single programming structure could you use to get this behavior for a date in any given month?) And then there's a few extra days more to add at the end.

Like I said, try it on paper two or three times to map out the process you're going through. Pick some dates in the second half of the year so you can easily see the pattern of what you're doing. Once you have a very clear idea of the process (algorithm), it will be much easier to translate the process into code.

I'm trying the "loop on bad input" extra credit. I'm catching the exception from String input, but it just results in an infinite loop!
When the Scanner fails to parse a token, it leaves that token in the input stream buffer in case you want to try something different with it. So when you prompt the user for a number again, it just chokes on the same string all over again. To fix this, you need to clear out the input stream buffer by calling the nextLine() method on your Scanner in the catch block. (You don't need to assign the returned String to anything--it's just "garbage".)