java 8 date類(lèi)庫(kù)使用
LocalDate
該類(lèi)的實(shí)例是一個(gè)不可變對(duì)象街氢,它只提供了簡(jiǎn)單的日期狈定,并不含當(dāng)天的時(shí)間信息。另外瓜富,它也不附帶任何與時(shí)區(qū)相關(guān)的信息鳍咱。
LocalDate date = LocalDate.of(2014, 3, 23);
int year = date.getYear();
Month month = date.getMonth();
int day = date.getDayOfMonth();
DayOfWeek dow = date.getDayOfWeek();
int len = date.lengthOfMonth();
boolean leap = date.isLeapYear();
//TemporalField讀取LocalDate的值
int year = date.get(ChronoField.YEAR);
int month = date.get(ChronoField.MONTH_OF_YEAR);
int day = date.get(ChronoField.DAY_OF_MONTH);
LocalTime
LocalTime和LocalDate類(lèi)似,不過(guò)它表示一天中的時(shí)間与柑,比如13:45:20谤辜。
LocalTime time = LocalTime.of(13, 45, 20);
int hour = time.getHour();
int minute = time.getMinute();
int second = time.getSecond();
LocalDate和LocalTime都可以通過(guò)解析代表它們的字符串創(chuàng)建
LocalDate date = LocalDate.parse("2014-03-18");
LocalTime time = LocalTime.parse("13:45:20");
你可以向parse方法傳遞一個(gè)DateTimeFormatter
LocalDateTime
是LocalDate和LocalTime的合體。它同時(shí)表示了日期和時(shí)間价捧,但不帶有時(shí)區(qū)信息丑念,你可以直接創(chuàng)建,也可以通過(guò)合并日期和時(shí)間對(duì)象構(gòu)造
LocalDateTime dt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20);
LocalDateTime dt2 = LocalDateTime.of(date, time);
LocalDateTime dt3 = date.atTime(13, 45, 20);
LocalDateTime dt4 = date.atTime(time);
LocalDateTime dt5 = time.atDate(date);
也可以從中提取LocalDate或者LocalTime结蟋。
Instant
它是以Unix元年時(shí)間(傳統(tǒng)的設(shè)定為UTC時(shí)區(qū)1970年1月1日午夜時(shí)分)開(kāi)始所經(jīng)歷的秒數(shù)進(jìn)行計(jì)算; 你可以通過(guò)向靜態(tài)工廠方法ofEpochSecond傳遞一個(gè)代表秒數(shù)的值創(chuàng)建一個(gè)該類(lèi)的實(shí)例
Instant.ofEpochSecond(3);
Instant.ofEpochSecond(3, 0);
Instant.ofEpochSecond(2, 1_000_000_000); //2秒之后再加上100萬(wàn)納秒(1秒)
Instant.ofEpochSecond(4, -1_000_000_000); //2秒之后再減去100萬(wàn)納秒(1秒)
Instant的設(shè)計(jì)初衷是為了便于機(jī)器使用脯倚。它包含的是由秒及納秒所構(gòu)成的數(shù)字。所以嵌屎,它無(wú)法處理那些我們非常容易理解的時(shí)間單位推正,exp:
int day = Instant.now().get(ChronoField.DAY_OF_MONTH);
會(huì)拋出異常
Duration and Period
Duration
Temporal接口定義了如何讀取和操縱為時(shí)間建模的對(duì)象的值
你可以創(chuàng)建兩個(gè)LocalTimes對(duì)象、兩個(gè)LocalDateTimes對(duì)象宝惰,或者兩個(gè)Instant對(duì)象之間的duration植榕,如下所示:
Duration d1 = Duration.between(time1, time2);
Duration d2 = Duration.between(dateTime1, dateTime2);
Duration d3 = Duration.between(instant1, instant2);
注意:
- 由于LocalDateTime和Instant是為不同的目的而設(shè)計(jì)的,一個(gè)是為了便于人閱讀使用尼夺,另一個(gè)是為了便于機(jī)器處理尊残,所以你不能將二者混用。如果你試圖在這兩類(lèi)對(duì)象之間創(chuàng)建duration汞斧,會(huì)觸發(fā)一個(gè)DateTimeException異常。
- 由于Duration類(lèi)主要用于以秒和納秒衡量時(shí)間的長(zhǎng)短什燕,你不能僅向between方法傳遞一個(gè)LocalDate對(duì)象做參數(shù)粘勒。
Period
如果你需要以年、月或者日的方式對(duì)多個(gè)時(shí)間單位建模;使用該類(lèi)的
工廠方法between屎即,你可以使用得到兩個(gè)LocalDate之間的時(shí)長(zhǎng)庙睡,如下所示:
Period tenDays = Period.between(LocalDate.of(2014, 3, 8),
LocalDate.of(2014, 3, 18));
Duration和Period類(lèi)都提供了很多非常方便的工廠類(lèi)事富,直接創(chuàng)建對(duì)應(yīng)的實(shí)例;換句話說(shuō)乘陪,就像下面這段代碼那樣统台,不再是只能以?xún)蓚€(gè)temporal對(duì)象的差值的方式來(lái)定義它們的對(duì)象。
Duration threeMinutes = Duration.ofMinutes(3);
Duration threeMinutes = Duration.of(3, ChronoUnit.MINUTES);
Period tenDays = Period.ofDays(10);
Period threeWeeks = Period.ofWeeks(3);
Period twoYearsSixMonthsOneDay = Period.of(2, 6, 1);
操縱啡邑、解析和格式化日期
操縱LocalDate的屬性,返回一個(gè)修改了屬性的對(duì)象贱勃。它們都不會(huì)修改原來(lái)的對(duì)象
LocalDate date1 = LocalDate.of(2014, 3, 18); //2014-03-18
LocalDate date2 = date1.withYear(2011); //2011-03-18
LocalDate date3 = date2.withDayOfMonth(25); //2011-03-25
LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 9); //2011-09-25
//以相對(duì)方式修改LocalDate對(duì)象的屬性
LocalDate date1 = LocalDate.of(2014, 3, 18);
LocalDate date2 = date1.plusWeeks(1);
LocalDate date3 = date2.minusYears(3);
LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS);
LocalDate、 LocalTime谤逼、 LocalDateTime以及Instant這樣表示時(shí)間點(diǎn)的日期,時(shí)間類(lèi)提供了大量通用的方法
方法名 | 是否靜態(tài)方法 | 描述 |
---|---|---|
from | 是 | 依據(jù)傳入的Temporal對(duì)象創(chuàng)建對(duì)象實(shí)例 |
now | 是 | 依據(jù)系統(tǒng)時(shí)鐘創(chuàng)建Temporal對(duì)象 |
of | 是 | 由Temporal對(duì)象的某個(gè)部分創(chuàng)建該對(duì)象的實(shí)例 |
parse | 是 | 由字符串創(chuàng)建Temporal對(duì)象的實(shí)例 |
atOffset | 否 | 將Temporal對(duì)象和某個(gè)時(shí)區(qū)偏移相結(jié)合 |
atZone | 否 | 將Temporal對(duì)象和某個(gè)時(shí)區(qū)相結(jié)合 |
format | 否 | 使用某個(gè)指定的格式器將Temporal對(duì)象轉(zhuǎn)換為字符串(Instant 類(lèi)不提供該方法) |
get | 否 | 讀取Temporal對(duì)象的某一部分的值 |
minus | 否 | 創(chuàng)建Temporal對(duì)象的一個(gè)副本贵扰,通過(guò)將當(dāng)前Temporal對(duì)象的值減去一定的時(shí)長(zhǎng)創(chuàng)建該副本 |
plus | 否 | 創(chuàng)建Temporal對(duì)象的一個(gè)副本,通過(guò)將當(dāng)前Temporal對(duì)象的值加上一定的時(shí)長(zhǎng)創(chuàng)建該副本 |
with | 否 | 以該Temporal對(duì)象為模板流部,對(duì)某些狀態(tài)進(jìn)行修改創(chuàng)建該對(duì)象的副本 |
TemporalAdjuster
有的時(shí)候戚绕,你需要進(jìn)行一些更加復(fù)雜的操作,比如枝冀,將日期調(diào)整到下個(gè)周日舞丛、下個(gè)工作日,或者是本月的最后一天果漾。這時(shí)球切,你可以使用重載版本的with方法,向其傳遞一個(gè)提供了更多定制化選擇的TemporalAdjuster對(duì)象跨晴,更加靈活地處理日期欧聘。你可以通過(guò)TemporalAdjusters類(lèi)的靜態(tài)工廠方法訪問(wèn)它們:
LocalDate date1 = LocalDate.of(2014, 3, 18);
LocalDate date2 = date1.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
LocalDate date3 = date2.with(TemporalAdjusters.lastDayOfMonth());
方法名 | 描述 |
---|---|
dayOfWeekInMonth | 創(chuàng)建一個(gè)新的日期,它的值為同一個(gè)月中每一周的第幾天 |
firstDayOfMonth | 創(chuàng)建一個(gè)新的日期端盆,它的值為當(dāng)月的第一天 |
firstDayOfNextMonth | 創(chuàng)建一個(gè)新的日期怀骤,它的值為下月的第一天 |
firstDayOfNextYear | 創(chuàng)建一個(gè)新的日期,它的值為明年的第一天 |
firstDayOfYear | 創(chuàng)建一個(gè)新的日期焕妙,它的值為當(dāng)年的第一天 |
firstInMonth | 創(chuàng)建一個(gè)新的日期蒋伦,它的值為同一個(gè)月中,第一個(gè)符合星期幾要求的值 |
lastDayOfMonth | 創(chuàng)建一個(gè)新的日期焚鹊,它的值為當(dāng)月的最后一天 |
lastDayOfNextMonth | 創(chuàng)建一個(gè)新的日期痕届,它的值為下月的最后一天 |
lastDayOfNextYear | 創(chuàng)建一個(gè)新的日期,它的值為明年的最后一天 |
lastDayOfYear | 創(chuàng)建一個(gè)新的日期末患,它的值為今年的最后一天 |
lastInMonth | 創(chuàng)建一個(gè)新的日期研叫,它的值為同一個(gè)月中,最后一個(gè)符合星期幾要求的值 |
next/previous | 創(chuàng)建一個(gè)新的日期璧针,并將其值設(shè)定為日期調(diào)整后或者調(diào)整前嚷炉,第一個(gè)符合指定星期幾要求的日期 |
nextOrSame/previousOrSame | 創(chuàng)建一個(gè)新的日期,并將其值設(shè)定為日期調(diào)整后或者調(diào)整前探橱,第一個(gè)符合指定星期幾要求的日期申屹,如果該日期已經(jīng)符合要求绘证,直接返回該對(duì)象 |
TemporalAdjuster類(lèi)中的工廠方法:
方法名 | 描述 |
---|---|
dayOfWeekInMonth | 創(chuàng)建一個(gè)新的日期,它的值為同一個(gè)月中每一周的第幾天 |
firstDayOfMonth | 創(chuàng)建一個(gè)新的日期哗讥,它的值為當(dāng)月的第一天 |
firstDayOfNextMonth | 創(chuàng)建一個(gè)新的日期嚷那,它的值為下月的第一天 |
firstDayOfNextYear | 創(chuàng)建一個(gè)新的日期,它的值為明年的第一天 |
firstDayOfYear | 創(chuàng)建一個(gè)新的日期杆煞,它的值為當(dāng)年的第一天 |
firstInMonth | 創(chuàng)建一個(gè)新的日期魏宽,它的值為同一個(gè)月中,第一個(gè)符合星期幾要求的值 |
lastDayOfMonth | 創(chuàng)建一個(gè)新的日期索绪,它的值為當(dāng)月的最后一天 |
lastDayOfNextMonth | 創(chuàng)建一個(gè)新的日期湖员,它的值為下月的最后一天 |
lastDayOfNextYear | 創(chuàng)建一個(gè)新的日期,它的值為明年的最后一天 |
lastDayOfYear | 創(chuàng)建一個(gè)新的日期瑞驱,它的值為今年的最后一天 |
lastInMonth | 創(chuàng)建一個(gè)新的日期娘摔,它的值為同一個(gè)月中,最后一個(gè)符合星期幾要求的值 |
next/previous | 創(chuàng)建一個(gè)新的日期唤反,并將其值設(shè)定為日期調(diào)整后或者調(diào)整前凳寺,第一個(gè)符合指定星期幾要求的日期 |
nextOrSame/previousOrSame | 創(chuàng)建一個(gè)新的日期,并將其值設(shè)定為日期調(diào)整后或者調(diào)整前彤侍,第一個(gè)符合指定星期幾要求的日期肠缨,如果該日期已經(jīng)符合要求,直接返回該對(duì)象 |
打印輸出及解析日期時(shí)間對(duì)象
新的java.time.format
包就是特別為這個(gè)目的而設(shè)計(jì)的盏阶。這個(gè)包中晒奕,最重要的類(lèi)是DateTimeFormatter
。創(chuàng)建格式器最簡(jiǎn)單的方法是通過(guò)它的靜態(tài)工廠方法以及常量名斟。
LocalDate date = LocalDate.of(2014, 3, 18);
String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE);
String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
//也可以通過(guò)解析代表日期或時(shí)間的字符串重新創(chuàng)建該日期對(duì)象
LocalDate date1 = LocalDate.parse("20140318", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate date2 = LocalDate.parse("2014-03-18", DateTimeFormatter.ISO_LOCAL_DATE);
和老的java.util.DateFormat相比較脑慧,所有的DateTimeFormatter實(shí)例都是線程安全的。所以砰盐,你能夠以單例模式創(chuàng)建格式器實(shí)例闷袒,就像DateTimeFormatter所定義的那些常量,并能在多個(gè)線程間共享這些實(shí)例岩梳。DateTimeFormatter類(lèi)還支持一個(gè)靜態(tài)工廠方法囊骤,它可以按照某個(gè)特定的模式創(chuàng)建格式器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
處理不同的時(shí)區(qū)和歷法
ZonedDateTime實(shí)例,它代表了相對(duì)于指定時(shí)區(qū)的時(shí)間點(diǎn)
Date LocalDate相關(guān)轉(zhuǎn)換
Java 8中 java.util.Date 類(lèi)新增了兩個(gè)方法冀值,分別是from(Instant instant)
和toInstant()
方法也物;
通過(guò)Instant當(dāng)中介,然后通過(guò)Instant
來(lái)創(chuàng)建LocalDateTime
(這個(gè)類(lèi)可以很容易獲取LocalDate
和LocalTime
)列疗,新的日期類(lèi)轉(zhuǎn)舊的也是如此滑蚯,將新的先轉(zhuǎn)成LocalDateTime
,然后獲取Instant
作彤,接著轉(zhuǎn)成Date
// 01. java.util.Date --> java.time.LocalDateTime
public void UDateToLocalDateTime() {
java.util.Date date = new java.util.Date();
Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
}
// java.time.LocalDateTime --> java.util.Date
public void LocalDateTimeToUdate() {
LocalDateTime localDateTime = LocalDateTime.now();
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zone).toInstant();
java.util.Date date = Date.from(instant);
}
小結(jié)
- Java 8之前老版的java.util.Date類(lèi)以及其他用于建模日期時(shí)間的類(lèi)有很多不一致及設(shè)計(jì)上的缺陷膘魄,包括易變性以及糟糕的偏移值、默認(rèn)值和命名竭讳。
- 新版的日期和時(shí)間API中创葡,日期-時(shí)間對(duì)象是不可變的。
- 新的API提供了兩種不同的時(shí)間表示方式绢慢,有效地區(qū)分了運(yùn)行時(shí)人和機(jī)器的不同需求灿渴。
- 你可以用絕對(duì)或者相對(duì)的方式操縱日期和時(shí)間,操作的結(jié)果總是返回一個(gè)新的實(shí)例胰舆,老的日期時(shí)間對(duì)象不會(huì)發(fā)生變化骚露。
- TemporalAdjuster讓你能夠用更精細(xì)的方式操縱日期,不再局限于一次只能改變它的一個(gè)值缚窿,并且你還可按照需求定義自己的日期轉(zhuǎn)換器棘幸。
- 你現(xiàn)在可以按照特定的格式需求,定義自己的格式器倦零,打印輸出或者解析日期?時(shí)間對(duì)象误续。這些格式器可以通過(guò)模板創(chuàng)建,也可以自己編程創(chuàng)建扫茅,并且它們都是線程安全的蹋嵌。
- 你可以用相對(duì)于某個(gè)地區(qū)/位置的方式,或者以與UTC/格林尼治時(shí)間的絕對(duì)偏差的方式表示時(shí)區(qū)葫隙,并將其應(yīng)用到日期?時(shí)間對(duì)象上栽烂,對(duì)其進(jìn)行本地化。
- 你現(xiàn)在可以使用不同于ISO-8601標(biāo)準(zhǔn)系統(tǒng)的其他日歷系統(tǒng)了恋脚。