這是文字版範例, 可以一列排三個月(類似 Unix 的 cal 命令),
也可以一個月一個月列印(比較簡單:-)
01 //Cal999.java //萬年曆的程式 @CopyLeft by tsaiwn@csie.nctu.edu.tw
02 //Note that the Sep. 1752 has ONLY 19 days according to USA/England
03 //See "cal" and "ncal" commands on Unix system
04 //javac Cal999.java
05 //java Cal999 3
06 import java.io.*;
07 import java.util.*;
08 public class Cal999 { // USA/England 1752/09/02 next 09/14
09 public static final int ggYear = 1752;
10 public static final int ggMonth = 9;
11 public static final int ggDay = 14; // 1752/9/14 0:0:0
12 public static final int ggChange = 4; // 4-th day in that week
13 public static final int skipDays = 11; // 10 if ggYear <=1699; 1582
14 static BufferedReader cin = null;
15 static PrintStream cout = null;
16 static GregorianCalendar ccc = new GregorianCalendar( );
17 static int days[ ] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
18 static int cols = 1;
19 public Cal999( ) { }
20 public static void main(String[ ] args) throws IOException {
21 Cal999 gg = new Cal999( );
22 if(args.length >= 1) gg.cols = 3; // 3 columns for year cal
23 gg.prepareIO( );
24 gg.main( );
25 }
26 void prepareIO( ) throws IOException {
27 cout = System.out;
28 cin = new BufferedReader(new InputStreamReader(System.in));
29 }
30 Cal999(BufferedReader in, PrintStream out) { // for network version
31 cout = out; cin = in;
32 }
33 void start( ) { try { main( ); }catch(Exception e) {;} }
34 static int whichDay = 0; // 用來存輸入的 "日", if any
35 int main( ) throws IOException {
36 String str = null;
37 cout.println("\t === 歡迎使用 萬 年 曆 ===\r");
38 Date now = new Date( ); // get current date/time
39 int nowYY = now.getYear( ) + 1900; // A.D.
40 int nowMM = now.getMonth( ) + 1; // 0..11 ==> 1..12
41 cout.println( showCal(nowMM, nowYY) ); // current Month
42 int tmp = getMY( ); // get Month + Year *100
43 // day will be put in the global variable whichDay if any
44 while(tmp != -1) { // 注意傳回的值是 年 *100 + 月
45 int mm = tmp % 100; // month
46 int yy = tmp / 100; // year
47 if(mm == 0) processYear( yy ); // 月是 0 表示要整年
48 else if(whichDay !=0) processDay(mm, whichDay, yy); //日
49 else if(mm >= 1 && mm <= 12) processMonth(mm, yy); // 月
50 else {
51 cout.print( "\n"+"********************************"+"\n");
52 cout.println("Error Input 輸入 Month 錯誤!");
53 } whichDay = mm = 0; // clear day
54 tmp = getMY( ); // read Day Month Year , again
55 } // while
56 cout.println("GregorianChange = " + ccc.getGregorianChange( ) );
57 return 0;
58 }// int main(
59
60 static void adjustDay(GregorianCalendar g) { // A.D.1700年是否為閏年 ?
61 // 1752/09/02 Wednesday --> next day --> 1752/09/14 Thursday
62 //GregorianChange: 1582/10/04 next 10/15; USA: 1752/09/02 next 09/14
63 if(ggYear <= 1582) return; // do NOT adjust, use Default Gregorian
64 g.setGregorianChange(new Date(ggYear-1900, ggMonth-1, ggDay, 0, 0, 0));
65 }
66 static boolean isLeap(int yyyy) { // return true if yyyy is Leap year
67 GregorianCalendar gCal = new GregorianCalendar( );
68 adjustDay(gCal); // USA/England calendar; 不然是用羅馬? 1582/10/15
69 if(38==38)return gCal.isLeapYear(yyyy); // 用程式庫的
70 ////// or use my own algorithm :
71 if (yyyy%400 == 0) return true;
72 if(yyyy >= ggYear) { // 1752/09 for USA/England? 1582/10 for Italy?
73 if ( (yyyy%4 == 0) && (yyyy%100 != 0) ) return true;
74 }else{ // before 1752 in USA/England
75 if (yyyy % 4 == 0) return true;
76 }
77 return false;
78 }// isLeap(
79 //////
80 static int getMY( ) { // get " MM DD YYYY " from User
81 int ans=0, m=0, d=0, y=-1; // mm dd yyyy
82 cout.print("\r\n 請輸入 年 或是 月 年 或 月 日 年( -1 結束): ");
83 whichDay = 0; // clear the day in global variable
84 try{
85 String s = cin.readLine( ); if(s == null) s = "-1";
86 StringTokenizer stk = new StringTokenizer(s, " ,\t");
87 try{ // assume Year ONLY
88 m = 0;
89 if(stk.hasMoreTokens( )) y = Integer.parseInt(stk.nextToken( ));
90 }catch(Exception e) {;}
91 if(stk.hasMoreTokens( )) { // assume Month Year
92 try{
93 m = y; // Month Year
94 y = Integer.parseInt(stk.nextToken( ));
95 }catch(Exception e) { y = -1;}
96 }
97 if(stk.hasMoreTokens( )) { // is "MM DD YYYY"
98 d = y; y=2010; // 剛才的 y 應該是 d (日)
99 try{
100 y = Integer.parseInt(stk.nextToken( ));
101 }catch(Exception e) { y = -1;}
102 whichDay = d; // put day in global variable
103 }// mm, dd, yyyy
104 }catch(Exception e) {;;}
105 if(m == -1 || y == -1) return -1;
106 if(m > 12) m = m%100; // month should be in 1..12 ; 防呆?
107 ans = y*100 + m ; // year* 100 + m
108 return ans;
109 }// getMY(
110 //////
111 static int processYear(int y) throws IOException {
112 if(y <= 0) return 0;
113 cout.println(showCal(y));
114 return 0;
115 } //
116 static int processMonth(int m, int y) throws IOException {
117 if(y == 0) return 0;
118 cout.println(showCal(m, y).replace(" _", " ") );
119 return 0;
120 } //int processMonth(
121 static int processDay(int m, int d, int y) throws IOException {
122 String dn[ ]={"Sunday", "Monday", "Tuesday", "Wednesday",
123 "Thursday", "Friday", "Saturday" };
124 adjustDay(ccc); // according to USA/England
125 ccc.set(y, m-1, d); // 設定日期再查出星期幾; 不然自己算也可
126 int today = ccc.get(Calendar.DAY_OF_WEEK)-1; // 0..6:Sun..Sat
127 cout.printf("%d/%02d/%02d is %s\n", y, m, d, dn[today]);
128 return 0;
129 /// A.D.01/01/01 Saturday; 1752/09/14 Thursday前一日是 1752/09/02
130 }// int processDay(
131
132 public static String showCal(int mon, int yyyy){
133 int beginDay=1,lostdat=0;
134 String msg="\r";
135 if (mon==2 && isLeap(yyyy)) days[1] = 29; else days[1] = 28; // Feburary
136 ///
137 adjustDay(ccc); // according to USA/England
138 ccc.set(yyyy, mon-1, 1);
139 msg += "\r\n" + " \t\t\t" + yyyy + " 年 " + mon + " 月" + ".\t.\t.\t\r\n";
140 msg += "日 \t一 \t二 \t三 \t四 \t五 \t六 \n\r";
141 //////
142 int firstDay = ccc.get(Calendar.DAY_OF_WEEK)-1; // 0..6:Sun..Sat
143 if ( (firstDay+days[mon-1])%7 != 0) lostdat = 1;
144 int weeks = (firstDay +days[mon-1])/7+lostdat ;
145 if(yyyy== ggYear && mon==ggMonth) weeks=3; // 19 days ONLY in Sep. 1752
146 for(int i = 1;i<= weeks ;i++) {
147 for(int j = 1;j<=7;j++) { // 7 days a week; Sun, Mon, .. Sat
148 if(beginDay <= firstDay || beginDay > days[mon-1] + firstDay)
149 msg+=" _ \t";
150 else { int dd = beginDay - firstDay ;
151 if(dd <= 9) msg += " "; // Align Right
152 msg += dd +" \t";
153 }// one day OK
154 // check to see if it is in special month ? and is adjust day?
155 if(yyyy==ggYear && mon== ggMonth)
156 if(beginDay == ggChange) beginDay += skipDays; // adjust
157 beginDay++; // advance one day
158 }// for j
159 msg+="\r\n"; // next week on next Line
160 }// for i
161 if(weeks<=5) msg+= " _ \t _ \t _ \t _ \t _ \t _ \t _ \t\r\n";
162 return msg;
163 }// showCal(int mon, int yyyy
164
165 public static String showCal(int yyyy) {
166 String yearMessage="";
167 if(cols == 1) { // one month in a Row
168 for(int mm=1;mm<=12; mm++) {
169 String msg = showCal(mm, yyyy); // month, year
170 yearMessage += msg; // concatenate together
171 }
172 }else{ // 3 columns; 3 months in a row
173 String msga="", msgb="", msgc="";
174 StringTokenizer a, b, c;
175 for(int mm=1;mm<=12; mm=mm+3) {
176 msga = showCal(mm, yyyy); // month, year
177 msgb = showCal(mm+1, yyyy); // month, year
178 msgc = showCal(mm+2, yyyy); // month, year
179 a = new StringTokenizer(msga, "\r\n");
180 b = new StringTokenizer(msgb, "\r\n");
181 c = new StringTokenizer(msgc, "\r\n");
182 while(a.hasMoreTokens( ) || b.hasMoreTokens( ) ||
183 c.hasMoreTokens( ) ) {
184 try{
185 yearMessage += a.nextToken( ); // concatenate together
186 }catch(Exception e){;}
187 yearMessage += " ";
188 try{
189 yearMessage += b.nextToken( ); // concatenate together
190 }catch(Exception e){;}
191 yearMessage += " ";
192 try{
193 yearMessage += c.nextToken( ); // concatenate together
194 }catch(Exception e){;}
195 yearMessage += "\r\n";
196 }//while
197 }//for
198 }
199 yearMessage = yearMessage.replace("\t", " ");
200 yearMessage = yearMessage.replace(" ", " ");
201 yearMessage = yearMessage.replace(" _", " ");
202 return yearMessage;
203 }// showCal for one year
204 }//class Cal999
205
|