A friend of mine was practicing his programming skills with a textbook meant to prepare students for computer science exams. He asked for help with a specific task.
The task is to capture user input (day of week and a year in the range 1500 to 2005 inclusive), and output all instances of the weekday in February that year.
The differences between the Julian and Gregorian calendars are to be accounted for.
Now, most likely the idea behind this task was to have the student create an algorithm to manually calculate the dates. However, as Java SE seems to be allowed in exams in my country, I came up with the idea of utilizing the GregorianCalendar
class (which, despite its name, combines the Julian and Gregorian calendars).
package calendar;
import java.text.DateFormat;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Scanner;
public class CalendarTask {
public static void main(String[] args) {
GregorianCalendar cal = new GregorianCalendar();
HashMap<String, Integer> daysOfWeek = new HashMap<>();
daysOfWeek.put("monday", cal.MONDAY);
daysOfWeek.put("tuesday", cal.TUESDAY);
daysOfWeek.put("wednesday", cal.WEDNESDAY);
daysOfWeek.put("thursday", cal.THURSDAY);
daysOfWeek.put("friday", cal.FRIDAY);
daysOfWeek.put("saturday", cal.SATURDAY);
daysOfWeek.put("sunday", cal.SUNDAY);
System.out.print("Enter day of week: ");
Scanner sc = new Scanner(System.in);
int dayOfWeek, year;
try {
dayOfWeek = daysOfWeek.get(sc.next().toLowerCase());
System.out.print("Enter year (1500-2005 inclusive): ");
year = Integer.parseInt(sc.next());
if (year < 1500 || year > 2005) throw new Exception();
System.out.println("Output:");
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.GERMANY);
cal.set(cal.YEAR, year);
trySetDay(cal, dayOfWeek, 1);
do {
System.out.println(df.format(cal.getTime()));
cal.add(cal.DAY_OF_MONTH, 7);
} while (cal.get(cal.MONTH) == cal.FEBRUARY);
} catch (Exception e) {
System.out.println("Incorrect input!");
} finally {
sc.close();
}
}
private static void trySetDay(GregorianCalendar cal, int dayOfWeek, int weekOffset) {
cal.set(cal.MONTH, cal.FEBRUARY);
cal.set(cal.WEEK_OF_MONTH, weekOffset);
cal.set(cal.DAY_OF_WEEK, dayOfWeek);
if (cal.get(cal.MONTH) != cal.FEBRUARY) trySetDay(cal, dayOfWeek, weekOffset + 1);
}
}
Example input and output (dates are output in DD.MM.YYYY
format):
Enter day of week: Monday Enter year (1500-2005 inclusive): 2000 Output: 07.02.2000 14.02.2000 21.02.2000 28.02.2000
The trySetDay()
method is meant for cases when the attempted day belongs to the previous month. In such a case, the week offset is increased by one to make sure we're dealing with February.
This code works fine and I'm satisfied with it. The catch
is there to handle NullPointerException
(when attempting to assign null
, a possible result of HashMap.get()
, and also when parsing the year) and a generic Exception
set to limit the possible input to the range 1500 to 2005.
What can be improved about this code? Is there anything that caught your eye instantly and that could be done better? Any and all feedback is appreciated.
Also, is it a good idea to access static class members via an instance of the class? Such as cal.MONDAY
(where cal
is an instance of GregorianCalendar
), instead of GregorianCalendar.MONDAY
?