當前位置:
首頁 > 知識 > 深入理解Java常用類——時間日期

深入理解Java常用類——時間日期

除了String這個類在日常的項目中比較常用之外,有關時間和日期的操作也是經常遇到的,本篇就講詳細介紹下Java API中對時間和日期的支持。其實在Java 8之前時間日期的API並不是很好用,以至於人們在項目中大多使用的是一個第三方庫 Joda-Time,當然Java 8 吸收了該庫的大部分優點,改進了相關API,現在的時間日期處理介面相對以前來說是好用很多,本篇也將學習下這個優秀的第三方庫。下面是本篇主要涉及內容:

  • 古老的Date類

  • 處理年月日的年曆類Calendar

  • 格式化字元串和日期對象的DateFormat格式轉換類

  • 好用的SimpleDateFormat實現類

  • Joda-Time庫

一、古老的Date類

Date這個類自jdk1.0開始就被設計出來, 從它的源代碼中我們也是可以看出來,Date類曾經扮演過很重要的角色,jdk早期的版本中有關日期和時間的操作幾乎都是由Date類完成的,下面我們一起看看它的源碼:

深入理解Java常用類——時間日期

首先Date中有封裝一個long類型的變數,這個變數是整個時間日期操作的對象,也就是我們使用該變數代表時間和日期。下面說明它是如何表示時間和日期的。所有計算機中的時間都是用一個整數表示的,該整數的值代表的是距離格林尼治標準時間(1970年1月1日0時0分0秒)的毫秒數,也就是說fastTime值為1000的時候代表時間為1970年1月1日0時0分1秒。至於為什麼是這個時間,由於種種歷史原因大家也可以去了解下,此處不再贅述。

由於該類中大部分方法都被註解了@Deprecated,已經不再推薦使用了,所以接下來我們主要還是看看其中還保留著的方法。只剩下兩個構造方法:

深入理解Java常用類——時間日期

只推薦使用上述兩個構造方法來構造我們的Date對象,一個是默認無參構造器(內部調用本地函數獲取系統當前時間計算與標準時間的毫秒差值),另一個則需要手動傳入一個毫秒值構造Date對象。

剩下的則主要是一些獲取和設置fastTime的函數,以及比較日期大小的函數,其他的都被註解了,至於上述這些函數,代碼相對簡單此處不再贅述。

二、處理年月日的年曆類Calendar

以前我們是可以使用Date來處理日期年月日的,但是由於該類不支持國際化等原因,現在其中大部分方法被註解,不再推薦使用,現在的Date類更像是代表著某一個時刻的對象,而處理年月日的這種轉換則完全交給了Calendar類處理。所以Calendar目前是日期時間處理中的核心類,接下來我們看看其中源碼:

深入理解Java常用類——時間日期

在Calendar的內部封裝了17個靜態常量,這些常量將會作為索引用來檢索fields屬性,例如:fields[YEAR]將返回當前毫秒值對應的日期時間的年份部分,fields[MONTH]將返回的是月份部分的值等等。至於這些值是哪裡來的,等我們介紹到後續源碼的時候再說明,此處只需要理解這些常量的作用即可。

該類是抽象類,我們使用工廠方法獲取該類實例:

深入理解Java常用類——時間日期

主要有四個方法用於創建Calendar實例,其實內部調用的是同一的方法只是傳入的參數的值不同。創建一個Calend 實例需要兩個參數,一個是TimeZone時區,另一個是Locale語言國家。因為每個國家或地區他們表示時間的形式是不一樣的,所以我們需要通過這兩個參數確定具體需要使用的格式,當然是以本地時間作為fastTime的值的,如果我們沒有指定時區和國家語言,那麼將會默認使用本機系統信息。接下來我們看如何通過獲取到Calendar實例完成對日期時間進行計算。

我們有獲取和設置內部代表毫秒的time屬性:

深入理解Java常用類——時間日期

也有獲取上述介紹的17中屬性的方法:

深入理解Java常用類——時間日期

其中complete方法就是調用了本地函數完成對fields屬性中沒有值的元素賦值。 調用internalGet方法其實就是調用的fields[field],為我們返回指定屬性的結果值。我們可以看個例子:

深入理解Java常用類——時間日期

結果如下:

深入理解Java常用類——時間日期

上述代碼運行在不同的時候的結果都是不一樣的,寫作時的時間:2017/5/29 14:02。需要注意一點的是,month屬性是從0開始的,也就是0表示一月,4表示5月,星期也是一樣。此外,上述中的AM_PM表示的是上下午的概念,上午為0,下午為1。

除了獲取有關日期時間的信息,我們也是有可以用來設置他們的方法的:

深入理解Java常用類——時間日期

除此之外,還有一些通過計算來設置Calendar屬性的方法:

深入理解Java常用類——時間日期

例如:

深入理解Java常用類——時間日期

改程序將輸出:2017 2027。還有一個roll方法也很有意思:

深入理解Java常用類——時間日期

我們需要記住的是,roll方法完成的工作是和add一樣的,只是add方法處理了越界的特殊情況(越界會向上進一位),而roll方法會重新回到初始值再加。例如:

深入理解Java常用類——時間日期

上述程序我們設置Calendar日期為2017/12,針對上述兩種方式add和roll,輸出結果如下:

深入理解Java常用類——時間日期

深入理解Java常用類——時間日期

對於12月,add方法加5之後,month為5月但是已經是2018年,而roll則沒有向上進位,這就是區別,實際使用的時候還需加以區分。當然,如果你對某個屬性的範圍不是很明確,可以使用下面兩個方法獲取:

深入理解Java常用類——時間日期

還有一些有關比較的函數,和Date是類似的:

深入理解Java常用類——時間日期

三、DateFormat處理格式轉換

DateFormat是一個抽象類,該類主要用於實現Date對象和字元串之間相互轉換, 涉及到兩個轉換的方法:

深入理解Java常用類——時間日期

除此之外,DateFormat還提供了四個靜態常量,代表著四種不同的風格。不同的風格輸出信息的內容詳盡程度不同,默認的風格是MEDIUM。(折中)

深入理解Java常用類——時間日期

該類是抽象類,一樣需要使用靜態工廠獲取實例對象。

深入理解Java常用類——時間日期

很明顯,有三種不同的方式來獲取DateFormat實例,每種方式有三個重載,getDateInstance用來處理日期,getTimeInstance用來處理時間,getDateTimeInstance既可以處理日期,也可以處理時間。我們通過一個例子看看他們之間的區別:

深入理解Java常用類——時間日期

輸出結果:

深入理解Java常用類——時間日期

很顯然,三者之間的區別也是不言而喻。對於他們另外兩個重載來說,一個重載提供修改輸出風格,另一個提供修改locale。無論是上述的哪一種工廠方法,在他們內部都調用的是同一個函數

深入理解Java常用類——時間日期

四個參數,所有我們在調用工廠方法的時候沒有提供的參數值都會使用默認值。至於該方法具體是如何實現創建一個實例返回的我們就暫時不深究了。至於其他的一些方法,我們將在其子類SimpleDateFormat中學習。

四、優秀的實現類SimpleDateFormat

SimpleDateFormat是DateFormat的一個優秀的實現類,它增強了一個重要的性質。它允許自定義格式輸出模板。構造SimpleDateFormat實例的時候,可以傳入一個pattern作為輸出模板。看個例子:

深入理解Java常用類——時間日期

輸出結果:

深入理解Java常用類——時間日期

上述的代碼中,字元串yyyy年MM月dd日 E HH時mm分ss秒就是一個模板pattern,其中:

  • yyyy表示使用四位數字輸出年份

  • MM表示使用兩位數字表示月份

  • dd表示使用兩位數字表示日

  • E表示星期幾

  • HH表示使用兩位數字表示小時(24以內)

  • mm和ss分別表示分鐘和秒數

其中需要注意一點的是,m這個字母大寫狀態被用作表示月份,小寫狀態被用作表示分鐘,不能混用二者。除了可以使用HH表示小時以外,hh也可以表示小時,只是它是12的(上午和下午)。當然我們也可以逆向操作:

深入理解Java常用類——時間日期

輸出結果:

深入理解Java常用類——時間日期

五、開源第三方庫Joda-Time

Joda-Time庫中的內容還是很多的,我們簡單了解下基本的使用即可,至於深入學習該庫,大家可以自行嘗試,此處限於篇幅,不再贅述。在該庫中DateTime相當於jdk中Calendar,主要完成對日期年月日的計算操作。首先我們通過簡單易理解的方式創建DateTime的實例對象:

深入理解Java常用類——時間日期

創建一個日期實例比Calendar中為每個屬性set值方便多了。在該庫中獲取日期的操作被分解了,不像Calendar中共享一個int數組。

深入理解Java常用類——時間日期

我們也可以直接使用DateTime的tostring方法來實現將日期轉換成指定pattern的字元串,例如:

深入理解Java常用類——時間日期

上述代碼將會把日期類型按照指定的模板輸出,該Joda-Time庫中內容很多,此處就簡單介紹到這, 感興趣的同學可以自行研究,該庫的核心優勢就在於它將很多複雜的操作分解為單個簡單操作,這也是我們程序設計中核心的思維方式。

有關Java中日期和時間的內容本篇已經簡單介紹完了,有理解不到之處,望大家指出,相互學習!


學習Java的同學注意了!!!

學習過程中遇到什麼問題或者想獲取學習資源的話,歡迎加入Java學習交流群495273252,我們一起學Java!

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Java團長 的精彩文章:

Java中String通過引用傳遞問題詳細解析
Java面向對象總結
深入學習Java同步器AQS
雜談:關於程序員職業發展的兩三事

TAG:Java團長 |

您可能感興趣

深入理解Flask
深入理解消息中間件技術之RabbitMQ服務
深入理解 ES Modules
MapReduce Shuffle深入理解
入門 | 通過 Q-learning 深入理解強化學習
更深入理解 Python 中的迭代
通過 Q-learning 深入理解強化學習
Glibc堆漏洞利用基礎-深入理解ptmalloc2 part1
Joker復盤比賽:Uzi對射程理解更深
深入理解 Web Server 原理與實踐:Nginx
用深度學習理解遙感圖像,識別效率提升90倍,PaddlePaddle&中科院遙感地球所
深入理解Flutter引擎線程模式
Redhat Ceph存儲之「深入理解Ceph架構」
Apache Shiro中許可權應用指南:深入理解許可權
命理解析:Jeff Bezos
用汽車比喻理解OOP-Jonathan Kuhl
我所理解的 Smartisan OS
如何深入理解以太坊gas機制
Fnatic打野接受採訪:一直不理解為什麼Caps離開
深入理解Windows頁幀號(一)