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
+ }