聲明:此筆記為根據(jù)黑馬程序員的“2020新版JDK8日期API解析”手打創(chuàng)作
源碼提却Х恰:
鏈接:https://pan.baidu.com/s/1aIJFugm-yGnjS2UAD-IY0w
提取碼:oopm
?不妨點個贊哦!
附加內(nèi)容? ? ? ??
jdk11中查看的java.util.Date類中可用方法
???????????????????????????一胸梆、 日期類API導(dǎo)學(xué)
設(shè)計初衷:Java原本自帶的java.util.Date和java.util.Calendar類踊谋,實際上兩種類有線程不安全的風(fēng)險(雖然學(xué)習(xí)的時候處于單線程環(huán)境并不會出現(xiàn)問題)护赊,但是之后到了企業(yè)中還是可能會增加學(xué)習(xí)成本给赞,重新學(xué)習(xí)如何處理時間,所以推出了這個Java8的最新時間類庫的講解蓬坡,希望降低學(xué)生的學(xué)習(xí)成本猿棉,能夠更快的融入到企業(yè)開發(fā)實戰(zhàn)中去。
課程目標(biāo)
*? ? 掌握J(rèn)ava8中提供的java.time包中的常用日期與相關(guān)方法
*? ? 可以從java.util包下的日期類相關(guān)類過度到j(luò)ava.time包下的日期類
*? ? 掌握J(rèn)ava8中的日期與字符串之間的相互轉(zhuǎn)換
學(xué)習(xí)此課程需要的基礎(chǔ)知識
*? ? java.util.Date與java.util.Calendar類的相關(guān)基礎(chǔ)知識
*? ? 線程相關(guān)的基礎(chǔ)知識
開發(fā)環(huán)境
*? ? IDEA + JDK1.8
適合人群
*? ? Java初學(xué)者
*? ? 再企業(yè)中有從老版本的日期類轉(zhuǎn)換到新版本的日期類需求的人員
? ? ? ? ? ? ? ? ? ? ? ? ? ? 二屑咳、 老版本API計算困難問題
為什么會出現(xiàn)新的日期類API
JAVA面世之初萨赁,標(biāo)準(zhǔn)庫就引入了兩種用于處理日期和時間的類,它們是java.util.Datejava.util.Calendar乔宿。而前者堪稱類糟糕的設(shè)計典范位迂,瀏覽API可以發(fā)現(xiàn)访雪,從Java1.1開始详瑞,Date 類中的所有方法就已經(jīng)被棄用,Java1.1推薦采用Calendar類處理日期和時間臣缀,但是這個類同樣存在不少問題坝橡。
對于日期的計算困難問題
毫秒值與日期直接轉(zhuǎn)換比較繁瑣,其次通過毫秒值來計算時間的差額步驟較多
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?三精置、老版本API線程不安全問題
SimpleDateFormat類是線程不安全的计寇,在多線程的情況下,全局共享一個SimpleDateFormat類中的Calendar對象有可能會出現(xiàn)異常脂倦。
另外一個問題就是在java.util.Date和java.util.Calendar類之前番宁,枚舉類型(ENUM)還沒有出現(xiàn),所以在字段中使用整數(shù)常量導(dǎo)致整數(shù)常量都是可變的赖阻,而不是線程安全的蝶押。? ? ? ? ? ? ? ? ? ? ? 為了處理 實際開發(fā)中遇到的問題,標(biāo)準(zhǔn)庫隨后引入了java.sql.Date作為java.util.Date的子類火欧,但是還是沒能徹底解決問題棋电。最終JavaSE 8中引入了java.time包茎截,這種全新的包從根本上解決了長久以來存在的諸多弊端,java.time包基于Joda-Time庫構(gòu)建赶盔,是一種免費的開源解決方案企锌,實際上在Java 8沒有出現(xiàn)之前,公司中已經(jīng)廣泛使用Joda-Time來解決Java中的日期與時間問題于未,Joda-Time的設(shè)計團隊也參與了java.time包的開發(fā)撕攒。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 四、老版本API使用規(guī)范問題
? ? ? ? ? ? ? ? ? ? ? ? 五沉眶、java.time包->常用類的概述和功能介紹
Instant類
? ? Instant類對時間軸上的單一瞬時點建模打却,可以用于記錄應(yīng)用程序中的事件時間戳,之后學(xué)習(xí)的類型轉(zhuǎn)換中谎倔,均可以使用Instant類作為中間類完成轉(zhuǎn)換柳击。
Duration類
? ? Duration類表示秒或納秒時間間隔,適合處理較短的時間片习,需要更高的精確性捌肴。
Period類
? ? Period類表示一段時間的年、月藕咏、日状知。
LocalDate類
? ? LocalDate是一個不可變的日期時間對象,表示日期孽查,通常被視為年月日饥悴。
LocalTime類
? ? LocalTime是一個不可變的日期時間對象,代表一個時間盲再,通常被看作是小時-秒西设,時間表示為納秒精度。
LocalDateTime類
? ? LocalDateTime類是一個不可變的日期時間對象答朋,代表日期時間贷揽,通常被視為年-月-日=時-分-秒。
ZonedDateTime類
? ? ZonedDateTime是具有時區(qū)的日期時間的不可變表示梦碗,此類存儲所有日期和時間字段禽绪,精度為納秒,時區(qū)為區(qū)域偏移量洪规,用于處理模糊的本地日期時間印屁。
now方法在日期/時間類的使用
Date-Time API中的所有類均生成不可變實例,它們是線程安全的斩例,并且這些類不提供公共構(gòu)造函數(shù)雄人,也就是說沒辦法通過new的方式直接創(chuàng)建,需要采用工廠方法加以實例化樱拴。? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? 六柠衍、now方法在日期時間類中的應(yīng)用1
?now方法可以根據(jù)當(dāng)前日期或時間創(chuàng)建實例洋满。
? ? ? ? ? ? ? ? ? ? ? ? ?七、now方法在日期時間類中的應(yīng)用2
不僅僅是以上提供的及各類可以使用now方法珍坊,Java8的Time包種還提供了其它幾個類可以更精準(zhǔn)的獲取某些信息牺勾。
Year類(表示年)
YearMonth類(表示年月)
MonthDay類(表示月日)
? ? ? ? ? ? ? ? ? ? ? ? 八、of方法在日期/時間類的應(yīng)用
指定任意時間節(jié)點
of方法可以根據(jù)給定的參數(shù)生成對應(yīng)的日期/時間對象阵漏,基本上每個基本類都有of方法用于生成的對應(yīng)的對象驻民,而且重載形式對邊,可以根據(jù)不同的參數(shù)生成對應(yīng)的數(shù)據(jù)履怯。
? ? ? ? ? ? ? ? ? ? ? ? ?九回还、時區(qū)信息的獲取(拓展)
在學(xué)習(xí)ZonedDateTime的時候叹洲,發(fā)現(xiàn)這個對象里面封裝的不僅有時間日期柠硕,并且還有偏移量+時區(qū),那么時區(qū)如何在Java中獲取呢运提?通過提供的一個類ZonedId的getAvailableZoneIds方法可以獲取到一個Set集合蝗柔,集合中封裝了600個時區(qū)。
? ? ? ? ? ? ? ? ? ? ? ? 十民泵、添加時區(qū)信息與獲取其它時區(qū)時間
我們可以通過給 LocalDateTimem添加時區(qū)信息來查看到不同時區(qū)的時間癣丧,比如說 LocalDateTime中當(dāng)前封裝的是上海時間,那么想知道此時此刻栈妆,紐約的時間是多少胁编,就可以將紐約的時區(qū)Id添加進去,就可以查看到了鳞尔,方式如下:
*? ? 封裝時間 LocalDateTime 并添加時區(qū)信息嬉橙。
*? ? 更改時區(qū)信息查看對應(yīng)時間。
? ? ? ? ? ? ? ? ? ? ? ? ? 十一铅檩、Month枚舉類的使用
java.time包中引用了Month的枚舉類憎夷,Month中包含標(biāo)準(zhǔn)日歷中的12個月份的常量(從JANUARY到DECEMEBER)也提供了一些方便的方法供我們使用莽鸿。
推薦在初始化LocalDate和LocalDateTime對象的時候昧旨,月份的參數(shù)使用枚舉的方式傳入,這樣更簡單易懂而且不易出錯祥得,因為如果是老的思維兔沃,Calendar傳入0的話,那么會出現(xiàn)異常级及。
? ? ? ? ? ? ? ? ? ? ? ? ? ? 十二乒疏、章節(jié)練習(xí)(1)
? ? ? ? ? ? ? ? ? ? ? ? ? ?十三、plus方法在LocalDate中的使用
想要修改某個日期/時間對象的現(xiàn)有實例時饮焦,我們可以使用 plus和 minus方法來完成操作怕吴。
Java8中日期時間相關(guān)的API中的所有實例都是不可改變的窍侧,一旦創(chuàng)建LocalDate,LocalTime转绷,LocalDateTime就無法修改他們(類似于String)伟件,這對于線程安全時非常有利的。
plus方法在LocalDate與LocalTime中的使用
*? ? LocalDate中定義了多種對日期進行增減操作的方法议经。
? ? LocalDate plusDay(long days) 增加天數(shù)
? ? LocalDate plusWeeks(long weeks) 增加周數(shù)
? ? LocallDate plusMonths(long months) 增加月數(shù)????
? ? LocalDate plusYears(long years) 增加年數(shù)
minus方法與以上類似斧账。
? ? ? ? ? ? ? ? ? ? ? ? ?十四、plus方法在LocalTime中的使用
LocalTime中定義了多種對事件進行增減操作的方法
LocalTime plusNanos(long nanos) 增加納秒
LocalTime plusSeconds(long seconds) 增加秒
LocalTime plusMinutes(long minutes) 增加分鐘
LocalTime plusHours(long hours) 增加小時
? ? ? ? ? ? ? ? ? ? ? ? ? ?十五煞肾、plus的單獨使用方式1
本文中都是使用plusXXX的方法進行演示咧织,實際上也有對應(yīng)的減少方法,以minus開頭的方法對應(yīng)的即為減少籍救,實際上也有對應(yīng)的減少方法习绢,以minus開頭的方法對應(yīng)的即為減少,實際上minus方法調(diào)用的也是plus方法蝙昙,只不過傳入的參數(shù)是負(fù)數(shù)毯炮。
plus 和 minus 方法的應(yīng)用
剛才學(xué)習(xí)到的plusXXX相關(guān)的方法都是添加了數(shù)值到具體的某一項上,根據(jù)觀察還有兩個單獨的plus方法耸黑,接下來我們來學(xué)習(xí)這兩個單獨的plus方法桃煎。
plus(long amountToadd, TemporalUnit unit)? LocalTime
plus(TemporalAmount amoutToadd)? ? ? ?LocalTime
TemporalAmount 是一個接口,當(dāng)接口作為方法的參數(shù)的時候大刊,實際上傳入的是接口的實現(xiàn)類對象为迈,根據(jù)查看這個接口的體系,可以看到這個接口有一個實現(xiàn)類缺菌,名字叫做Period葫辐,在學(xué)習(xí)第一節(jié)的時候,說明了這個 嘞表示一段時間伴郁。
如何使用Period來表示一段時間呢耿战?這個類本身提供了of(int year, int month, int day)來表示,例如:Period.of(1,2,3)返回的對象即為1年2個月3天這么一個時間段焊傅。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?十六剂陡、plus的單獨使用方式2
plus(long amountToadd, TemporalUnit unit)
在實際開發(fā)過程中,可能還會更精準(zhǔn)的去操作日期或者說增加一些特殊的時間狐胎,比如說1個世紀(jì)鸭栖、1個半天,1千年握巢,10年等晕鹊,Java8提供了這些日期的表示方式而不需要去單獨進行計算了。
TemporalUnit是一個接口,通過查看體系接口發(fā)現(xiàn),可以使用子類ChronoUnit來表示溅话,ChronoUnit封裝了很多時間段供我們使用晓锻。
? ? ? ? ? ? ? ? ? ? ? ? ? ? 十七、with方法的使用方式1
with方法在LocalDateTime類的應(yīng)用
如果不需要對日期進行加減而是要直接修改日期的話飞几,那么可以使用with方法带射,with方法提供了很多種修改時間的方式
LocalDateTime withNano(int i) 修改納秒
LocalDateTime withSecond(int i) 修改秒
LocalDateTime withMinute(int i) 修改分支
LocalDateTime withHour(int i) 修改小時
LocalDateTime withDayOfMonth(int i) 修改日
LocalDateTime withMonth(int i) 修改月
LocalDateTime withYear(int i) 修改年
? ? ? ? ? ? ? ? ? ? ? ? ? 十八、with方法的使用方式2
with(TemporalField field, long newValue)
temporalField是一個接口循狰,通過查看體系結(jié)構(gòu)窟社,可以使用它的子類
ChronoField,ChronoField中封裝了一些日期時間中的組成成分,可以直接選擇之后傳入第二個參數(shù)進行修改绪钥。
例如:with(ChronoField.DAY_OFMONTH,1);將日期中的月份中的天數(shù)改為1
例如:with(ChronoField.YEAR,2021);將日期中的年份改為2021灿里。