Date類的概述
1.JDK提供date類表示特定的瞬間,精確到毫秒。
繼續查閱Date類的描述,發現Date擁有多個構造函數,只是部分已經過時,但是其中有未過時的構造函數可以把毫秒值轉成日期對象。
//創建日期對象,把當前的毫秒值轉成日期對象
Date date = new Date(124355676160L);
System.out.println(date);
//Mon Dec 10 15:14:36 CST 1973
可是將毫秒值轉成日期後,輸出的格式不利於我們閱讀,繼續查閱API,Date中有getYear、getMouth等方法,可以他們已經過時,繼續往下查閱,還有讓我們參見toLocaleString方法,點進去,這個方法也過時了,從JDK 1.1 開始,由 DateFormat.format(Date date) 取代。
既然這個方法被DateFormat.format(Date date)取代,那麼就要去查閱DateFormat類。
date常用的方法:
把日期對象轉換成對應的時間毫秒值
2.DateFormat的概述:DateFormat是日期/時間格式化子類的抽象類,它以與語言無關的方式格式化並解析日期或時間。日期/時間格式化子類(如SimpleDateFormat類)允許進行格式化(也就是日期-> 文本)、解析(文本->日期)和標準化。
我們通過這個類可以幫我們完成日期和文本之間的轉換。
DateFormat 可幫助進行格式化並解析任何語言環境的日期。對於月、星期,甚至日曆格式(陰曆和陽曆),其代碼可完全與語言環境的約定無關。
(1.)日期格式:日期-->文本要格式化一個當前語言環境下的日期也就是日期 -> 文本),要通過下面的方法來完成。DateFormat是抽象類,我們需要使用其子類SimpleDateFormat來創建對象。
//創建日期格式化對象,在獲取格式化對象時可以指定風格
DateFormat df= new SimpleDateFormat("yyyy-MM-dd");//對日期進行格式化
Date date = new Date(124355676160L);
String str_time = df.format(date);
System.out.println(str_time);//1973年12月10日
l DateFormat類的作用:即可以將一個Date對象轉換爲一個符合指定格式的字符串,也可以將一個符合指定格式的字符串轉爲一個Date對象。
指定格式的具體規則我們可參照SimpleDateFormat類的說明,這裏做簡單介紹,規則是在一個字符串中,會將以下字母替換成對應時間組成部分,剩餘內容原樣輸出:
l 當出現y時,會將y替換成年
2 當出現M時,會將M替換成月
3 當出現d時,會將d替換成日
4 當出現H時,會將H替換成時
5 當出現m時,會將m替換成分
6 當出現s時,會將s替換成秒
2.DateFormat類常用方法
format方法,用來將Date對象轉換成String
parse方法,用來將String轉換成Date(轉換時,該String要符合指定格式,否則不能轉換)。
代碼演示:
練習一:把Date對象轉換成String
Date date = new Date(124355676160L);
DateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
String str = df.format(date);
System.out.println(str);
//str中的內容爲1973年12月10日
練習二:把String轉換成Date對象
String str = "1973年12月10日";
DateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
Date date = df.parse( str );
System.out.println(str);
Calendar類概述:
Calendar是日曆類,在Date後出現,替換掉了許多Date的方法。該類將所有可能用到的時間信息封裝爲靜態成員變量,方便獲取。
Calendar爲抽象類,由於語言敏感性,Calendar類在創建對象時並非直接創建,而是通過靜態方法創建,將語言敏感內容處理好,再返回子類對象,如下:
Calendar類靜態方法
Calendar c = Calendar.getInstance(); //返回當前時間
Calendar類常用方法:
public int get(int field) //獲取時間字段值,字段參見幫助文檔
YEAR 年
MONTH 月,從0開始算起,最大11;0代表1月,11代表12月。
DATE 天
HOUR 時
MINUTE分
SECOND秒
代碼演示:
Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
public void add(int field,int amount) //指定字段增加某值
代碼演示:
Calendar c = Calendar.getInstance();
//修改當前時間爲3天后
c.add(Calendar.DATE, 3);
//修改當前時間爲5小時後
c.add(Calendar.HOUR, 5);
public final void set(int field,int value)//設置指定字段的值
代碼演示:
Calendar c = Calendar.getInstance();
//設置時間爲2020年5月20日
c.set(Calendar.YEAR, 2020);
c.set(Calendar.MONTH, 4);
c.set(Calendar.DATE, 20);
public final Date getTime() //獲取該日曆對象轉成的日期對象
代碼演示:
Calendar c = Calendar.getInstance();
Date d = c.getTime();
注意事項:西方星期的開始爲週日,中國爲週一。
在Calendar類中,月份的表示是以0-11代表1-12月。
日期是有大小關係的,時間靠後,時間越大。
上述總結:
l Date: 日期/時間類
構造方法:
public Date()// 系統當前日期時間
public Date(long date) 得到一個1970年1月1日0點這個時間基礎上,加上參數date毫秒值對應的日期時間
方法:
public long getTime() 獲取日期所對應的毫秒值
2 DateFormat:是日期/時間格式化子類的抽象類, 使用其子類SimpleDateFormat 實例化
構造方法:
public SimpleDateFormat() 默認的格式化操作
public SimpleDateFormat(String pattern) 按照指定的格式,進行日期格式化
日期和時間模式
y 年
M 年中的月份
d 月份中的天數
H 一天中的小時數(0-23)
m 小時中的分鐘數
s 分鐘中的秒數
S 毫秒數
方法:
public final String format(Date date) 把日期 格式化成字符串
public Date parse(String source) 把日期字符串 轉換成 日期對象
3 Calendar:日曆類,可獲取日期中指定字段的值
方法:
public static Calendar getInstance() //獲取日期對象
public int get(int field) //獲取時間字段值
public void add(int field,int amount) //指定字段增加某值
public final void set(int field,int value)//設置指定字段的值
public final Date getTime() //獲取該日曆對象轉成的日期對象
4.Joda-Time (http://www.joda.org/joda-time/userguide.html)
架構概述
下面介紹Joda-Time的主要構建模塊。這些是即時,間隔,持續時間,週期,年代和時區的概念。接下來我們談一談關於界面在圖書館設計中的作用,這與標準略有不同。我們結束對包裝結構的幾句話。即時的使用示例會延遲到指南的以下部分。間隔,持續時間和週期的例子可以在文檔的“重要概念”部分的相應部分找到。
瞬間
Joda-Time中最常用的概念是即時的概念。“即時”定義爲從1970-01-01T00:00Z指定爲數毫秒的日期時間連續區中的時刻。毫秒的定義與日期或日曆中的JDK的定義一致。這兩個API之間的互操作非常簡單。
在Joda-Time中,一個瞬間由ReadableInstant接口表示。這個接口的主要實現和普通API用戶需要最熟悉的類是DateTime。DateTime是不可變的 - 一旦創建,值不會改變。因此,這個類可以安全地傳遞,並在多個線程中使用,而無需同步。
毫秒瞬間可以轉換成任何日期時間字段使用年表。爲了解決這個問題,在DateTime上提供了一些方法來作爲getter的最常用的日期和時間字段。
在這個概述中,我們將進一步討論年表概念。
DateTime的伴隨可變類是MutableDateTime。這個類的對象可以被修改,而且不是線程安全的。
ReadableInstant的其他實現包括Instant和已棄用的DateMidnight。
字段
DateTime的主要API 一直保持很小,僅限於獲取每個日曆字段的方法。因此,例如,通過調用getDayOfYear()方法可以檢索“日曆”日曆字段。有關字段及其說明的完整列表,請參閱字段參考。
屬性
然而,通過使用所謂的財產,有更多的權力可用。每個日曆字段都與這樣的屬性相關聯。因此,getDayOfYear()方法直接返回值的“day-of-year” 也與dayOfYear()方法返回的屬性相關聯。與DateTime關聯的屬性類是DateTime.Property。
瞭解財產的方法是充分利用API的祕訣。我們在本文後面的使用屬性上有更多的話要說。
間隔
的間隔在約達時間表示時間從一個時刻到另一時刻的間隔。這兩個時刻都是在日期時間連續統一時間完全指定的時間,完整的時區。
間隔實現爲半開放,也就是說開始時刻是包含的,但結束時刻是獨佔的。結束總是大於或等於開始。兩個終點都被限制在相同的年代和相同的時區。
提供了兩個實現,Interval和MutableInterval,都是ReadableInterval的特化。
持續時間
甲持續時間在約達時間表示以毫秒計的時間的持續時間。持續時間通常是從一個時間間隔獲得的。
持續時間是一個非常簡單的概念,實現也很簡單。他們沒有年代或時區,只有毫秒的時間。
持續時間可以被添加到一個瞬間,或者到一個時間間隔的任何一端來改變這些對象。在日期時間的數學,你可以說:
即時+持續時間=即時
目前,ReadableDuration接口只有一個實現:持續時間。
期
甲期間在約達時間表示一段時間中的字段來定義,例如,3年5月2天及7小時。這與持續時間的不同之處在於毫秒數不準確。通過指定與時間有關的時刻(包括時間順序和時區),一個時段只能被解析爲精確的毫秒數。
例如,考慮一個月的時間。如果你把這段時間加到2月1日(ISO)那麼你將會在3月1日。如果你在3月1日增加相同的時間,你將會在4月1日。但是在這兩種情況下增加的時間(以毫秒爲單位)是非常不同的。
作爲第二個例子,考慮在夏令時邊界添加1天。如果您使用一段時間來進行添加,那麼23或25小時將被適當添加。如果你創建了一個24小時的持續時間,那麼你最終會得到錯誤的結果。
期間是作爲一組int字段實現的。一段時間內的標準字段集合是年,月,周,日,時,分,秒和毫秒。所述PeriodType類允許這個組字段被限制,例如以elimate周。當將持續時間或時間間隔轉換爲時間段時,這是非常重要的,因爲計算需要知道應該填充哪些時間段。
方法存在期間獲得每個字段值。時期不與時間順序或時區有關。
可以將時間段添加到即時,或者間隔的任一末尾以更改這些對象。在日期時間的數學,你可以說:
即時+週期=即時
ReadablePeriod接口有兩個實現:Period和MutablePeriod。
年表
喬達時代的設計是基於年表。它是一個計算引擎,支持日曆系統的複雜規則。它封裝了按需使用的字段對象,將絕對時間瞬間分割成可識別的日曆字段,如“星期幾”。它實際上是一個可插拔的日曆系統。
年表的實際計算分爲Chronology類本身和字段類DateTimeField和DurationField。這三個類的子類一起構成了庫中的大部分代碼。大多數用戶將永遠不需要使用或直接引用子類。相反,他們將簡單地獲得年表,並將其用作單例,如下所示:
Chronology coptic = CopticChronology.getInstance();
在內部,所有的年表,領域等等都保持爲單身。因此,在使用Joda-Time時有一個初始設置成本,但之後只有主要API實例類(DateTime,Interval,Period等)具有創建和垃圾收集器成本。
雖然年代學是設計的關鍵,但它並不是使用API的關鍵!
對於大多數應用來說,年代學可以被忽略,因爲它將默認爲ISOC年代學。這適用於大多數用途。如果您在1582年10月15日之前需要準確的日期,或者Julian日曆在您感興趣的地區停止,那麼您可以更改它。如果您需要像以前所示的科普特日曆這樣的特定日曆,還可以更改它。
時區
年表類也支持時區功能。這是通過裝飾設計模式應用於底層年表。所述DateTimeZone類,可以訪問這些區主要通過一個工廠的方法,如下所示:
DateTimeZone zone = DateTimeZone.forID(“Europe / London”);
除了命名時區,Joda-Time還支持固定時區。最簡單的是UTC,它被定義爲一個常量:
DateTimeZone zoneUTC = DateTimeZone.UTC;
DateTimeZone zoneUTC = DateTimeZone.forOffsetHours(hours);
時區實施基於公共IANA 時區數據庫提供的數據。時區id的完整列表可以在這裏找到
Joda-Time提供了一個默認時區,在沒有指定時區的情況下,該時區在很多操作中都會使用。這在概念上類似於java.util.TimeZone類的默認時區。該值可以通過靜態方法訪問和更新:
DateTimeZone defaultZone = DateTimeZone.getDefault(); DateTimeZone.setDefault(的myZone);
接口使用
正如你所看到的,Joda-Time定義了許多在javadoc中可見的新接口。最重要的是目前有4個實現的ReadableInstant。其他重要的接口包括ReadableInterval和ReadablePeriod。這些目前分別被用作僅值類和可變類的概括。
這裏要提到的一個重點是Joda接口的使用方式與JDK Collections Framework接口不同。當使用集合接口(如List或Map)時,通常會將您的變量作爲List或Map的類型保存,只有在創建對象時才引用具體的類。
List list = new ArrayList(); Map map = new HashMap();
DateTime dt = new DateTime();
爲了獲得最大的靈活性,您可以選擇使用Joda-Time界面來聲明您的方法參數。接口上的方法可以獲得方法中使用的具體類。
公共無效進程(ReadableDateTime dateTime){ DateTime dt = dateTime.toDateTime(); }
包結構
包結構被設計爲將公共API中的方法與私有API分開。公共包是根包(在org.joda.time下)和格式包。私人包是基地,計時,轉換,領域和tz包。大多數應用程序不需要從私有包中導入類。
使用DateTime
施工
日期時間對象是通過使用DateTime構造函數創建的。默認的構造函數使用如下
DateTime dt = new DateTime();
要創建代表特定日期和時間的日期時間對象,可以使用初始化字符串:
DateTime dt = new DateTime(“2004-12-13T21:39:45.618-08:00”);
DateTime還提供其他構造函數來使用各種標準字段創建特定的日期和時間。這也允許使用任何日曆和時區。
JDK互操作性
的日期時間類有一個構造它接受一個對象作爲輸入。特別是這個構造函數可以傳遞一個JDK Date,JDK Calendar或者JDK GregorianCalendar(它也接受一個ISO8601格式的字符串,或者一個表示毫秒的Long對象)。這是與JDK互操作性的一半。與JDK的互操作性的另一半由返回JDK對象的DateTime方法提供。
因此,Joda DateTime和JDK Date之間的轉換可以如下進行
//從Joda到JDK DateTime dt = new DateTime(); 日期jdkDate = dt.toDate(); //從JDK到Joda dt = new DateTime(jdkDate);
同樣,對於JDK 日曆:
//從Joda到JDK DateTime dt = new DateTime(); 日曆jdkCal = dt.toCalendar(Locale.CHINESE); //從JDK到Joda dt = new DateTime(jdkCal);
和JDK GregorianCalendar:
//從Joda到JDK DateTime dt = new DateTime(); GregorianCalendar jdkGCal = dt.toGregorianCalendar(); //從JDK到Joda dt = new DateTime(jdkGCal);
查詢日期時間
日曆字段(計算的分離DateTimeField字段從日曆時刻(的表示)的DateTime)使一個強大和靈活的API。兩者之間的連接由屬性(DateTime.Property)維護,該屬性提供對該字段的訪問。
例如,直接獲取特定DateTime的星期值的方法涉及到調用方法
int iDoW = dt.getDayOfWeek();
public static final int MONDAY = 1; 公共靜態最終詮釋TUESDAY = 2; 公共靜態最終詮釋WEDNESDAY = 3; 公共靜態最終詮釋THURSDAY = 4; public static final int FRIDAY = 5; public static final int SATURDAY = 6; public static final int SUNDAY = 7;
訪問字段
直接方法對於簡單的使用來說很好,但是通過屬性/字段機制可以實現更多的靈活性。星期幾財產是通過
DateTime.Property pDoW = dt.dayOfWeek();
String strST = pDoW.getAsShortText(); //返回“Mon”,“Tue”等 String strT = pDoW.getAsText(); //返回“星期一”,“星期二”等
String strTF = pDoW.getAsText(Locale.FRENCH); //返回“Lundi”等
當然,該字段的原始整數值仍然可以被訪問爲
iDoW = pDoW.get();
實際上,實際上不會創建中間pDoW變量。如果在匿名中間對象上調用方法,代碼更容易閱讀。因此,例如,
strT = dt.dayOfWeek()。getAsText(); iDoW = dt.dayOfWeek()。get();
注意:對於獲取字段數值的單個情況,我們建議在主DateTime對象上使用get方法,因爲效率更高。
iDoW = dt.getDayOfWeek();
日期字段
該日期時間實現提供了標準的日曆字段的完整列表:
dt.getEra(); dt.getYear(); dt.getWeekyear(); dt.getCenturyOfEra(); dt.getYearOfEra(); dt.getYearOfCentury(); dt.getMonthOfYear(); dt.getWeekOfWeekyear(); dt.getDayOfYear(); dt.getDayOfMonth(); dt.getDayOfWeek();
正如您所期望的那樣,我們上面在星期幾示例中顯示的所有方法都可以應用於這些屬性中的任何一個。例如,要從日期時間中提取標準的月份,日期和年份字段,我們可以編寫
String month = dt.monthOfYear()。getAsText(); int maxDay = dt.dayOfMonth()。getMaximumValue(); boolean leapYear = dt.yearOfEra()。isLeap();
時間字段
另一組屬性訪問字段代表時間計算的日間持續時間。因此,爲了計算由DateTime表示的時刻的小時,分鍾和秒,我們將寫
int hour = dt.getHourOfDay(); int min = dt.getMinuteOfHour(); int sec = dt.getSecondOfMinute();
操作日期時間
DateTime對象具有值語義,並且在構造之後不能被修改(它們是不可變的)。因此,日期時間對象的最簡單的操作涉及構建新的日期時間作爲原始的修改副本。
警告:使用不可變類的常見錯誤是忘記將結果賦值給變量。請記住,在一個不可移動的對象上調用add或set方法對該對象沒有影響 - 只有結果被更新。
修改字段
一種方法是在屬性上使用方法。爲了回到我們之前的例子,如果我們希望通過將星期幾字段更改爲星期一來修改dt對象,我們可以通過使用屬性的setCopy方法來實現:
DateTime result = dt.dayOfWeek()。setCopy(DateTimeConstants.MONDAY);
要添加到日期,您可以使用addToCopy方法。
DateTime結果= dt.dayOfWeek()。addToCopy(3);
DateTime方法
完成類似計算的另一種方法是在DateTime對象本身上使用方法。因此,我們可以直接添加3天到dt,如下所示:
DateTime結果= dt.plusDays(3);
使用MutableDateTime
上述方法適用於涉及一個或兩個字段的簡單計算。在需要修改多個字段的情況下,創建日期時間的可變副本,修改副本並最終創建新的日期時間值會更有效。
MutableDateTime mdt = dt.toMutableDateTime(); //對mdt進行各種計算 ... DateTime結果= mdt.toDateTime();
改變時區
DateTime支持一些常見的時區計算。例如,如果你想在這個時間在倫敦的當地時間,你會做到以下幾點
//獲取默認時區的當前時刻 DateTime dt = new DateTime(); //翻譯倫敦當地時間 DateTime dtLondon = dt.withZone(DateTimeZone.forID(“Europe / London”));
這裏還有一個反向操作的支持,即獲得的日期時間(毫秒絕對值)相對應的時刻,倫敦擁有相同的本地時間作爲缺省時區存在的現在。這如下完成
//獲取默認時區的當前時刻 DateTime dt = new DateTime(); //找到倫敦將有同一時間的時刻 dtLondonSameTime = dt.withZoneRetainFields(DateTimeZone.forID(“Europe / London”));
通過調用DateTimeZone.getAvailableIDs()可以獲得一組所有TimeZone ID字符串(如“Europe / London” )。這裏提供了完整的可用時區列表。
改變年表
該日期時間類也有改變日曆的一種方法。這使您可以更改給定時刻的日曆。因此,如果你想獲得當前的日期時間,但在佛教日曆,你會這樣做
//獲取默認時區的當前時刻 DateTime dt = new DateTime(); dt.getYear(); //返回2004年 //改爲佛教年代 DateTime dtBuddhist = dt.withChronology(BuddhistChronology.getInstance()); dtBuddhist.getYear(); //返回2547
輸入和輸出
具有自定義格式的外部來源的日期時間信息是具有日期時間計算的應用程序的常見要求。寫入自定義格式也是一個常見的要求。
許多自定義格式可以用日期格式字符串來表示,這些字符串指定一系列日曆字段以及表示(數字,名稱字符串等)和字段長度。例如,模式“yyyy”將代表4位數的年份。其他格式不是很容易表示。例如,兩位數年份的模式“yy”並不唯一標識它所屬的世紀。在輸出上,這不會造成問題,但是輸入上有解釋的問題。
另外,現在有幾種常用的日期/時間序列化標準,特別是ISO8601。這些也必須由大多數日期時間的應用程序支持。
Joda-Time通過靈活的架構支持這些不同的需求。現在我們將描述這個架構的各種元素。
格式化程序
所有打印和解析都使用DateTimeFormatter對象執行。給定這樣一個對象fmt,解析執行如下
String strInputDateTime; //字符串以某種方式填充日期時間字符串 ... DateTime dt = fmt.parseDateTime(strInputDateTime);
String strOutputDateTime = fmt.print(dt);
標準格式化器
ISODateTimeFormat類提供了對基於ISO8601的標準格式的支持。這提供了許多工廠方法。
例如,如果您想要使用datetime的ISO標準格式,即yyyy-MM-dd'T'HH:mm:ss.SSSZZ,則可以將fmt初始化爲
DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
自定義格式化程序
如果您需要一個自定義格式化程序,可以用格式模式來描述,則可以使用DateTimeFormat類提供的工廠方法。因此,要得到一個4位數的年份,2位數的月份和2位數的日期的格式化程序,即yyyyMMdd的格式,你會做
DateTimeFormatter fmt = DateTimeFormat.forPattern(“yyyyMMdd”);
您可能需要打印或解析特定的語言環境。這是通過在格式化程序上調用withLocale方法來實現的,該方法返回基於原始格式的另一格式化程序。
DateTimeFormatter fmt = DateTimeFormat.forPattern(“yyyyMMdd”); DateTimeFormatter frenchFmt = fmt.withLocale(Locale.FRENCH); DateTimeFormatter germanFmt = fmt.withLocale(Locale.GERMAN);
怪異的格式化程序
最後,如果你有一個不容易被模式字符串表示的格式,Joda-Time架構公開了一個構建器類,可以用來構建一個自定義的格式化程序,這個格式化程序是以編程方式定義的。因此,如果您希望格式化程序打印並解析“22-Jan-65”形式的日期,則可以執行以下操作:
DateTimeFormatter fmt = new DateTimeFormatterBuilder() .appendDayOfMonth(2) .appendLiteral( ' - ') .appendMonthOfYearShortText() .appendLiteral( ' - ') .appendTwoDigitYear(1956)// pivot = 1956 .toFormatter();
這種格式特別有趣的是兩位數的年份。由於對兩位數年份的解釋是不明確的,所以appendTwoDigitYear通過指定範圍的中點來獲取定義兩位數的100年範圍的額外參數。在這個例子中,範圍將是(1956 - 50)= 1906到(1956 + 49)= 2005。因此,04將是2004年,但07年將是1907年。這種轉換對於普通格式的字符串是不可能的, Joda時間格式體系結構。
直接訪問
爲了簡化對格式化器體系結構的訪問,已經在datetime類(如DateTime)上提供了方法。
DateTime dt = new DateTime(); String a = dt.toString(); 字符串b = dt.toString(“dd:MM:yy”); String c = dt.toString(“EEE”,Locale.FRENCH); DateTimeFormatter fmt = ...; String d = dt.toString(fmt);
高級功能
更改當前時間
Joda-Time允許您更改當前時間。所有獲取當前時間的方法都是通過DateTimeUtils進行的。這樣可以改變當前的時間,這對測試非常有用。
//查詢當前時間總是返回同一時間 DateTimeUtils.setCurrentMillisFixed(米利斯); //抵消實時 DateTimeUtils.setCurrentMillisOffset(米利斯);
轉換器
API中每個主要具體類的構造函數都將Object作爲參數。這被傳遞到轉換器子系統,該子系統負責將對象轉換爲Joda-Time可接受的對象。例如,轉換器可以將JDK Date對象轉換爲DateTime。如果需要,您可以將自己的轉換器添加到Joda-Time提供的轉換器中。
安全
Joda-Time包含了針對敏感更改的標準JDK安全機制。這些包括更改時區處理程序,更改當前時間和更改轉換器。有關詳細信息,請參閱JodaTimePermission。