日期格式彙總

DateFormat     java.text.DateFormat

public abstract class DateFormat extends Format

DateFormat 是日期/時間格式化子類的抽象類,它以與語言無關的方式格式化並解析日期或時間。日期/時間格式化子類(如 SimpleDateFormat)允許進行格式化(也就是日期 -> 文本)、解析(文本-> 日期)和標準化。將日期表示爲 Date 對象,或者表示爲從 GMT(格林尼治標準時間)1970 年 1 月 1 日 00:00:00 這一刻開始的毫秒數。 

DateFormat 提供了很多類方法,以獲得基於默認或給定語言環境和多種格式化風格的默認日期/時間 Formatter。格式化風格包括 FULL、LONG、MEDIUM 和 SHORT。方法描述中提供了使用這些風格的更多細節和示例。 

DateFormat 可幫助進行格式化並解析任何語言環境的日期。對於月、星期,甚至日曆格式(陰曆和陽曆),其代碼可完全與語言環境的約定無關。 

要格式化一個當前語言環境下的日期,可使用某個靜態工廠方法: 
  myString = DateFormat.getDateInstance().format(myDate);
 如果格式化多個日期,那麼獲取該格式並多次使用它是更爲高效的做法,這樣系統就不必多次獲取有關環境語言和國家/地區約定的信息了。 
  DateFormat df = DateFormat.getDateInstance();
  for (int i = 0; i < myDate.length; ++i) {
    output.println(df.format(myDate[i]) + "; ");
  }

 要格式化不同語言環境的日期,可在 getDateInstance() 的調用中指定它。 
  DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);

 還可使用 DateFormat 進行解析。 
  myDate = df.parse(myString);

另外還提供了一些其他靜態工廠方法。使用 getDateInstance 來獲取該國家/地區的標準日期格式。使用 getTimeInstance 可獲取該國家/地區的時間格式。使用 getDateTimeInstance 可獲取日期和時間格式。可以將不同選項傳入這些工廠方法,以控制結果的長度(從 SHORT 到 MEDIUM 到 LONG 再到 FULL)。確切的結果取決於語言環境,但是通常: 

  • SHORT 完全爲數字,如 12.13.52 或 3:30pm 
  • MEDIUM 較長,如 Jan 12, 1952 
  • LONG 更長,如 January 12, 1952 或 3:30:32pm 
  • FULL 是完全指定,如 Tuesday、April 12、1952 AD 或 3:30:42pm PST。 
如果願意,還可以在格式上設置時區。

如果想對格式化或解析施加更多的控制(或者給予用戶更多的控制),可以嘗試將從工廠方法所獲取的 DateFormat 強制轉換爲 SimpleDateFormat。這適用於大多數國家/地區;只是要記住將其放入一個 try 代碼塊中,以防遇到特殊的格式。 

還可以使用藉助 ParsePosition 和 FieldPosition 的解析和格式化方法形式來

  • 逐步地解析字符串的各部分。 
  • 對齊任意特定的字段,或者找出字符串在屏幕上的選擇位置。 

同步

日期格式不是同步的。建議爲每個線程創建獨立的格式實例。如果多個線程同時訪問一個格式,則它必須保持外部同步。 

SimpleDateFormat     java.text.SimpleDateFormat

SimpleDateFormat 是一個以與語言環境有關的方式來格式化和解析日期的具體類。它允許進行格式化(日期 -> 文本)、解析(文本 -> 日期)和規範化。 

SimpleDateFormat 使得可以選擇任何用戶定義的日期-時間格式的模式。但是,仍然建議通過 DateFormat 中的 getTimeInstance、getDateInstance 或 getDateTimeInstance 來創建日期-時間格式器。每一個這樣的類方法都能夠返回一個以默認格式模式初始化的日期/時間格式器。可以根據需要使用 applyPattern 方法來修改格式模式。

日期和時間模式

日期和時間格式由日期和時間模式 字符串指定。在日期和時間模式字符串中,未加引號的字母 'A' 到 'Z' 和 'a' 到 'z' 被解釋爲模式字母,用來表示日期或時間字符串元素。文本可以使用單引號 (') 引起來,以免進行解釋。"''" 表示單引號。所有其他字符均不解釋;只是在格式化時將它們簡單複製到輸出字符串,或者在解析時與輸入字符串進行匹配。 

定義了以下模式字母(所有其他字符 'A' 到 'Z' 和 'a' 到 'z' 都被保留): 


模式字母通常是重複的,其數量確定其精確表示: 
  • Text: 對於格式化來說,如果模式字母的數量大於等於 4,則使用完全形式;否則,在可用的情況下使用短形式或縮寫形式。對於解析來說,兩種形式都是可接受的,與模式字母的數量無關。 
  • Number: 對於格式化來說,模式字母的數量是最小的數位,如果數位不夠,則用 0 填充以達到此數量。對於解析來說,模式字母的數量被忽略,除非必須分開兩個相鄰字段。 
  • Year: 如果格式器的 Calendar 是格里高利曆,則應用以下規則。

對於格式化來說,如果模式字母的數量爲 2,則年份截取爲 2 位數,否則將年份解釋爲 number。 對於解析來說,如果模式字母的數量大於 2,則年份照字面意義進行解釋,而不管數位是多少。因此使用模式 "MM/dd/yyyy",將 "01/11/12" 解析爲公元 12 年 1 月 11 日。在解析縮寫年份模式("y" 或 "yy")時,SimpleDateFormat 必須相對於某個世紀來解釋縮寫的年份。這通過將日期調整爲 SimpleDateFormat 實例創建之前的 80 年和之後 20 年範圍內來完成。例如,在 "MM/dd/yy" 模式下,如果 SimpleDateFormat 實例是在 1997 年 1 月 1 日創建的,則字符串 "01/11/12" 將被解釋爲 2012 年 1 月 11 日,而字符串 "05/04/64" 將被解釋爲 1964 年 5 月 4 日。在解析時,只有恰好由兩位數字組成的字符串(如 Character.isDigit(char) 所定義的)被解析爲默認的世紀。其他任何數字字符串將照字面意義進行解釋,例如單數字字符串,3 個或更多數字組成的字符串,或者不都是數字的兩位數字字符串(例如"-1")。因此,在相同的模式下, "01/02/3" 或 "01/02/003" 解釋爲公元 3 年 1 月 2 日。同樣,"01/02/-3" 解析爲公元前 4 年 1 月 2 日。 

否則,則應用日曆系統特定的形式。對於格式化和解析,如果模式字母的數量爲 4 或大於 4,則使用日曆特定的 long form。否則,則使用日曆特定的 short or abbreviated          form。 

  • Month: 如果模式字母的數量爲 3 或大於 3,則將月份解釋爲 text;否則解釋爲 number。 

同步

日期格式是不同步的。建議爲每個線程創建獨立的格式實例。如果多個線程同時訪問一個格式,則它必須是外部同步的。


Date     java.util.Date

public class Date extends Object implements Serializable, Cloneable, Comparable<Date>

類 Date 表示特定的瞬間,精確到毫秒。 

在 JDK 1.1 之前,類 Date 有兩個其他的函數。它允許把日期解釋爲年、月、日、小時、分鐘和秒值。它也允許格式化和解析日期字符串。不過,這些函數的 API 不易於實現國際化。從 JDK 1.1 開始,應該使用 Calendar 類實現日期和時間字段之間轉換,使用 DateFormat 類來格式化和解析日期字符串。Date 中的相應方法已廢棄。 

儘管 Date 類打算反映協調世界時 (UTC),但無法做到如此準確,這取決於 Java 虛擬機的主機環境。當前幾乎所有操作系統都假定 1 天 = 24 × 60 × 60 = 86400 秒。但對於 UTC,大約每一兩年出現一次額外的一秒,稱爲“閏秒”。閏秒始終作爲當天的最後一秒增加,並且始終在 12 月 31 日或 6 月 30 日增加。例如,1995 年的最後一分鐘是 61 秒,因爲增加了閏秒。大多數計算機時鐘不是特別的準確,因此不能反映閏秒的差別。 

一些計算機標準是按照格林威治標準時 (GMT) 定義的,格林威治標準時和世界時 (UT) 是相等的。GMT 是標準的“民間”名稱;UT 是相同標準的“科學”名稱。UTC 和 UT 的區別是:UTC 是基於原子時鐘的,UT 是基於天體觀察的,兩者在實際應用中難分軒輊。因爲地球的旋轉不是均勻的(它以複雜的方式減速和加速),所以 UT 始終不是均勻地流過。閏秒是根據需要引入 UTC 的,以便把 UTC 保持在 UT1 的 0.9 秒之內,UT1 是應用了某些更正的 UT 版本。還有其他的時間和日期系統;例如,基於衛星的全球定位系統 (GPS) 使用的時間刻度與 UTC 同步,但沒有 針對閏秒進行調整。


 在類 Date 所有可以接受或返回年、月、日期、小時、分鐘和秒值的方法中,將使用下面的表示形式: 
  • 年份 y 由整數 y - 1900 表示。 
  • 月份由從 0 至 11 的整數表示;0 是一月、1 是二月等等;因此 11 是十二月。 
  • 日期(一月中的某天)按通常方式由整數 1 至 31 表示。 
  • 小時由從 0 至 23 的整數表示。因此,從午夜到 1 a.m. 的時間是 0 點,從中午到 1 p.m. 的時間是 12 點。 
  • 分鐘按通常方式由 0 至 59 的整數表示。 
  • 秒由 0 至 61 的整數表示;值 60 和 61 只對閏秒發生,儘管那樣,也只用在實際正確跟蹤閏秒的 Java 實現中。於按當前引入閏秒的方式,兩個閏秒在同一分鐘內發生是極不可能的,但此規範遵循 ISO C 的日期和時間約定。 
在所有情形中,針對這些目的賦予方法的參數不需要在指定的範圍內;例如,可以把日期指定爲 1 月 32 日,並把它解釋爲 2 月 1 日的相同含義。 

從以下版本開始: JDK1.0 


Calender      java.util.Calendar

public abstract class Calendar extends Object implements Serializable, Cloneable, Comparable<Calendar>

Calendar 類是一個抽象類,它爲特定瞬間與一組諸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日曆字段之間的轉換提供了一些方法,併爲操作日曆字段(例如獲得下星期的日期)提供了一些方法。瞬間可用毫秒值來表示,它是距曆元(即格林威治標準時間 1970 年 1 月 1 日的 00:00:00.000,格里高利曆)的偏移量。 

該類還爲實現包範圍外的具體日曆系統提供了其他字段和方法。這些字段和方法被定義爲 protected。 

與其他語言環境敏感類一樣,Calendar 提供了一個類方法 getInstance,以獲得此類型的一個通用的對象。Calendar 的 getInstance 方法返回一個 Calendar 對象,其日曆字段已由當前日期和時間初始化: 
     Calendar rightNow = Calendar.getInstance();
Calendar 對象能夠生成爲特定語言和日曆風格實現日期-時間格式化所需的所有日曆字段值,例如,日語-格里高裏歷,日語-傳統日曆。Calendar 定義了某些日曆字段返回值的範圍,以及這些值的含義。例如,對於所有日曆,日曆系統第一個月的值是 MONTH == JANUARY。其他值是由具體子類(例如 ERA)定義的。有關此內容的細節,請參閱每個字段的文檔和子類文檔。 

獲得並設置日曆字段值

可以通過調用 set 方法來設置日曆字段值。在需要計算時間值(距曆元所經過的毫秒)或日曆字段值之前,不會解釋 Calendar 中的所有字段值設置。調用 get、getTimeInMillis、getTime、add 和 roll 涉及此類計算。 


寬鬆性

Calendar 有兩種解釋日曆字段的模式,即 lenient 和 non-lenient。當 Calendar 處於 lenient 模式時,它可接受比它所生成的日曆字段範圍更大範圍內的值。當 Calendar 重新計算日曆字段值,以便由 get() 返回這些值時,所有日曆字段都被標準化。例如,lenient 模式下的 GregorianCalendar 將 MONTH == JANUARY、DAY_OF_MONTH == 32 解釋爲 February 1。 

當 Calendar 處於 non-lenient 模式時,如果其日曆字段中存在任何不一致性,它都會拋出一個異常。例如,GregorianCalendar 總是在 1 與月份的長度之間生成 DAY_OF_MONTH 值。如果已經設置了任何超出範圍的字段值,那麼在計算時間或日曆字段值時,處於 non-lenient 模式下的 GregorianCalendar 會拋出一個異常。 


第一個星期

Calendar 使用兩個參數定義了特定於語言環境的 7 天制星期:星期的第一天和第一個星期中的最小一天(從 1 到 7)。這些數字取自構造 Calendar 時的語言環境資源數據。還可以通過爲其設置值的方法來顯式地指定它們。 
在設置或獲得 WEEK_OF_MONTH 或 WEEK_OF_YEAR 字段時,Calendar 必須確定一個月或一年的第一個星期,以此作爲參考點。一個月或一年的第一個星期被確定爲開始於 getFirstDayOfWeek() 的最早七天,它最少包含那一個月或一年的 getMinimalDaysInFirstWeek() 天數。第一個星期之前的各星期編號爲 ...、-1、0;之後的星期編號爲 2、3、...。注意,get() 返回的標準化編號方式可能有所不同。例如,特定 Calendar 子類可能將某一年第 1 個星期之前的那個星期指定爲前一年的第 n 個星期。 

日曆字段解析

在計算日曆字段中的日期和時間時,可能沒有足夠的信息用於計算(例如只有年和月,但沒有日),或者可能有不一致的信息( 例如 "Tuesday, July 15, 1996"(格林威治時間)——實際上,1996 年 7 月 15 日是星期一 )。Calendar 將解析日曆字段值,以便用以下方式確定日期和時間。 
如果日曆字段值中存在任何衝突,則 Calendar 將爲最近設置的日曆字段提供優先權。以下是日曆字段的默認組合。將使用由最近設置的單個字段所確定的最近組合。 

對於日期字段: 

 YEAR + MONTH + DAY_OF_MONTH
 YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
 YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
 YEAR + DAY_OF_YEAR
 YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
 對於時間字段: 
 HOUR_OF_DAY
 AM_PM + HOUR
 如果在選定的字段組合中,還有尚未設置值的任一日曆字段,那麼 Calendar 將使用其默認值。每個字段的默認值可能依據具體的日曆系統而有所不同。例如,在 GregorianCalendar 中,字段的默認值與曆元起始部分的字段值相同:即 YEAR = 1970、MONTH = JANUARY、DAY_OF_MONTH = 1,等等。 

注: 對於某些特別時間的解釋可能會有某些歧義,可以用下列方式解決: 
  1. 23:59 是一天中的最後一分鐘,而 00:00 是下一天的第一分鐘。因此,1999 年 12 月 31 日的 23:59 < 2000 年 1 月 1 日的 00:00。 
  2. 儘管從歷史上看不夠精確,但午夜也屬於 "am",,中午屬於 "pm",所以在同一天,12:00 am ( 午夜 ) < 12:01 am,12:00 pm ( 中午 ) < 12:01 pm。 
日期或時間格式字符串不是日曆定義的一部分,因爲在運行時,用戶必須能夠修改或重寫它們。可以使用 DateFormat 格式化日期。 

字段操作

可以使用三種方法更改日曆字段:set()、add() 和 roll()。

set(f, value) 

將日曆字段 f 更改爲 value。此外,它設置了一個內部成員變量,以指示日曆字段 f 已經被更改。儘管日曆字段 f 是立即更改的,但是直到下次調用 get()、getTime()、getTimeInMillis()、add() 或 roll() 時纔會重新計算日曆的時間值(以毫秒爲單位)。因此,多次調用 set() 不會觸發多次不必要的計算。使用 set() 更改日曆字段的結果是,其他日曆字段也可能發生更改,這取決於日曆字段、日曆字段值和日曆系統。此外,在重新計算日曆字段之後,get(f) 沒必要通過調用 set 方法返回 value 集合。具體細節是通過具體的日曆類確定的。



示例:假定 GregorianCalendar 最初被設置爲 1999 年 8 月 31 日。調用 set(Calendar.MONTH, Calendar.SEPTEMBER) 將該日期設置爲 1999 年 9 月 31 日。如果隨後調用 getTime(),那麼這是解析 1999 年 10 月 1 日的一個暫時內部表示。但是,在調用 getTime() 之前調用 set(Calendar.DAY_OF_MONTH, 30) 會將該日期設置爲 1999 年 9 月 30 日,因爲在調用 set() 之後沒有發生重新計算。

add(f, delta) 

將 delta 添加到 f 字段中。這等同於調用 set(f, get(f) + delta),但要帶以下兩個調整:

  • Add 規則 1。調用後 f 字段的值減去調用前 f 字段的值等於 delta,以字段 f 中發生的任何溢出爲模。溢出發生在字段值超出其範圍時,結果,下一個更大的字段會遞增或遞減,並將字段值調整回其範圍內。
  • Add 規則 2。如果期望某一個更小的字段是不變的,但讓它等於以前的值是不可能的,因爲在字段 f 發生更改之後,或者在出現其他約束之後,比如時區偏移量發生更改,它的最大值和最小值也在發生更改,然後它的值被調整爲儘量接近於所期望的值。更小的字段表示一個更小的時間單元。HOUR 是一個比 DAY_OF_MONTH 小的字段。對於不期望是不變字段的更小字段,無需進行任何調整。日曆系統會確定期望不變的那些字段。
此外,與 set() 不同,add() 強迫日曆系統立即重新計算日曆的毫秒數和所有字段。


示例:假定 GregorianCalendar 最初被設置爲 1999 年 8 月 31 日。調用 add(Calendar.MONTH, 13) 將日曆設置爲 2000 年 9 月 30 日。Add 規則 1 將 MONTH 字段設置爲 September,因爲向 August 添加 13 個月得出的就是下一年的 September。因爲在 GregorianCalendar 中,DAY_OF_MONTH 不可能是 9 月 31 日,所以 add 規則 2 將 DAY_OF_MONTH 設置爲 30,即最可能的值。儘管它是一個更小的字段,但不能根據規則 2 調整 DAY_OF_WEEK,因爲在 GregorianCalendar 中的月份發生變化時,該值也需要發生變化。

roll(f, delta) 

將 delta 添加到 f 字段中,但不更改更大的字段。這等同於調用 add(f, delta),但要帶以下調整:

Roll 規則。在完成調用後,更大的字段無變化。更大的字段表示一個更大的時間單元。DAY_OF_MONTH 是一個比 HOUR 大的字段。

使用模型

爲了幫助理解 add() 和 roll() 的行爲,假定有一個用戶界面組件,它帶有用於月、日、年和底層 GregorianCalendar 的遞增或遞減按鈕。如果從界面上讀取的日期爲 1999 年 1 月 31 日,並且用戶按下月份的遞增按鈕,那麼應該得到什麼?如果底層實現使用 set(),那麼可以將該日期讀爲 1999 年 3 月 3 日。更好的結果是 1999 年 2 月 28 日。此外,如果用戶再次按下月份的遞增按鈕,那麼該日期應該讀爲 1999 年 3 月 31 日,而不是 1999 年 3 月 28 日。通過保存原始日期並使用 add() 或 roll(),根據是否會影響更大的字段,用戶界面可以像大多數用戶所期望的那樣運行。


從以下版本開始: JDK1.1 

發佈了8 篇原創文章 · 獲贊 24 · 訪問量 35萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章