?
Java?語言的Calendar(日歷),Date(日期),?和DateFormat(日期格式)組成了Java標準的一個基本但是非常重要的部分.??日期是商業邏輯計算一個關鍵的部分.?所有的開發者都應該能夠計算未來的日期,?定制日期的顯示格式,?并將文本數據解析成日期對象.?我們寫了兩篇文章,?這是第一篇,?我們將大概的學習日期,?日期格式,?日期的解析和日期的計算.
我們將討論下面的類:
1、具體類(和抽象類相對)java.util.Date?
2、抽象類java.text.DateFormat?和它的一個具體子類,java.text.SimpleDateFormat?
3、抽象類java.util.Calendar?和它的一個具體子類,java.util.GregorianCalendar?
具體類可以被實例化,?但是抽象類卻不能.?你首先必須實現抽象類的一個具體子類.
Date??類從Java?開發包(JDK)?1.0?就開始進化,?當時它只包含了幾個取得或者設置一個日期數據的各個部分的方法,?比如說月,?日,?和年.?這些方法現在遭到了批評并且已經被轉移到了Calendar類里去了,?我們將在本文中進一步討論它.?這種改進旨在更好的處理日期數據的國際化格式.?就象在JDK?1.1中一樣,?Date?類實際上只是一個包裹類,?它包含的是一個長整型數據,?表示的是從GMT(格林尼治標準時間)1970年,??1?月?1日00:00:00這一刻之前或者是之后經歷的毫秒數.
一、創建一個日期對象
讓我們看一個使用系統的當前日期和時間創建一個日期對象并返回一個長整數的簡單例子.?這個時間通常被稱為Java?虛擬機(JVM)主機環境的系統時間.
import?java.util.Date;
public?class?DateExample1?{
????public?static?void?main(String[]?args)?{
????//?Get?the?system?date/time
????Date?date?=?new?Date();
????System.out.println(date.getTime());
????}
}
在星期六,?2001年9月29日,?下午大約是6:50的樣子,?上面的例子在系統輸出設備上顯示的結果是?1001803809710.?在這個例子中,值得注意的是我們使用了Date?構造函數創建一個日期對象,?這個構造函數沒有接受任何參數.?而這個構造函數在內部使用了?System.currentTimeMillis()?方法來從系統獲取日期.
那么,?現在我們已經知道了如何獲取從1970年1月1?日開始經歷的毫秒數了.?我們如何才能以一種用戶明白的格式來顯示這個日期呢??在這里類java.text.SimpleDateFormat?和它的抽象基類?java.text.DateFormat?就派得上用場了.
二、日期數據的定制格式
假如我們希望定制日期數據的格式,?比方星期六-9月-29日-2001年.?下面的例子展示了如何完成這個工作:
import?java.text.SimpleDateFormat;
import?java.util.Date;
public?class?DateExample2?{
????public?static?void?main(String[]?args)?{
????????SimpleDateFormat?bartDateFormat?=
????????new?SimpleDateFormat("EEEE-MMMM-dd-yyyy");
????????Date?date?=?new?Date();
????????System.out.println(bartDateFormat.format(date));
????}
}
只要通過向SimpleDateFormat?的構造函數傳遞格式字符串"EEE-MMMM-dd-yyyy",?我們就能夠指明自己想要的格式.?你應該可以看見,?格式字符串中的ASCII?字符告訴格式化函數下面顯示日期數據的哪一個部分.?EEEE是星期,?MMMM是月,?dd是日,?yyyy是年.?字符的個數決定了日期是如何格式化的.傳遞"EE-MM-dd-yy"會顯示?Sat-09-29-01.?請察看Sun?公司的Web?站點獲取日期格式化選項的完整的指示.
三、將文本數據解析成日期對象
假設我們有一個文本字符串包含了一個格式化了的日期對象,?而我們希望解析這個字符串并從文本日期數據創建一個日期對象.?我們將再次以格式化字符串"MM-dd-yyyy"?調用?SimpleDateFormat類,?但是這一次,?我們使用格式化解析而不是生成一個文本日期數據.?我們的例子,?顯示在下面,?將解析文本字符串?"9-29-2001"并創建一個值為001736000000?的日期對象.
例子程序:
import?java.text.SimpleDateFormat;
import?java.util.Date;
public?class?DateExample3?{
????public?static?void?main(String[]?args)?{
????????//?Create?a?date?formatter?that?can?parse?dates?of
????????//?the?form?MM-dd-yyyy.
????????SimpleDateFormat?bartDateFormat?=
????????new?SimpleDateFormat("MM-dd-yyyy");
????????//?Create?a?string?containing?a?text?date?to?be?parsed.
????????String?dateStringToParse?=?"9-29-2001";
????????try?{
????????????//?Parse?the?text?version?of?the?date.
????????????//?We?have?to?perform?the?parse?method?in?a
????????????//?try-catch?construct?in?case?dateStringToParse
????????????//?does?not?contain?a?date?in?the?format?we?are?expecting.
????????????Date?date?=?bartDateFormat.parse(dateStringToParse);
????????????//?Now?send?the?parsed?date?as?a?long?value
????????????//?to?the?system?output.
????????????System.out.println(date.getTime());
????????}
????????catch?(Exception?ex)?{
????????????System.out.println(ex.getMessage());
????????}
????}
}
?
五、使用標準的日期格式化過程
既然我們已經可以生成和解析定制的日期格式了,?讓我們來看一看如何使用內建的格式化過程.?方法??DateFormat.getDateTimeInstance()?讓我們得以用幾種不同的方法獲得標準的日期格式化過程.?在下面的例子中,?我們獲取了四個內建的日期格式化過程.?它們包括一個短的,?中等的,?長的,?和完整的日期格式.
import?java.text.DateFormat;
import?java.util.Date;
public?class?DateExample4?{
????public?static?void?main(String[]?args)?{
????????Date?date?=?new?Date();
????????DateFormat?shortDateFormat?=
????????DateFormat.getDateTimeInstance(
????????DateFormat.SHORT,
????????DateFormat.SHORT);
????????DateFormat?mediumDateFormat?=
????????DateFormat.getDateTimeInstance(
????????DateFormat.MEDIUM,
????????DateFormat.MEDIUM);
????????DateFormat?longDateFormat?=
????????DateFormat.getDateTimeInstance(
????????DateFormat.LONG,
????????DateFormat.LONG);
????????DateFormat?fullDateFormat?=
????????DateFormat.getDateTimeInstance(
????????DateFormat.FULL,
????????DateFormat.FULL);
????????System.out.println(shortDateFormat.format(date));
????????System.out.println(mediumDateFormat.format(date));
????????System.out.println(longDateFormat.format(date));
????????System.out.println(fullDateFormat.format(date));
????}
}
注意我們在對?getDateTimeInstance的每次調用中都傳遞了兩個值.?第一個參數是日期風格,?而第二個參數是時間風格.?它們都是基本數據類型int(整型).?考慮到可讀性,?我們使用了DateFormat?類提供的常量:?SHORT,?MEDIUM,?LONG,?和??FULL.?要知道獲取時間和日期格式化過程的更多的方法和選項,?請看Sun?公司Web?站點上的解釋.
運行我們的例子程序的時候,?它將向標準輸出設備輸出下面的內容:
9/29/01?8:44?PM
Sep?29,?2001?8:44:45?PM
September?29,?2001?8:44:45?PM?EDT
Saturday,?September?29,?2001?8:44:45?PM?EDT
六、Calendar?類
我們現在已經能夠格式化并創建一個日期對象了,?但是我們如何才能設置和獲取日期數據的特定部分呢,?比如說小時,?日,?或者分鐘??我們又如何在日期的這些部分加上或者減去值呢??答案是使用Calendar?類.?就如我們前面提到的那樣,?Calendar?類中的方法替代了Date?類中被人唾罵的方法.
假設你想要設置,?獲取,?和操縱一個日期對象的各個部分,?比方一個月的一天或者是一個星期的一天.?為了演示這個過程,?我們將使用具體的子類?java.util.GregorianCalendar.?考慮下面的例子,?它計算得到下面的第十個星期五是13號.?
import?java.util.GregorianCalendar;
import?java.util.Date;
import?java.text.DateFormat;
public?class?DateExample5?{
????public?static?void?main(String[]?args)?{
????????DateFormat?dateFormat?=
????????DateFormat.getDateInstance(DateFormat.FULL);
????????//?Create?our?Gregorian?Calendar.
????????GregorianCalendar?cal?=?new?GregorianCalendar();
????????//?Set?the?date?and?time?of?our?calendar
????????//?to?the?system's?date?and?time
????????cal.setTime(new?Date());
????????System.out.println("System?Date:?"?+
????????dateFormat.format(cal.getTime()));
????????//?Set?the?day?of?week?to?FRIDAY
????????cal.set(GregorianCalendar.DAY_OF_WEEK,
????????GregorianCalendar.FRIDAY);
????????System.out.println("After?Setting?Day?of?Week?to?Friday:?"?+
????????dateFormat.format(cal.getTime()));
????????int?friday13Counter?=?0;
????????while?(friday13Counter?<=?10)?{
????????????//?Go?to?the?next?Friday?by?adding?7?days.
????????????cal.add(GregorianCalendar.DAY_OF_MONTH,?7);
????????????//?If?the?day?of?month?is?13?we?have
????????????//?another?Friday?the?13th.
????????????if?(cal.get(GregorianCalendar.DAY_OF_MONTH)?==?13)?{
????????????????friday13Counter++;
????????????????System.out.println(dateFormat.format(cal.getTime()));
????????????}
????????}
????}
}
在這個例子中我們作了有趣的函數調用:
cal.set(GregorianCalendar.DAY_OF_WEEK,
GregorianCalendar.FRIDAY);
和:
cal.add(GregorianCalendar.DAY_OF_MONTH,?7);
set??方法能夠讓我們通過簡單的設置星期中的哪一天這個域來將我們的時間調整為星期五.?注意到這里我們使用了常量?DAY_OF_WEEK?和?FRIDAY?來增強代碼的可讀性.?add?方法讓我們能夠在日期上加上數值.?潤年的所有復雜的計算都由這個方法自動處理.
我們這個例子的輸出結果是:
System?Date:?Saturday,?September?29,?2001
當我們將它設置成星期五以后就成了:?Friday,?September?28,?2001
Friday,?September?13,?2002
Friday,?December?13,?2002
Friday,?June?13,?2003
Friday,?February?13,?2004
Friday,?August?13,?2004
Friday,?May?13,?2005
Friday,?January?13,?2006
Friday,?October?13,?2006
Friday,?April?13,?2007
Friday,?July?13,?2007
Friday,?June?13,?2008
七、時間掌握在你的手里
有了這些Date?和Calendar?類的例子,?你應該能夠使用?java.util.Date,?java.text.SimpleDateFormat,?和?java.util.GregorianCalendar?創建許多方法了.
在下面的文章中,?我們將討論更高級的Date?和?Calendar?類的使用技巧,?包括時區和國際化的格式.?我們還會考察兩個日期類?java.sql.Date?和?java.util.Date?之間的區別.