天天看點

JAVA常用類之日期處理

在應用程式設計中,我們經常會用到日期時間,比如出生日期之類的,java中為我們提供了一些處理日期的類。這一片部落格将為大家介紹一下。

date類是我們用的比較多的一個處理時間的類。表示特定的瞬間,精确到毫秒。

在 jdk 1.1 之前,類 date 有兩個其他的函數。它允許把日期解釋為年、月、日、小時、分鐘和秒值。它也允許格式化和解析日期字元串。不過,這些函數的 api 不易于實作國際化。從 jdk 1.1 開始,應該使用 calendar 類實作日期和時間字段之間轉換,使用 dateformat 類來格式化和解析日期字元串。date 中的相應方法已廢棄。 在類 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 日的相同含義。

下表中展示的為date類的構造方法,已經過時的方法沒有列出:

方法名

說明

date()

配置設定 date 對象并初始化此對象,以表示配置設定它的時間(精确到毫秒)

date(long date)

配置設定 date 對象并初始化此對象,以表示自從标準基準時間(稱為“曆元(epoch)”,即 1970 年 1 月 1 日 00:00:00 gmt)以來的指定毫秒數

傳回值

boolean

after(date when)

測試此日期是否在指定日期之後

before(date when)

測試此日期是否在指定日期之前

object

clone()

傳回此對象的副本

int

compareto(date anotherdate)

比較兩個日期的順序

equals(object obj)

比較兩個日期的相等性

long

gettime()

傳回自 1970 年 1 月 1 日 00:00:00 gmt 以來此 date 對象表示的毫秒數

hashcode()

傳回此對象的哈希碼值

void

settime(long time)

設定此 date 對象,以表示 1970 年 1 月 1 日 00:00:00 gmt 以後 time 毫秒的時間點

string

tostring()

把此 date 對象轉換為以下形式的 string: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (sun, mon, tue, wed, thu, fri, sat)

輸出結果為:

true

date類可以很友善的表示時間,但是諸如獲得目前小時、分鐘等方法已經被标記為過時的方法。是以這裡為大家介紹calendar類。

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

與其他語言環境敏感類一樣,calendar 提供了一個類方法 getinstance,以獲得此類型的一個通用的對象。calendar 的 getinstance 方法傳回一個 calendar 對象,其月曆字段已由目前日期和時間初始化:

<code>calendar rightnow = calendar.getinstance();</code>

calendar 對象能夠生成為特定語言和月曆風格實作日期-時間格式化所需的所有月曆字段值,例如,日語-格裡高裡曆,日語-傳統月曆。calendar 定義了某些月曆字段傳回值的範圍,以及這些值的含義。

獲得并設定月曆字段值

可以通過調用 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 将為最近設定的月曆字段提供優先權。以下是月曆字段的預設組合。将使用由最近設定的單個字段所确定的最近組合。

對于日期字段:

<code>year + month + day_of_month</code>

<code>year + month + week_of_month + day_of_week</code>

<code>year + month + day_of_week_in_month + day_of_week</code>

<code>year + day_of_year</code>

<code>year + day_of_week + week_of_year</code>

對于時間字段:

<code>hour_of_day</code>

<code>am_pm + hour</code>

如果在標明的字段組合中,還有尚未設定值的任一月曆字段,那麼 calendar 将使用其預設值。每個字段的預設值可能依據具體的月曆系統而有所不同。例如,在 gregoriancalendar 中,字段的預設值與曆元起始部分的字段值相同:即 year = 1970、month = january、day_of_month = 1,等等。

注: 對于某些特别時間的解釋可能會有某些歧義,可以用下列方式解決:

23:59 是一天中的最後一分鐘,而 00:00 是下一天的第一分鐘。是以,1999 年 12 月 31 日的 23:59 &lt; 2000 年 1 月 1 日的 00:00。

盡管從曆史上看不夠精确,但午夜也屬于 “am”,,中午屬于 “pm”,是以在同一天,12:00 am ( 午夜 ) &lt; 12:01 am,12:00 pm ( 中午 ) &lt; 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(),根據是否會影響更大的字段,使用者界面可以像大多數使用者所期望的那樣運作。

protected calendar()

構造一個帶有預設時區和語言環境的 calendar

protected calendar(timezone zone, locale alocale)

構造一個帶有指定時區和語言環境的 calendar

abstract void

add(int field, int amount)

根據月曆的規則,為給定的月曆字段添加或減去指定的時間量

after(object when)

判斷此 calendar 表示的時間是否在指定 object 表示的時間之後,傳回判斷結果

before(object when)

判斷此 calendar 表示的時間是否在指定 object 表示的時間之前,傳回判斷結果

clear()

将此 calendar 的所月曆字段值和時間值(從曆元至現在的毫秒偏移量)設定成未定義

clear(int field)

将此 calendar 的給定月曆字段值和時間值(從曆元至現在的毫秒偏移量)設定成未定義

建立并傳回此對象的一個副本

compareto(calendar anothercalendar)

比較兩個 calendar 對象表示的時間值(從曆元至現在的毫秒偏移量)

protected void

complete()

填充月曆字段中所有未設定的字段

protected abstract void

computefields()

将目前毫秒時間值 time 轉換為 fields[] 中的月曆字段值

computetime()

将 fields[] 中的目前月曆字段值轉換為毫秒時間值 time

将此 calendar 與指定 object 比較

get(int field)

傳回給定月曆字段的值

getactualmaximum(int field)

給定此 calendar 的時間值,傳回指定月曆字段可能擁有的最大值

getactualminimum(int field)

給定此 calendar 的時間值,傳回指定月曆字段可能擁有的最小值

static locale[]

getavailablelocales()

傳回所有語言環境的數組,此類的 getinstance 方法可以為其傳回本地化的執行個體

getdisplayname(int field, int style, locale locale)

傳回給定style和locale下的月曆field值的字元串表示形式

map&lt; string, integer&gt;

getdisplaynames(int field, int style, locale locale)

傳回給定style和locale下包含月曆 field 所有名稱的map及其相應字段值

getfirstdayofweek()

擷取一星期的第一天;例如,在美國,這一天是 sunday,而在法國,這一天是 monday

abstract int

getgreatestminimum(int field)

傳回此 calendar 執行個體給定月曆字段的最高的最小值

static calendar

getinstance()

使用預設時區和語言環境獲得一個月曆

getinstance(locale alocale)

使用預設時區和指定語言環境獲得一個月曆

getinstance(timezone zone)

使用指定時區和預設語言環境獲得一個月曆

getinstance(timezone zone, locale alocale)

使用指定時區和語言環境獲得一個月曆

getleastmaximum(int field)

傳回此 calendar 執行個體給定月曆字段的最低的最大值

getmaximum(int field)

傳回此 calendar 執行個體給定月曆字段的最大值

getminimaldaysinfirstweek()

擷取一年中第一個星期所需的最少天數,例如,如果定義第一個星期包含一年第一個月的第一天,則此方法将傳回 1

getminimum(int field)

傳回此 calendar 執行個體給定月曆字段的最小值

date

傳回一個表示此 calendar 時間值(從曆元至現在的毫秒偏移量)的 date 對象

gettimeinmillis()

傳回此 calendar 的時間值,以毫秒為機關

timezone

gettimezone()

獲得時區

傳回該此月曆的哈希碼

protected int

internalget(int field)

islenient()

判斷日期/時間的解釋是否為寬松的

isset(int field)

确定給定月曆字段是否已經設定了一個值,其中包括因為調用 get 方法觸發内部字段計算而導緻已經設定該值的情況

roll(int field, boolean up)

在給定的時間字段上添加或減去(上/下)單個時間單元,不更改更大的字段

roll(int field, int amount)

向指定月曆字段添加指定(有符号的)時間量,不更改更大的字段

set(int field, int value)

将給定的月曆字段設定為給定值

set(int year, int month, int date)

設定月曆字段 year、month 和 day_of_month 的值

set(int year, int month, int date, int hourofday, int minute)

設定月曆字段 year、month、day_of_month、hour_of_day 和 minute 的值

set(int year, int month, int date, int hourofday, int minute, int second)

設定字段 year、month、day_of_month、hour、minute 和 second 的值

setfirstdayofweek(int value)

設定一星期的第一天是哪一天;例如,在美國,這一天是 sunday,而在法國,這一天是 monday

setlenient(boolean lenient)

指定日期/時間解釋是否是寬松的

setminimaldaysinfirstweek(int value)

設定一年中第一個星期所需的最少天數,例如,如果定義第一個星期包含一年第一個月的第一天,則使用值 1 調用此方法

settime(date date)

使用給定的 date 設定此 calendar 的時間

settimeinmillis(long millis)

用給定的 long 值設定此 calendar 的目前時間值

settimezone(timezone value)

使用給定的時區值來設定時區

傳回此月曆的字元串表示形式