1+ import java .util .Scanner ;
2+
3+ /*
4+ Adapted by Sleekpanther from SquirrelCoder's initial idea from 29-Jan-17.
5+ Uses arrays, even though they technically aren't introduced until chapter 7. But it simplifies this a lot
6+
7+ 6.34 (Print calendar) Programming Exercise 3.21 uses Zeller's congruence to calculate
8+ the day of the week. Simplify Listing 6.12, PrintCalendar.java, using Zeller's
9+ algorithm to get the start day of the month.
10+
11+
12+ Exercise 3.21 details
13+ (Science: day of the week) Zeller's congruence is an algorithm developed by
14+ Christian Zeller to calculate the day of the week. The formula is:
15+ h=(q + (26(m+1))/10 + k + k/4 + j/4 +5*j)%7
16+ h is the day of the week (0: Saturday, 1: Sunday, 2: Monday, 3: Tuesday, 4: Wednesday, 5: Thursday, 6: Friday).
17+ q is the day of the month.
18+ m is the month (3: March, 4: April, ..., 12: December). January and February are counted as months 13 and 14 of the previous year.
19+ j is the century (i.e. year/100)
20+ k is the year of the century (i.e., year % 100).
21+
22+ Note that the division in the formula performs an integer division. Write a program
23+ that prompts the user to enter a year, month, and day of the month, and
24+ displays the name of the day of the week.
25+ (Hint: January and February are counted as 13 and 14 in the formula, so you need
26+ to convert the user input 1 to 13 and 2 to 14 for the month and change the year to the previous year.)
27+ */
28+ public class PrintCalendar {
29+ public static void main (String [] args ) {
30+ Scanner keyboard = new Scanner (System .in );
31+
32+ // get & validate user year
33+ System .out .print ("Enter full year (e.g., 2012): " );
34+ int year = keyboard .nextInt ();
35+ while (!isValidYear (year )) { //validate input
36+ System .out .println ("Invalid Year!" );
37+ System .out .print ("Enter full year (e.g., 2012): " );
38+ year = keyboard .nextInt ();
39+ }
40+
41+ // get & validate user month
42+ System .out .print ("Enter month as number between 1 and 12: " );
43+ int month = keyboard .nextInt ();
44+ while (!isValidMonth (month )) { //validate input
45+ System .out .println ("Invalid Month!" );
46+ System .out .print ("Enter month as number between 1 and 12: " );
47+ month = keyboard .nextInt ();
48+ }
49+
50+
51+ printCalendarHeader (month , year ); // print the calendar header
52+
53+ printFirstDay (month , year ); // print the calendar first day
54+
55+ printCalendarItself (month , year ); // print the calendar itself
56+ }
57+
58+ public static boolean isValidYear (int year ) {
59+ return year > 0 ; //might want to check an upper bound, not sure if this formula works for HUGE numbers
60+ }
61+
62+ public static boolean isValidMonth (int month ) {
63+ return month > 0 && month <= 12 ;
64+ }
65+
66+ public static void printCalendarHeader (int month , int year ) {
67+ String [] months = {"January" , "February" , "March" , "April" , "May" , "June" , "July" , "August" , "Septemter" , "October" , "November" , "December" };
68+
69+ System .out .print ("\t \t " +months [month -1 ]+"\t " ); //access the month array with a -1 offset since arrays count from 0
70+ System .out .println (year );
71+ System .out .println ("---------------------------" );
72+
73+ System .out .println ("Sun\t Mon\t Tue\t Wed\t Thu\t Fri\t Sat" );
74+ }
75+
76+ public static void printFirstDay (int month , int year ) {
77+ int firstDay = dayOfWeek (1 , month , year ); //calculate the 1st day
78+
79+ String leadingTabs = "1" ; //Holds any leading tabs to align 1st row of numbers in a calendar. This takes care of firstDay=1
80+
81+ //cases for firstDay between 2 & 6 (adds a "\t" at the beginning of the string each iteration)
82+ //Loop starts from 1 since we want 1 less tab than the value of firstDay (firstDay=1 is 0 tabs, firstDay=2 is 1 tab, firstDay=3 is 2 tabs, firstDay=4 is 3 tabs, firstDay=5 is 4 tabs)
83+ for (int i = 1 ; i <firstDay ; i ++){
84+ leadingTabs = "\t " + leadingTabs ;
85+ }
86+ if (firstDay == 0 ){ //reset it & ignore what the loop did if it's 0. THIS IS A SPECIAL CASE. We want 6 tabs
87+ leadingTabs = "\t \t \t \t \t \t 1" ;
88+ }
89+
90+ System .out .print (leadingTabs + "\t " );
91+ }
92+
93+ public static void printCalendarItself (int month , int year ) {
94+ // find out the last day of that month
95+ // whether it's 28/29/30/31 days
96+ int lastDayOfMonth = lastDayOfMonth (month , year );
97+
98+ // print the calendar itself
99+ for (int i = 2 ; i <= lastDayOfMonth ; i ++) {
100+ int printedDay = dayOfWeek (i , month , year );
101+ if (printedDay == 1 ) {
102+ System .out .println ();
103+ }
104+ System .out .print (i + "\t " );
105+ }
106+ }
107+
108+ //Implement Zeller's Algorithm
109+ public static int dayOfWeek (int dayOfMonth , int month , int year ) {
110+ if (month == 1 || month == 2 ) {
111+ month = month + 12 ;
112+ year --;
113+ }
114+ int q , m , j , k ;
115+ q = dayOfMonth ;
116+ m = month ; //adjusted month (corrected for January & February being 13 & 14 respectively)
117+ j = year /100 ; //century
118+ k = year %100 ; //year of the century
119+ int dayOfTheWeek = (q + (26 *(m +1 ) /10 ) + k + k /4 + j /4 + (5 *j )) % 7 ; //performs integer division where appropriate (like the Algorithms wants)
120+ return dayOfTheWeek ;
121+ }
122+
123+ public static boolean isLeapYear (int year ) {
124+ return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0 );
125+ }
126+
127+ public static int lastDayOfMonth (int month , int year ) {
128+ int lastDayOfMonth ;
129+ if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12 ) {
130+ lastDayOfMonth = 31 ;
131+ } else if (month == 2 ) {
132+ if (isLeapYear (year )) {
133+ lastDayOfMonth = 29 ;
134+ } else {
135+ lastDayOfMonth = 28 ;
136+ }
137+ } else {
138+ lastDayOfMonth = 30 ;
139+ }
140+ return lastDayOfMonth ;
141+ }
142+
143+ }
0 commit comments