Java 使用 Date 類來表示日期和時間, 從 JDK 1.1 開始, Date 類中的大部分方法已經不推薦使用了, 原因是這些方法不能滿足國際化的要求. 取而代之的是使用 Calendar 類來對日期進行操作, 使用 DateFormat 類來對日期格式化.
我將在下一節為大家介紹有關數字和日期格式化的相關知識, 本節主要關注日期操作. 顯然, 為了對日期進行操作, 我們經常需要在 Date 和 Calendar 類之間轉換. 下面是一個簡單的例子.
public static void main(String[] args) throws Exception {// 定義當前日期Date today = new Date();System.out.println("Today is " + today);// 將 Date 轉換為 CalendarCalendar c = Calendar.getInstance();c.setTime(today);// 給該日期加一天c.add(Calendar.DAY_OF_MONTH, 1);// 將 Calendar 轉換為 Date Date tomorrow = c.getTime();System.out.println("Torrow is " + tomorrow);}
大家想想, 通常我們想對日期進行什麼樣的操作呢?
首先我們必須能夠定義一個具體的日期;
有時候我們需要獲得日期的各個組成部分, 如: 年/月/日/時/分/秒等;
有時候我們也需要比較兩個日期的大小;
有時候我們需要計算兩個日期的間隔, 如: 年/月/日/時/分/秒等;
有時候我們需要計算給特定日期加上或減去 n 年/月/日/時/分/秒 後的結果;
還有些時候我們可能要進行時區轉換.
下面我們通過一個具體的例子來看看如何對日期進行操作.
public static void main(String[] args) throws Exception {// 定義一個具體的日期System.out.println("------ 定義一個具體的日期 ------");Calendar c = Calendar.getInstance();c.set(2012, 4, 31, 17, 02, 20); // 2012-05-31 17:02:20System.out.println(c.getTime());System.out.println("\n");// 獲得日期的各個組成部分System.out.println("------ 獲得日期的各個組成部分 ------");System.out.println("年: " + c.get(Calendar.YEAR));System.out.println("月: " + (c.get(Calendar.MONTH) + 1)); // January is 0System.out.println("日: " + c.get(Calendar.DAY_OF_MONTH));System.out.println("時: " + c.get(Calendar.HOUR_OF_DAY));System.out.println("分: " + c.get(Calendar.MINUTE));System.out.println("秒: " + c.get(Calendar.SECOND));System.out.println("星期: " + (c.get(Calendar.DAY_OF_WEEK) - 1)); // Sunday is 1System.out.println("\n");// 比較兩個日期的大小System.out.println("------ 比較兩個日期的大小 ------");Calendar now = Calendar.getInstance();if (now.before(c)) {System.out.println(now.getTime() + " 在 " + c.getTime() + " 之前.");}if (now.after(c)) {System.out.println(now.getTime() + " 在 " + c.getTime() + " 之後.");}if (now.compareTo(c) > 0) {System.out.println(now.getTime() + " 大於 " + c.getTime());}System.out.println("\n");// 計算兩個日期的間隔System.out.println("------ 計算兩個日期的間隔 ------");long dateInterval = Math.abs(c.getTime().getTime() - now.getTime().getTime()) / (1 * 24 * 60 * 60 * 1000);System.out.println(now.getTime() + " 和 " + c.getTime() + " 的時間間隔是 " + dateInterval + " 天.");System.out.println("\n");// 計算給特定日期加上或減去 n 年/月/日/時/分/秒 後的結果System.out.println("------ 計算給特定日期加上或減去 1 年/月/日/時/分/秒 後的結果 ------");c.add(Calendar.YEAR, 1); // 加1年System.out.println("加1年: " + c.getTime());c.add(Calendar.MONTH, 1); // 加1月System.out.println("加1月: " + c.getTime());c.add(Calendar.DAY_OF_MONTH, 1); // 加1日System.out.println("加1日: " + c.getTime());c.add(Calendar.DAY_OF_MONTH, 32); // 加32日System.out.println("加32日: " + c.getTime());c.add(Calendar.HOUR_OF_DAY, 1); // 加1時System.out.println("加1時: " + c.getTime());c.add(Calendar.MINUTE, 1); // 加1分System.out.println("加1分: " + c.getTime());c.add(Calendar.SECOND, 1); // 加1秒System.out.println("加1秒: " + c.getTime());System.out.println("\n");// 時區轉換c.clear(); // 清空設定c.set(2012, 4, 31, 17, 02, 20); // 2012-05-31 17:02:20System.out.println("------ 時區轉換 ------");System.out.println("當前時區: " + c.getTimeZone().getDisplayName());System.out.println("目前時間: " + c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" + c.get(Calendar.DAY_OF_MONTH) + " " + c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND));c.setTimeZone(TimeZone.getTimeZone("GMT"));System.out.println("轉換後時區: " + c.getTimeZone().getDisplayName());System.out.println("轉換後時間: " + c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" + c.get(Calendar.DAY_OF_MONTH) + " " + c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND));}
運行結果如下:
------ 定義一個具體的日期 ------Thu May 31 17:02:20 CDT 2012------ 獲得日期的各個組成部分 ------年: 2012月: 5日: 31時: 17分: 2秒: 20星期: 4------ 比較兩個日期的大小 ------Fri May 04 00:41:19 CDT 2012 在 Thu May 31 17:02:20 CDT 2012 之前.------ 計算兩個日期的間隔 ------Fri May 04 00:41:19 CDT 2012 和 Thu May 31 17:02:20 CDT 2012 的時間間隔是 27 天.------ 計算給特定日期加上或減去 1 年/月/日/時/分/秒 後的結果 ------加1年: Fri May 31 17:02:20 CDT 2013加1月: Sun Jun 30 17:02:20 CDT 2013加1日: Mon Jul 01 17:02:20 CDT 2013加32日: Fri Aug 02 17:02:20 CDT 2013加1時: Fri Aug 02 18:02:20 CDT 2013加1分: Fri Aug 02 18:03:20 CDT 2013加1秒: Fri Aug 02 18:03:21 CDT 2013------ 時區轉換 ------當前時區: Central Standard Time目前時間: 2012-5-31 17:2:20轉換後時區: Greenwich Mean Time轉換後時間: 2012-5-31 22:2:20
從上面的例子我們可以看到, Calendar 類並沒有提供計算日期的間隔的方法, 我們需要自己手動計算.
注意看上面例子的 58 行, 我們給日期加了 32 天, 但是程式並沒有拋異常, 原因是 Calendar 類預設採用寬鬆(leniency)的計算方式, 當然我們也可以通過調用下面的方法將它改為嚴格的模式, 此時, 再次運行 58 行的代碼程式會拋出異常.
c.setLenient(false);
從上面例子的 79 行我們可以看到, 我們可以通過下面的方式來得到一個 TimeZone 執行個體, 但是我們需要指定一個 ID, 問題是我們如何判斷一個 ID 是不是合法呢? 其實很簡單, 我們可以調用 getAvailableIDs() 方法來查看.
TimeZone.getTimeZone("GMT")
通過上面的例子我們看到, 使用 Calendar 類操作日期真的是很複雜, 為此, 好多開源的日期架構提供了更便於使用, 功能更強大的功能, 如: Joda