Java開發筆記(四十一)日曆工具Calendar
前面的文章提到,Date是Java最早的日期工具,估計當時的設計師是個技術宅男,未經過充分調研就拍腦袋寫下了Date的原始碼,造成該工具存在先天不足,比如getYear方法返回的不是純正的公元紀年、getHours方法無法區分12小時制和24小時制等等,這很不利於Java語言的國際化。故而從JDK1.1開始,Java又提供了一個日曆工具Calendar,官方建議採用Calendar替代Date,並且Date的相關get方法都被標記為Deprecated(意思是已廢棄)。接下來就來看看這個全新的Calendar該當如何使用。
首先,建立日曆例項呼叫的是getInstance方法,而非new關鍵字,日曆例項的獲取程式碼如下所示:
// 建立一個日曆例項 Calendar calendar = Calendar.getInstance();
其次,呼叫日曆例項的get方法,獲得指定時間單位的具體數值,例如型別Calendar.YEAR對應的是公元年份,型別Calendar.MONTH對應的是月份序號等等,以年份為例,具體的獲取程式碼如下所示:
// 獲取日曆例項中的年份 int year = calendar.get(Calendar.YEAR); System.out.println("year="+year);
從以上程式碼可見,此時得到的年份數值無需額外加上1900,果然比Date省事多了。不過通過Calendar獲取其它時間單位仍有兩點需要注意:
1、Calendar的月份依然從0開始計數,也就是說,日曆工具獲取的一月份數值為0,十二月份的數值為11,於是獲取月份的程式碼需要記得加一:
// 獲取日曆例項中的月份 int month = calendar.get(Calendar.MONTH)+1; System.out.println("month="+month);
2、原來Date的星期幾從0開始計數,現在Calendar的星期幾改為從1開始計數,可謂一大進步,不料它的星期仍舊以星期日打頭、以星期六結尾。也就是說,日曆工具獲取的星期日數值為1,星期一數值為2,這樣一來只好由程式設計師手工調整,按照國人習慣把星期一對應的數值改為1、把星期日對應的數值改為7等等。修改後的星期獲取程式碼示例如下:
// 獲取日曆例項中的星期幾 int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); dayOfWeek = dayOfWeek==1 ? 7 : dayOfWeek-1; System.out.println("dayOfWeek="+dayOfWeek);
其它的時間單位中規中矩,無需額外的處理,與Date相比,Calendar新增了型別Calendar.DAY_OF_YEAR(從年初開始數的日子),以及Calendar.MILLISECOND(秒鐘後面的毫秒),另外把時鐘區分為Calendar.HOUR(十二小時制的時鐘數值)和Calendar.HOUR_OF_DAY(二十四小時制的時鐘數值)兩種型別。這些普通時間單位的獲取程式碼如下所示:
// 獲取日曆例項中的日子 int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); System.out.println("dayOfMonth="+dayOfMonth); // 獲取日曆例項中從年初開始數的日子 int dayOfYear = calendar.get(Calendar.DAY_OF_YEAR); System.out.println("dayOfYear="+dayOfYear); // 獲取日曆例項中的時鐘(12小時制) int hour = calendar.get(Calendar.HOUR); System.out.println("hour="+hour); // 獲取日曆例項中的時鐘(24小時制) int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY); System.out.println("hourOfDay="+hourOfDay); // 獲取日曆例項中的分鐘 int minute = calendar.get(Calendar.MINUTE); System.out.println("minute="+minute); // 獲取日曆例項中的秒鐘 int second = calendar.get(Calendar.SECOND); System.out.println("second="+second); // 獲取日曆例項中的毫秒 int milliSecond = calendar.get(Calendar.MILLISECOND); System.out.println("milliSecond="+milliSecond);
再次,Calendar提供了set方法用於設定時間數值,並且過載了引數個數不同的多種set方法,其中帶三個引數的set方法支援同時設定年月日,帶六個引數的set方法支援同時設定年月日、時分秒。這兩種set方法的呼叫程式碼示例如下:
Calendar calendar = Calendar.getInstance(); // 呼叫帶三個引數的set方法同時設定日曆例項的年、月、日 calendar.set(2018, 11, 27); // 呼叫帶六個引數的set方法同時設定日曆例項的年、月、日、時、分、秒 calendar.set(2018, 11, 27, 12, 30, 40);
如果只想修改某個時間單位,則可呼叫帶兩個引數的set方法,第一個引數為單位型別包括Calendar.YEAR、Calendar.MONTH等等,第二個引數為具體的時間數值。比如以下的程式碼表示把某個日期改為當月1號:
// 帶兩個引數的set方法允許把某個時間單位改為指定數值 calendar.set(Calendar.DAY_OF_MONTH, 1); System.out.println("end set dayOfMonth="+calendar.get(Calendar.DAY_OF_MONTH));
注意到以上程式碼設定的日期是絕對值,有時候可能需要在當前日期上增增減減,也就是設定日期的相對值,此時可以聯合使用get和set方法,先通過get方法獲得當前的時間數值,對當前數值增減之後再傳給set方法。下面的程式碼便演示了設定時間相對值的實現過程:
// 聯合使用get和set方法,可對某個時間單位進行增減 int dayResult = calendar.get(Calendar.HOUR_OF_DAY) + 1; // 給當前日期加上一天 calendar.set(Calendar.HOUR_OF_DAY, dayResult); System.out.println("end set hourOfDay="+calendar.get(Calendar.HOUR_OF_DAY));
聯合使用get和set方法固然實現了相對時間的修改,可是簡簡單單的功能還得兩個步驟稍顯繁瑣,因此Calendar另外提供了add方法,利用add方法允許直接設定相對數值,就像下列程式碼示範的那樣:
// 呼叫add方法,直接在當前時間的基礎上增加若干數值 calendar.add(Calendar.MINUTE, 10); // 給當前時間加上10分鐘 System.out.println("end add minute="+calendar.get(Calendar.MINUTE));
日曆工具Calendar就像它的前輩Date一樣,仍然保留了與時間校驗相關的幾個方法,包括equals、before、after、compareTo方法等,並且它們的用法與Date型別的同名方法保持一致,這裡不再贅述,還是直接看下面的時間比較程式碼好了:
// 比較兩個日曆時間的先後關係 private static void compareCalendar() { Calendar calendarOld = Calendar.getInstance(); Calendar calendarNew = Calendar.getInstance(); // 給calendarNew加上一秒 calendarNew.add(Calendar.SECOND, 1); // 比較兩個時間是否相等 boolean equals = calendarOld.equals(calendarNew); System.out.println("equals="+equals); // 比較A時間是否在B時間之前 boolean before = calendarOld.before(calendarNew); System.out.println("before="+before); // 比較A時間是否在B時間之後 boolean after = calendarOld.after(calendarNew); System.out.println("after="+after); // 比較A時間與B時間的先後關係。返回-1表示A時間較早,返回0表示兩個時間相等,返回1表示B時間較早 int compareResult = calendarOld.compareTo(calendarNew); System.out.println("compareResult="+compareResult); }
更多Java技術文章參見《Java開發筆記(序)章節目錄》