深度思考JDK8中日期類(lèi)型該如何使用詳解
在JDK8之前,處理日期時(shí)間,我們主要使用3個(gè)類(lèi), Date
、 SimpleDateFormat
和 Calendar
。
這3個(gè)類(lèi)在使用時(shí)都或多或少的存在一些問(wèn)題,比如 SimpleDateFormat
不是線(xiàn)程安全的,
比如 Date
和 Calendar
獲取到的月份是0到11,而不是現(xiàn)實(shí)生活中的1到12,關(guān)于這一點(diǎn),《阿里巴巴Java開(kāi)發(fā)手冊(cè)》中也有提及,因?yàn)楹苋菀追稿e(cuò):
不過(guò),JDK8推出了全新的日期時(shí)間處理類(lèi)解決了這些問(wèn)題,比如 Instant
、 LocalDate
、 LocalTime
、 LocalDateTime
、 DateTimeFormatter
,在《阿里巴巴Java開(kāi)發(fā)手冊(cè)》中也推薦使用 Instant
、
LocalDateTime
、 DateTimeFormatter
:
但我發(fā)現(xiàn)好多項(xiàng)目中其實(shí)并沒(méi)有使用這些類(lèi),使用的還是之前的 Date
、 SimpleDateFormat
和 Calendar
,所以本篇博客就講解下JDK8新推出的日期時(shí)間類(lèi),主要是下面幾個(gè):
- Instant
- LocalDate
- LocalTime
- LocalDateTime
- DateTimeFormatter
1. Instant
1.1 獲取當(dāng)前時(shí)間
既然 Instant
可以代替 Date
類(lèi),那它肯定可以獲取當(dāng)前時(shí)間:
Instant instant = Instant.now(); System.out.println(instant);
輸出結(jié)果:
2020-06-10T08:22:13.759Z
細(xì)心的你會(huì)發(fā)現(xiàn),這個(gè)時(shí)間比北京時(shí)間少了8個(gè)小時(shí),如果要輸出北京時(shí)間,可以加上默認(rèn)時(shí)區(qū):
System.out.println(instant.atZone(ZoneId.systemDefault()));
輸出結(jié)果:
2020-06-10T16:22:13.759+08:00[Asia/Shanghai]
1.2 獲取時(shí)間戳
Instant instant = Instant.now(); // 當(dāng)前時(shí)間戳:單位為秒 System.out.println(instant.getEpochSecond()); // 當(dāng)前時(shí)間戳:單位為毫秒 System.out.println(instant.toEpochMilli());
輸出結(jié)果:
1591777752
1591777752613
當(dāng)然,也可以通過(guò) System.currentTimeMillis()
獲取當(dāng)前毫秒數(shù)。
1.3 將long轉(zhuǎn)換為Instant
1)根據(jù)秒數(shù)時(shí)間戳轉(zhuǎn)換:
Instant instant = Instant.now(); System.out.println(instant); long epochSecond = instant.getEpochSecond(); System.out.println(Instant.ofEpochSecond(epochSecond)); System.out.println(Instant.ofEpochSecond(epochSecond, instant.getNano()));
輸出結(jié)果:
2020-06-10T08:40:54.046Z
2020-06-10T08:40:54Z
2020-06-10T08:40:54.046Z
2)根據(jù)毫秒數(shù)時(shí)間戳轉(zhuǎn)換:
Instant instant = Instant.now(); System.out.println(instant); long epochMilli = instant.toEpochMilli(); System.out.println(Instant.ofEpochMilli(epochMilli));
輸出結(jié)果:
2020-06-10T08:43:25.607Z
2020-06-10T08:43:25.607Z
1.4 將String轉(zhuǎn)換為Instant
String text = "2020-06-10T08:46:55.967Z"; Instant parseInstant = Instant.parse(text); System.out.println("秒時(shí)間戳:" + parseInstant.getEpochSecond()); System.out.println("豪秒時(shí)間戳:" + parseInstant.toEpochMilli()); System.out.println("納秒:" + parseInstant.getNano());
輸出結(jié)果:
秒時(shí)間戳:1591778815
豪秒時(shí)間戳:1591778815967
納秒:967000000
如果字符串格式不對(duì),比如修改成 2020-06-10T08:46:55.967
,就會(huì)拋出 java.time.format.DateTimeParseException
異常,如下圖所示:
2. LocalDate
2.1 獲取當(dāng)前日期
使用 LocalDate
獲取當(dāng)前日期非常簡(jiǎn)單,如下所示:
LocalDate today = LocalDate.now(); System.out.println("today: " + today);
輸出結(jié)果:
today: 2020-06-10
不用任何格式化,輸出結(jié)果就非常友好,如果使用 Date
,輸出這樣的格式,還得配合 SimpleDateFormat
指定 yyyy-MM-dd
進(jìn)行格式化,一不小心還會(huì)出個(gè)bug,比如去年年底很火的1個(gè)bug,我當(dāng)時(shí)還是截了圖的:
這2個(gè)好友是2019/12/31關(guān)注我的,但我2020年1月2號(hào)查看時(shí),卻顯示成了2020/12/31,為啥呢?格式化日期時(shí)格式寫(xiě)錯(cuò)了,應(yīng)該是 yyyy/MM/dd
,卻寫(xiě)成了 YYYY/MM/dd
,剛好那周跨年,就顯示成下一年,也就是2020年了,當(dāng)時(shí)好幾個(gè)博主寫(xiě)過(guò)文章解析原因,我這里就不做過(guò)多解釋了。
劃重點(diǎn):都說(shuō)到這了,給大家安利下我新注冊(cè)的公眾號(hào)「申城異鄉(xiāng)人」,歡迎大家關(guān)注,更多原創(chuàng)文章等著你哦,哈哈。
2.2 獲取年月日
LocalDate today = LocalDate.now(); int year = today.getYear(); int month = today.getMonthValue(); int day = today.getDayOfMonth(); System.out.println("year: " + year); System.out.println("month: " + month); System.out.println("day: " + day);
輸出結(jié)果:
year: 2020
month: 6
day: 10
獲取月份終于返回1到12了,不像 java.util.Calendar
獲取月份返回的是0到11,獲取完還得加1。
2.3 指定日期
LocalDate specifiedDate = LocalDate.of(2020, 6, 1); System.out.println("specifiedDate: " + specifiedDate);
輸出結(jié)果:
specifiedDate: 2020-06-01
如果確定月份,推薦使用另一個(gè)重載方法,使用枚舉指定月份:
LocalDate specifiedDate = LocalDate.of(2020, Month.JUNE, 1);
2.4 比較日期是否相等
LocalDate localDate1 = LocalDate.now(); LocalDate localDate2 = LocalDate.of(2020, 6, 10); if (localDate1.equals(localDate2)) { System.out.println("localDate1 equals localDate2"); }
輸出結(jié)果:
localDate1 equals localDate2
2.5 獲取日期是本周/本月/本年的第幾天
LocalDate today = LocalDate.now(); System.out.println("Today:" + today); System.out.println("Today is:" + today.getDayOfWeek()); System.out.println("今天是本周的第" + today.getDayOfWeek().getValue() + "天"); System.out.println("今天是本月的第" + today.getDayOfMonth() + "天"); System.out.println("今天是本年的第" + today.getDayOfYear() + "天");
輸出結(jié)果:
Today:2020-06-11
Today is:THURSDAY
今天是本周的第4天
今天是本月的第11天
今天是本年的第163天
2.6 判斷是否為閏年
LocalDate today = LocalDate.now(); System.out.println(today.getYear() + " is leap year:" + today.isLeapYear());
輸出結(jié)果:
2020 is leap year:true
3. LocalTime
3.1 獲取時(shí)分秒
如果使用 java.util.Date
,那代碼是下面這樣的:
Date date = new Date(); int hour = date.getHours(); int minute = date.getMinutes(); int second = date.getSeconds(); System.out.println("hour: " + hour); System.out.println("minute: " + minute); System.out.println("second: " + second);
輸出結(jié)果:
注意事項(xiàng):這幾個(gè)方法已經(jīng)過(guò)期了,因此強(qiáng)烈不建議在項(xiàng)目中使用:
如果使用 java.util.Calendar
,那代碼是下面這樣的:
Calendar calendar = Calendar.getInstance(); // 12小時(shí)制 int hourOf12 = calendar.get(Calendar.HOUR); // 24小時(shí)制 int hourOf24 = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); int milliSecond = calendar.get(Calendar.MILLISECOND); System.out.println("hourOf12: " + hourOf12); System.out.println("hourOf24: " + hourOf24); System.out.println("minute: " + minute); System.out.println("second: " + second); System.out.println("milliSecond: " + milliSecond);
輸出結(jié)果:
注意事項(xiàng):獲取小時(shí)時(shí),有2個(gè)選項(xiàng),1個(gè)返回12小時(shí)制的小時(shí)數(shù),1個(gè)返回24小時(shí)制的小時(shí)數(shù),因?yàn)楝F(xiàn)在是晚上8點(diǎn),所以 calendar.get(Calendar.HOUR)
返回8,而 calendar.get(Calendar.HOUR_OF_DAY)
返回20。
如果使用 java.time.LocalTime
,那代碼是下面這樣的:
LocalTime localTime = LocalTime.now(); System.out.println("localTime:" + localTime); int hour = localTime.getHour(); int minute = localTime.getMinute(); int second = localTime.getSecond(); System.out.println("hour: " + hour); System.out.println("minute: " + minute); System.out.println("second: " + second);
輸出結(jié)果:
可以看出,LocalTime只有時(shí)間沒(méi)有日期。
4. LocalDateTime
4.1 獲取當(dāng)前時(shí)間
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime:" + localDateTime);
輸出結(jié)果:
localDateTime: 2020-06-11T11:03:21.376
4.2 獲取年月日時(shí)分秒
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime: " + localDateTime); System.out.println("year: " + localDateTime.getYear()); System.out.println("month: " + localDateTime.getMonthValue()); System.out.println("day: " + localDateTime.getDayOfMonth()); System.out.println("hour: " + localDateTime.getHour()); System.out.println("minute: " + localDateTime.getMinute()); System.out.println("second: " + localDateTime.getSecond());
輸出結(jié)果:
4.3 增加天數(shù)/小時(shí)
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime: " + localDateTime); LocalDateTime tomorrow = localDateTime.plusDays(1); System.out.println("tomorrow: " + tomorrow); LocalDateTime nextHour = localDateTime.plusHours(1); System.out.println("nextHour: " + nextHour);
輸出結(jié)果:
localDateTime: 2020-06-11T11:13:44.979
tomorrow: 2020-06-12T11:13:44.979
nextHour: 2020-06-11T12:13:44.979
LocalDateTime
還提供了添加年、周、分鐘、秒這些方法,這里就不一一列舉了:
4.4 減少天數(shù)/小時(shí)
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime: " + localDateTime); LocalDateTime yesterday = localDateTime.minusDays(1); System.out.println("yesterday: " + yesterday); LocalDateTime lastHour = localDateTime.minusHours(1); System.out.println("lastHour: " + lastHour);
輸出結(jié)果:
localDateTime: 2020-06-11T11:20:38.896
yesterday: 2020-06-10T11:20:38.896
lastHour: 2020-06-11T10:20:38.896
類(lèi)似的, LocalDateTime
還提供了減少年、周、分鐘、秒這些方法,這里就不一一列舉了:
4.5 獲取時(shí)間是本周/本年的第幾天
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime: " + localDateTime); System.out.println("DayOfWeek: " + localDateTime.getDayOfWeek().getValue()); System.out.println("DayOfYear: " + localDateTime.getDayOfYear());
輸出結(jié)果:
localDateTime: 2020-06-11T11:32:31.731
DayOfWeek: 4
DayOfYear: 163
5. DateTimeFormatter
JDK8中推出了 java.time.format.DateTimeFormatter
來(lái)處理日期格式化問(wèn)題,《阿里巴巴Java開(kāi)發(fā)手冊(cè)》中也是建議使用 DateTimeFormatter
代替 SimpleDateFormat
。
5.1 格式化LocalDate
LocalDate localDate = LocalDate.now(); System.out.println("ISO_DATE: " + localDate.format(DateTimeFormatter.ISO_DATE)); System.out.println("BASIC_ISO_DATE: " + localDate.format(DateTimeFormatter.BASIC_ISO_DATE)); System.out.println("ISO_WEEK_DATE: " + localDate.format(DateTimeFormatter.ISO_WEEK_DATE)); System.out.println("ISO_ORDINAL_DATE: " + localDate.format(DateTimeFormatter.ISO_ORDINAL_DATE));
輸出結(jié)果:
如果提供的格式無(wú)法滿(mǎn)足你的需求,你還可以像以前一樣自定義格式:
LocalDate localDate = LocalDate.now(); System.out.println("yyyy/MM/dd: " + localDate.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")));
輸出結(jié)果:
yyyy/MM/dd: 2020/06/11
5.2 格式化LocalTime
LocalTime localTime = LocalTime.now(); System.out.println(localTime); System.out.println("ISO_TIME: " + localTime.format(DateTimeFormatter.ISO_TIME)); System.out.println("HH:mm:ss: " + localTime.format(DateTimeFormatter.ofPattern("HH:mm:ss")));
輸出結(jié)果:
14:28:35.230
ISO_TIME: 14:28:35.23
HH:mm:ss: 14:28:35
5.3 格式化LocalDateTime
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDateTime); System.out.println("ISO_DATE_TIME: " + localDateTime.format(DateTimeFormatter.ISO_DATE_TIME)); System.out.println("ISO_DATE: " + localDateTime.format(DateTimeFormatter.ISO_DATE));
輸出結(jié)果:
2020-06-11T14:33:18.303
ISO_DATE_TIME: 2020-06-11T14:33:18.303
ISO_DATE: 2020-06-11
6. 類(lèi)型相互轉(zhuǎn)換
6.1 Instant轉(zhuǎn)Date
JDK8中, Date
新增了 from()
方法,將 Instant
轉(zhuǎn)換為 Date
,代碼如下所示:
Instant instant = Instant.now(); System.out.println(instant); Date dateFromInstant = Date.from(instant); System.out.println(dateFromInstant);
輸出結(jié)果:
2020-06-11T06:39:34.979Z
Thu Jun 11 14:39:34 CST 2020
6.2 Date轉(zhuǎn)Instant
JDK8中, Date
新增了 toInstant
方法,將 Date
轉(zhuǎn)換為 Instant
,代碼如下所示:
Date date = new Date(); Instant dateToInstant = date.toInstant(); System.out.println(date); System.out.println(dateToInstant);
輸出結(jié)果:
Thu Jun 11 14:46:12 CST 2020
2020-06-11T06:46:12.112Z
6.3 Date轉(zhuǎn)LocalDateTime
Date date = new Date(); Instant instant = date.toInstant(); LocalDateTime localDateTimeOfInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); System.out.println(date); System.out.println(localDateTimeOfInstant);
輸出結(jié)果:
Thu Jun 11 14:51:07 CST 2020
2020-06-11T14:51:07.904
6.4 Date轉(zhuǎn)LocalDate
Date date = new Date(); Instant instant = date.toInstant(); LocalDateTime localDateTimeOfInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); LocalDate localDate = localDateTimeOfInstant.toLocalDate(); System.out.println(date); System.out.println(localDate);
輸出結(jié)果:
Thu Jun 11 14:59:38 CST 2020
2020-06-11
可以看出, Date
是先轉(zhuǎn)換為 Instant
,再轉(zhuǎn)換為 LocalDateTime
,然后通過(guò) LocalDateTime
獲取 LocalDate
。
6.5 Date轉(zhuǎn)LocalTime
Date date = new Date(); Instant instant = date.toInstant(); LocalDateTime localDateTimeOfInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); LocalTime toLocalTime = localDateTimeOfInstant.toLocalTime(); System.out.println(date); System.out.println(toLocalTime);
輸出結(jié)果:
Thu Jun 11 15:06:14 CST 2020
15:06:14.531
可以看出, Date
是先轉(zhuǎn)換為 Instant
,再轉(zhuǎn)換為 LocalDateTime
,然后通過(guò) LocalDateTime
獲取 LocalTime
。
6.6 LocalDateTime轉(zhuǎn)Date
LocalDateTime localDateTime = LocalDateTime.now(); Instant toInstant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); Date dateFromInstant = Date.from(toInstant); System.out.println(localDateTime); System.out.println(dateFromInstant);
輸出結(jié)果:
2020-06-11T15:12:11.600
Thu Jun 11 15:12:11 CST 2020
6.7 LocalDate轉(zhuǎn)Date
LocalDate today = LocalDate.now(); LocalDateTime localDateTime = localDate.atStartOfDay(); Instant toInstant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); Date dateFromLocalDate = Date.from(toInstant); System.out.println(dateFromLocalDate);
輸出結(jié)果:
Thu Jun 11 00:00:00 CST 2020
6.8 LocalTime轉(zhuǎn)Date
LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime); Instant instantFromLocalTime = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); Date dateFromLocalTime = Date.from(instantFromLocalTime); System.out.println(dateFromLocalTime);
輸出結(jié)果:
Thu Jun 11 15:24:18 CST 2020
7. 總結(jié)
JDK8推出了全新的日期時(shí)間類(lèi),如 Instant
、 LocaleDate
、 LocalTime
、 LocalDateTime
、 DateTimeFormatter
,設(shè)計(jì)比之前更合理,也是線(xiàn)程安全的。
《阿里巴巴Java開(kāi)發(fā)規(guī)范》中也推薦使用 Instant
代替 Date
, LocalDateTime
代替 Calendar
, DateTimeFormatter
代替 SimpleDateFormat
。
因此,如果條件允許,建議在項(xiàng)目中使用,沒(méi)有使用的,可以考慮升級(jí)下。
到此這篇關(guān)于JDK8中日期類(lèi)型該如何使用詳解的文章就介紹到這了,更多相關(guān)JDK8 日期類(lèi)型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- jdk7 中HashMap的知識(shí)點(diǎn)總結(jié)
- 使用jdk7的nio2操作文件拷貝和剪切示例
- 教你怎么在win10環(huán)境下安裝jdk8
- 解決mybatis-plus使用jdk8的LocalDateTime 查詢(xún)時(shí)報(bào)錯(cuò)的方法
- 面試官:怎么做JDK8的垃圾收集器的調(diào)優(yōu)(面試常問(wèn))
- JDK8并行流及串行流區(qū)別原理詳解
- CentOS7上以rpm方式安裝JDK8
- Linux系統(tǒng)(CentOS7安裝)安裝JDK8的教程詳解
- CentOS8 安裝 jdk8 / java8的教程(推薦)
- 淺談JDK7和JDK8的區(qū)別在哪
相關(guān)文章
Java Web Fragment在項(xiàng)目中使用方法詳解
這篇文章主要介紹了Web Fragment在項(xiàng)目中使用方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02spring event 事件異步處理方式(發(fā)布,監(jiān)聽(tīng),異步處理)
這篇文章主要介紹了spring event 事件異步處理方式(發(fā)布,監(jiān)聽(tīng),異步處理),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02java實(shí)現(xiàn)利用String類(lèi)的簡(jiǎn)單方法讀取xml文件中某個(gè)標(biāo)簽中的內(nèi)容
下面小編就為大家?guī)?lái)一篇java實(shí)現(xiàn)利用String類(lèi)的簡(jiǎn)單方法讀取xml文件中某個(gè)標(biāo)簽中的內(nèi)容。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12java中對(duì)字符串每個(gè)字符統(tǒng)計(jì)的方法
java中對(duì)字符串每個(gè)字符統(tǒng)計(jì)的方法,需要的朋友可以參考一下2013-03-03Idea配置Maven阿里云鏡像加速的實(shí)現(xiàn)
這篇文章主要介紹了Idea配置Maven阿里云鏡像加速的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04擴(kuò)展Hibernate使用自定義數(shù)據(jù)庫(kù)連接池的方法
這篇文章主要介紹了擴(kuò)展Hibernate使用自定義數(shù)據(jù)庫(kù)連接池的方法,涉及Hibernate數(shù)據(jù)庫(kù)操作擴(kuò)展的相關(guān)技巧,需要的朋友可以參考下2016-03-03