国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

還在用Calendar操作Date?Java8都被放棄了,你還不知道Java8中全新的日期時(shí)間API

開(kāi)發(fā) 前端
本文探討了Java 8引入的全新日期時(shí)間API相較于傳統(tǒng)的Date和Calendar類(lèi)的優(yōu)勢(shì)及實(shí)際應(yīng)用。鑒于Java 8新日期時(shí)間API在設(shè)計(jì)上的先進(jìn)性和易用性,強(qiáng)烈建議積極采納并替換掉陳舊的Date和Calendar類(lèi),轉(zhuǎn)而采用如LocalDate、LocalDateTime、ZonedDateTime等現(xiàn)代日期時(shí)間類(lèi)。

引言

在過(guò)去的Java版本中,日期和時(shí)間的處理主要依賴(lài)于java.util.Date和java.util.Calendar類(lèi),然而隨著業(yè)務(wù)系統(tǒng)的復(fù)雜以及技術(shù)層面的提升,這些傳統(tǒng)的日期時(shí)間類(lèi)暴露出了若干顯著的不足之處。隨著Java8的發(fā)布,其引入了一套全新的日期時(shí)間API,徹底改變了我們處理日期和時(shí)間的方式。

傳統(tǒng)的日期時(shí)間類(lèi)

相比較Java8中新引入的java.time包下的時(shí)間處理類(lèi),傳統(tǒng)的日期時(shí)間處理類(lèi)在易用性,線程安全,不支持市時(shí)區(qū)等缺點(diǎn)。

  1. 設(shè)計(jì)復(fù)雜性:Date類(lèi)的設(shè)計(jì)較為簡(jiǎn)單,但它實(shí)際上混合了日期和時(shí)間信息,并且沒(méi)有提供直觀的方法來(lái)單獨(dú)操作日期或時(shí)間部分。Calendar類(lèi)雖然提供了更多靈活性,但由于其內(nèi)部狀態(tài)和方法的復(fù)雜性,使得開(kāi)發(fā)者在使用過(guò)程中容易出現(xiàn)錯(cuò)誤和混淆,尤其是在進(jìn)行日期時(shí)間計(jì)算和格式化時(shí)。比如:
Date currentDate = new Date();  
// 輸出原始的日期時(shí)間,通常不是人類(lèi)可讀格式   Fri Mar 08 03:13:47 CST 2024
System.out.println(currentDate);

// 要改變?nèi)掌诘哪硞€(gè)部分,必須先將其轉(zhuǎn)換為 Calendar,然后設(shè)置  
Calendar calendar = Calendar.getInstance();  
calendar.setTime(currentDate);  
// 修改日期的天數(shù)  
calendar.add(Calendar.DAY_OF_MONTH, 1);
  1. 線程安全性:Date和 Calendar類(lèi),以及格式化日期的SimpleDateFormat類(lèi)都不是線程安全的,這意味著在多線程環(huán)境下的并發(fā)訪問(wèn)可能會(huì)導(dǎo)致數(shù)據(jù)不一致。

Date類(lèi)內(nèi)部維護(hù)了一個(gè) long 類(lèi)型的瞬時(shí)值,當(dāng)調(diào)用如setTime()方法來(lái)更新這個(gè)瞬時(shí)值時(shí),不同的線程同時(shí)調(diào)用就會(huì)互相覆蓋彼此的值,造成數(shù)據(jù)不一致。

Calendar類(lèi)不僅包含了日期和時(shí)間信息,還有一系列內(nèi)部狀態(tài)變量,如年、月、日、小時(shí)、分鐘、秒等。Calendar類(lèi)的方法通常會(huì)修改這些內(nèi)部狀態(tài),例如 add()、set() 等。在多線程環(huán)境下,若多個(gè)線程嘗試同時(shí)修改同一個(gè) Calendar 實(shí)例,也會(huì)導(dǎo)致不可預(yù)期的結(jié)果。

SimpleDateFormat類(lèi)在執(zhí)行格式化和解析日期時(shí)間操作時(shí),內(nèi)部會(huì)維護(hù)一個(gè) Calendar對(duì)象以及其他一些狀態(tài)變量。在 format() 或 parse() 方法執(zhí)行過(guò)程中,這些狀態(tài)會(huì)被更新以完成格式轉(zhuǎn)換。并且SimpleDateFormat中的方法并非原子操作,因此在多線程并發(fā)調(diào)用時(shí),可能在一個(gè)線程還未完成整個(gè)操作時(shí)就被另一個(gè)線程打斷,導(dǎo)致錯(cuò)誤的日期時(shí)間處理結(jié)果。

  1. 時(shí)區(qū)處理能力:Date類(lèi)雖能表示時(shí)間戳,但它不直接關(guān)聯(lián)時(shí)區(qū)信息,難以進(jìn)行時(shí)區(qū)相關(guān)的轉(zhuǎn)換。而 Calendar 雖然支持時(shí)區(qū),但操作過(guò)程相當(dāng)復(fù)雜。
  2. 精度差異:Date類(lèi)精度只到毫秒級(jí)。

Java8中日期時(shí)間類(lèi)

Java8中引入的LocalDate,LocalTime,LocalDateTime這幾個(gè)位于java.time下的類(lèi)克服了上述傳統(tǒng)類(lèi)別的局限性,提供了更強(qiáng)大、直觀和精準(zhǔn)的日期時(shí)間處理能力,成為現(xiàn)代Java開(kāi)發(fā)中處理日期時(shí)間首選的工具類(lèi)。相比較傳統(tǒng)的日期時(shí)間類(lèi),具備以下顯著優(yōu)勢(shì):

  1. 功能豐富java.time包下的類(lèi)如 LocalDate、LocalTime、LocalDateTime、ZonedDateTime 等都有明確的職責(zé)劃分,分別處理日期、時(shí)間、日期時(shí)間以及帶時(shí)區(qū)的日期時(shí)間,結(jié)構(gòu)清晰,易于理解和使用。并且它們提供了一系列直觀、面向?qū)ο蟮腁PI,如 plusXxx()、minusXxx()、withXxx()等方法,使日期時(shí)間操作變得簡(jiǎn)單明了。
  2. 時(shí)區(qū)支持除此之外,還支持時(shí)區(qū),通過(guò)ZonedDateTime和 ZoneId等類(lèi)提供了對(duì)時(shí)區(qū)的更好支持,可以方便地進(jìn)行時(shí)區(qū)轉(zhuǎn)換和處理。
  3. 線程安全這些類(lèi)都是不可變對(duì)象,線程安全,可以在多線程環(huán)境下安全使用,不會(huì)出現(xiàn)因并發(fā)操作導(dǎo)致的數(shù)據(jù)不一致問(wèn)題。
  4. 更高的精度支持納秒級(jí)精度,相比 Date 類(lèi)的毫秒精度更勝一籌。

java.time下主要有如下一些關(guān)鍵類(lèi):

  1. LocalDateLocalDate類(lèi)表示一個(gè)不包含時(shí)間信息的日期,只包含年、月、日三個(gè)部分,且不關(guān)聯(lián)任何特定時(shí)區(qū)。
  2. LocalTimeLocalTime類(lèi)表示一個(gè)不包含日期信息的具體時(shí)間,包含時(shí)、分、秒和納秒四個(gè)部分。
  3. LocalDateTimeLocalDateTime類(lèi)結(jié)合了日期和時(shí)間,表示一個(gè)具體的日期和時(shí)間點(diǎn),但是不包含時(shí)區(qū)信息。
  4. ZonedDateTimeZonedDateTime類(lèi)表示一個(gè)帶有時(shí)區(qū)的日期時(shí)間,它可以明確表示某一特定時(shí)區(qū)內(nèi)的某一確切時(shí)間點(diǎn)。
  5. InstantInstant類(lèi)表示時(shí)間線上某一瞬時(shí)點(diǎn),通常以Unix紀(jì)元(1970-01-01T00:00:00Z)以來(lái)的秒數(shù)和納秒數(shù)表示,它是全球通用的時(shí)間點(diǎn)表示。
  6. PeriodPeriod類(lèi)用于表示兩個(gè)日期之間的期間,包括年、月、日的數(shù)量。
  7. DurationDuration類(lèi)表示兩個(gè)時(shí)間點(diǎn)之間的時(shí)間差,包含秒和納秒的持續(xù)時(shí)間,主要用于表示時(shí)間間隔而非日歷單位。
  8. DateTimeFormatterDateTimeFormatter類(lèi)用于日期時(shí)間的格式化和解析,提供了標(biāo)準(zhǔn)化和自定義的日期時(shí)間格式化方式。
  9. TemporalAdjustersTemporalAdjusters類(lèi)提供了一系列實(shí)用方法,用于調(diào)整日期時(shí)間,例如獲取下一個(gè)工作日、月初、月末等。

這些類(lèi)共同構(gòu)成了一個(gè)強(qiáng)大、靈活且易于使用的日期時(shí)間處理體系,大大改善了Java在處理日期時(shí)間問(wèn)題時(shí)的效率和準(zhǔn)確性。接下來(lái)我們?cè)谑褂蒙戏謩e介紹這些類(lèi),以及使用他們的方式,感受他們的強(qiáng)大。

Java8中日期時(shí)間類(lèi)使用

創(chuàng)建

NOW方法獲取當(dāng)前 時(shí)刻、日期、時(shí)間
LocalTime localTime = LocalTime.now();  
System.out.println("localTime:"+localTime);  

LocalDate localDate = LocalDate.now();  
System.out.println("localDate:"+localDate);  

LocalDateTime localDateTime = LocalDateTime.now();  
System.out.println("localDateTime:"+localDateTime);

輸出為:

localTime:15:28:45.241181
localDate:2024-03-11
localDateTime:2024-03-11T15:28:45.260655

針對(duì)LocalTime,LocalDateTime獲取當(dāng)前時(shí)刻默認(rèn)會(huì)帶有毫秒,如果不需要毫秒的話(huà),可以通過(guò)設(shè)置納秒為0 保留秒 1秒 = 十億納秒 。例如:

LocalTime localTime = LocalTime.now().withNano(0);
System.out.println("localTime:"+localTime);  

LocalDateTime localDateTime = LocalDateTime.now().withNano(0);  
System.out.println("localDateTime:"+localDateTime);

輸出為:

localTime:15:32:31
localDateTime:2024-03-11T15:32:31

而對(duì)于LocalDateTime獲取當(dāng)前日期,默認(rèn)toString會(huì)帶有T分隔日期和時(shí)間,在項(xiàng)目中,可以通過(guò)全局序列化,進(jìn)行統(tǒng)一的時(shí)間格式輸出為 yyyy-MM-dd HH:mm:ss。但是一般不建議這么干,畢竟改變?nèi)中蛄谢渲茫ㄗh不使用toString,可以使用DateTimeFormatter進(jìn)行自定義轉(zhuǎn)換。

of()方法指定年、月、日、時(shí)刻創(chuàng)建
// of方法直接傳遞對(duì)應(yīng)的年、月、日  
LocalDate localDate = LocalDate.of(2024, 3, 11);  
System.out.println("localDate:"+localDate);  
localDate = LocalDate.of(2024, Month.MARCH, 11);  
System.out.println("localDate:"+localDate);  
localDate = LocalDate.ofYearDay(2024, 71);  
System.out.println("localDate:"+localDate);  

// 北京時(shí)間對(duì)應(yīng)的時(shí)區(qū)  
ZoneId chinaTimeZone = ZoneId.of("Asia/Shanghai");  
// 創(chuàng)建一個(gè) Instant,這里使用當(dāng)前時(shí)間的 InstantInstant instant = Instant.now();  
localDate = LocalDate.ofInstant(instant, chinaTimeZone);  
System.out.println("localDate:"+localDate);  

// 使用ofEpochDay()方法,則EpochDay為從公元1970年1月1日(Unix紀(jì)元)開(kāi)始的第多少天  
localDate = LocalDate.ofEpochDay(LocalDate.now().toEpochDay());  
System.out.println("localDate:"+localDate);  


LocalTime localTime = LocalTime.of(1, 30);  
System.out.println("localTime:"+localTime);  
localTime = LocalTime.of(1, 30, 30);  
System.out.println("localTime:"+localTime);  

localTime = LocalTime.ofInstant(instant, chinaTimeZone);  
System.out.println("localTime:"+localTime);  
// 根據(jù)一天中的總秒數(shù)構(gòu)建時(shí)間
localTime = LocalTime.ofSecondOfDay(localTime.toSecondOfDay());  
System.out.println("localTime:"+localTime);  


LocalDateTime localDateTime = LocalDateTime.of(2024, 3, 11, 1, 30, 30);  
System.out.println("localDateTime:"+localDateTime);  
localDateTime = LocalDateTime.of(2024, Month.MARCH, 11, 1, 30, 30);  
System.out.println("localDateTime:"+localDateTime);  
// 使用LocalDate和LocalTime組合構(gòu)造  
localDateTime = LocalDateTime.of(localDate, localTime);  
System.out.println("localDateTime:"+localDateTime);  

localDateTime = LocalDateTime.ofInstant(instant, chinaTimeZone);  
System.out.println("localDateTime:"+localDateTime);

輸出為:

localDate:2024-03-11
localDate:2024-03-11
localDate:2024-03-11
localDate:2024-03-11
localDate:2024-03-11
localTime:01:30
localTime:01:30:30
localTime:16:41:37.893310
localTime:16:41:37
localDateTime:2024-03-11T01:30:30
localDateTime:2024-03-11T01:30:30
localDateTime:2024-03-11T16:41:37
localDateTime:2024-03-11T16:41:37.893310
from()方法轉(zhuǎn)換

from()方法將TemporalAccessor類(lèi)型(如ZonedDateTime)轉(zhuǎn)換為相對(duì)應(yīng)的日期或者時(shí)間。TemporalAccessor接口是一個(gè)用于讀取或?qū)懭肴掌凇r(shí)間或者日期時(shí)間的通用接口。

// 創(chuàng)建一個(gè)ZonedDateTime實(shí)例  
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));  
LocalTime localTime = LocalTime.from(zonedDateTime);  
System.out.println("localTime:"+localTime);  

LocalDate localDate = LocalDate.from(zonedDateTime);  
System.out.println("localDate:"+localDate);  

LocalDateTime localDateTime = LocalDateTime.from(zonedDateTime);  
System.out.println("localDateTime:"+localDateTime);

輸出為:

localTime:17:18:27.942911
localDate:2024-03-11
localDateTime:2024-03-11T17:18:27.942911
parse()方法轉(zhuǎn)換

將字符串按照指定格式(可選)解析為對(duì)應(yīng)的日期時(shí)間類(lèi)。

LocalTime localTime = LocalTime.parse("17:25:30");  
System.out.println("localTime:"+localTime);  
localTime = LocalTime.parse("17:25:30", DateTimeFormatter.ofPattern("HH:mm:ss"));  
System.out.println("localTime:"+localTime);  

LocalDate localDate = LocalDate.parse("2024-03-11");  
System.out.println("localDate:"+localDate);  
localDate = LocalDate.parse("2024/03/11", DateTimeFormatter.ofPattern("yyyy/MM/dd"));  
System.out.println("localDate:"+localDate);  

LocalDateTime localDateTime = LocalDateTime.parse("2024-03-11T17:25:30");  
System.out.println("localDateTime:"+localDateTime);  
localDateTime = LocalDateTime.parse("2024/03/11 17:25:30", DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));  
System.out.println("localDateTime:"+localDateTime);

輸出為:

localTime:17:25:30
localTime:17:25:30
localDate:2024-03-11
localDate:2024-03-11
localDateTime:2024-03-11T17:25:30
localDateTime:2024-03-11T17:25:30

日期時(shí)間類(lèi)的相互轉(zhuǎn)換

LocalTime、LocalDate、LocalDateTime 相互轉(zhuǎn)化
// LocalTime + LocalDate = LocalDateTime
LocalDateTime localDateTime = LocalTime.now().atDate(LocalDate.now());
System.out.println("localDateTime:"+localDateTime);
localDateTime = LocalDate.now().atTime(LocalTime.now());
System.out.println("localDateTime:"+localDateTime);
localDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.now());
System.out.println("localDateTime:"+localDateTime);

// LocalDateTime 轉(zhuǎn) LocalDate
LocalDate localDate = LocalDateTime.now().toLocalDate();
System.out.println("localDate:"+localDate);
// LocalDateTime 轉(zhuǎn) LocalTime
LocalTime localTime = LocalDateTime.now().toLocalTime();
System.out.println("localTime:"+localTime);

// 獲取今日開(kāi)始時(shí)間 2024-03-11T00:00
localDateTime = LocalDate.now().atStartOfDay();
System.out.println("localDateTime:"+localDateTime);
// 獲取今日開(kāi)始時(shí)間 2024-03-11T00:00
LocalDateTime startDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
System.out.println("startDateTime:"+ startDateTime);
// 獲取今日結(jié)束時(shí)間 2024-03-11T23:59:59.999999999
LocalDateTime endDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
System.out.println("endDateTime:"+ endDateTime);

輸出為:

localDateTime:2024-03-11T18:04:22.348539
localDateTime:2024-03-11T18:04:22.370562
localDateTime:2024-03-11T18:04:22.370768
localDate:2024-03-11
localTime:18:04:22.371062
localDateTime:2024-03-11T00:00
startDateTime:2024-03-11T00:00
endDateTime:2024-03-11T23:59:59.999999999
String 與 LocalTime、LocalDate、LocalDateTime 相互轉(zhuǎn)化

主要使用format 和 parse 進(jìn)行轉(zhuǎn)換,使用方法基本相同。使用 DateTimeFormatter.ofPattern() 定義時(shí)間格式,再進(jìn)行轉(zhuǎn)換。DateTimeFormatter線程安全。

// LocalTime 轉(zhuǎn) String 自定義輸出格式,例如:**時(shí)**分**秒 該轉(zhuǎn)化的 00 不會(huì)被省略
String localTimeStr = LocalTime.now().format(DateTimeFormatter.ofPattern("HH時(shí)mm分ss秒"));
System.out.println("localTimeStr:"+localTimeStr);

String localDateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println("localDateStr:"+localDateStr);

// LocalDateTime 轉(zhuǎn) String
String localDateTimeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("localDateTimeStr:"+localDateTimeStr);

// String 轉(zhuǎn) LocalDateTime
LocalDateTime localDateTime = LocalDateTime.parse("2023-04-14 15:59:40", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("localDateTime:"+localDateTime);

輸出結(jié)果:

localTimeStr:19時(shí)02分58秒
localDateStr:2024-03-11
localDateTimeStr:2024-03-11 19:02:58
localDateTime:2023-04-14T15:59:40
Date 與 LocalDate、LocalDateTime 相互轉(zhuǎn)化
// Date 轉(zhuǎn) LocalDateTime
Date currentDate = new Date();
// 轉(zhuǎn)換為Instant 
Instant instant = currentDate.toInstant();
// 通過(guò)zoneId設(shè)置時(shí)區(qū)(這里使用系統(tǒng)時(shí)區(qū)),轉(zhuǎn)換為帶帶時(shí)區(qū)的 ZoneDateTime
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
// 然后通過(guò)ZonedDateTime轉(zhuǎn)換為L(zhǎng)ocalDateTime
LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
System.out.println("localDateTime:"+localDateTime);
// LocalDateTime 轉(zhuǎn) Date,同理也是通過(guò)ZonedDateTime轉(zhuǎn)換為Date
Date localDateTimeToDate = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());
System.out.println(localDateTimeToDate);
// Date轉(zhuǎn)LocalDate 同理 LocalDateTime轉(zhuǎn)換
LocalDate localDate = currentDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
System.out.println("localDate:"+localDate);
// LocalDate 轉(zhuǎn) Date  需要先將 LocalDate 轉(zhuǎn) LocalDateTime
Date localDateToDate = Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());

這里介紹一下ZoneId。java.time.ZoneId是Java 8中java.time包中用于表示時(shí)區(qū)的類(lèi)。時(shí)區(qū)是地球上的地理位置,用于確定在該位置觀察太陽(yáng)升落以及規(guī)定當(dāng)?shù)鼐用裆詈蜕虡I(yè)活動(dòng)時(shí)間的標(biāo)準(zhǔn)時(shí)間。ZoneId使用IANA時(shí)區(qū)數(shù)據(jù)庫(kù)提供的時(shí)區(qū)標(biāo)識(shí)符,這個(gè)標(biāo)識(shí)符是唯一的,這些標(biāo)識(shí)符通常是地區(qū)/城市對(duì),例如“Asia/Shanghai”代表中國(guó)上海所在的時(shí)區(qū),America/New_York代表美國(guó)紐約城市。其實(shí)例獲取有兩種方式:

  • ZoneId.systemDefault():獲取系統(tǒng)默認(rèn)的時(shí)區(qū)ID。
  • ZoneId.of(String zoneId):根據(jù)提供的時(shí)區(qū)ID字符串獲取ZoneId實(shí)例。至于zoneId的值,可以查看源碼。可以通過(guò)ZoneId.getAvailableZoneIds()查看獲取。
Long 與 LocalDate、LocalDateTime 相互轉(zhuǎn)化

時(shí)間戳轉(zhuǎn)換。

long timeMillis = System.currentTimeMillis();

// 時(shí)間戳(Long) 轉(zhuǎn) LocalDateTime
LocalDateTime localDateTime = Instant.ofEpochMilli(timeMillis).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
System.out.println("localDateTime:"+localDateTime);
localDateTime = Instant.ofEpochMilli(timeMillis).atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println("localDateTime:"+localDateTime);
// LocalDateTime 轉(zhuǎn) 時(shí)間戳(Long) 秒級(jí)
long localDateTimeToSecond = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8));
System.out.println("localDateTimeToSecond:"+ localDateTimeToSecond);
// LocalDateTime 轉(zhuǎn) 時(shí)間戳(Long) 毫秒級(jí)
long localDateTimeToMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
System.out.println("localDateTimeToMilliSecond:"+ localDateTimeToMilliSecond);

// 時(shí)間戳(Long) 轉(zhuǎn) LocalDate
LocalDate localDate = Instant.ofEpochMilli(timeMillis).atZone(ZoneOffset.ofHours(8)).toLocalDate();
System.out.println("localDate:"+ localDate);
// LocalDate 轉(zhuǎn) 時(shí)間戳(Long) 秒級(jí)
long localDateToSecond =  LocalDate.now().atStartOfDay().toEpochSecond(ZoneOffset.ofHours(8));
System.out.println("localDateToSecond:"+ localDateToSecond);
// LocalDate 轉(zhuǎn) 時(shí)間戳(Long) 毫秒級(jí)
long localDateToMilliSecond = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
System.out.println("localDateToMilliSecond:"+ localDateToMilliSecond);

輸出結(jié)果為:

localDateTime:2024-03-11T19:37:02.335
localDateTime:2024-03-11T19:37:02.335
localDateTimeToSecond:1710157022
localDateTimeToMilliSecond:1710157022365
localDate:2024-03-11
localDateToSecond:1710086400
localDateToMilliSecond:1710086400000

java.time.ZoneOffset是Java8中java.time包內(nèi)用來(lái)表示時(shí)區(qū)偏移量的類(lèi),它表示的是格林尼治標(biāo)準(zhǔn)時(shí)間或協(xié)調(diào)世界時(shí)間(UTC)基礎(chǔ)上的固定偏移量。每一個(gè)時(shí)區(qū)都可以通過(guò)一個(gè)或多個(gè)偏移量來(lái)表示,比如“+02:00”表示比UTC時(shí)間快兩個(gè)小時(shí)的時(shí)區(qū)偏移。其實(shí)例創(chuàng)建有如下方式:

  • ZoneOffset.ofHours(int hours):根據(jù)小時(shí)數(shù)創(chuàng)建偏移量,例如 ZoneOffset.ofHours(2) 表示比UTC早2小時(shí)的時(shí)區(qū)。
  • ZoneOffset.ofHoursMinutes(int hours, int minutes):根據(jù)小時(shí)數(shù)和分鐘數(shù)創(chuàng)建偏移量。
  • ZoneOffset.ofHoursMinutesSeconds(int hours, int minutes, int seconds):根據(jù)小時(shí)、分鐘和秒數(shù)創(chuàng)建偏移量。
  • ZoneOffset.ofTotalSeconds(int totalSeconds):根據(jù)相對(duì)于UTC的總秒數(shù)創(chuàng)建偏移量。
  • ZoneOffset.of(String offsetId):根據(jù)偏移量ID(如 "+02:00")創(chuàng)建實(shí)例。

日期時(shí)間類(lèi)的操作

日期時(shí)間的增減

java.time 包中日期時(shí)間類(lèi)(如 LocalDateTime、LocalDate 和 LocalTime)可以通過(guò)plusXxx() 和 minusXxx() 方法,用于對(duì)日期時(shí)間對(duì)象進(jìn)行加減操作,以增加或減少指定的時(shí)間或日期單位。

1、LocalDateTime 加減:

  • plusHours(int hours), plusMinutes(int minutes), plusSeconds(int seconds):分別用于向 LocalDateTime 對(duì)象添加指定的小時(shí)數(shù)、分鐘數(shù)和秒數(shù)。
  • plus(1, ChronoUnit.XXX):這里的 ChronoUnit 參數(shù)可以是 HOURS、MINUTES、SECONDS 等,也可以是 YEARS、MONTHS、DAYS、WEEKS 等,用于向日期時(shí)間對(duì)象添加指定單位的數(shù)量。
  • plus(Duration duration):使用 Duration 對(duì)象來(lái)增加時(shí)間,Duration 可以包含秒和納秒的精度。
  • plus(Period period):使用 Period 對(duì)象來(lái)增加日期,Period 可以表示年、月、日的數(shù)量。
  • 與plusXxx() 方法相對(duì)應(yīng),minusXxx() 方法用于從日期時(shí)間對(duì)象中減少指定的單位。例如 minusHours(int hours)、minusMinutes(int minutes)、minusSeconds(int seconds) 等方法用于減少小時(shí)、分鐘、秒數(shù)。
// LocalDateTime 加減
LocalDateTime localDateTime = LocalDateTime.now();
// 以下為增加時(shí)、分、秒
LocalDateTime plusLocalDateTime = localDateTime.plusHours(1).plusMinutes(1).plusSeconds(1);
System.out.println("plusLocalDateTime:"+plusLocalDateTime);
plusLocalDateTime = localDateTime.plus(1, ChronoUnit.HOURS).plus(1, ChronoUnit.MINUTES).plus(1, ChronoUnit.SECONDS);
System.out.println("plusLocalDateTime:"+plusLocalDateTime);
plusLocalDateTime = localDateTime.plus(Duration.ofHours(1)).plus(Duration.of(1, ChronoUnit.MINUTES)).plus(Duration.of(1, ChronoUnit.SECONDS));
System.out.println("plusLocalDateTime:"+plusLocalDateTime);

// 以下為增加年、月、日
plusLocalDateTime = localDateTime.plusYears(1).plusMonths(1).plusWeeks(1).plusDays(1);
System.out.println("plusLocalDateTime:"+plusLocalDateTime);
plusLocalDateTime = localDateTime.plus(1, ChronoUnit.YEARS).plus(1, ChronoUnit.MONTHS).plus(1, ChronoUnit.WEEKS).plus(1, ChronoUnit.DAYS);
System.out.println("plusLocalDateTime:"+plusLocalDateTime);
plusLocalDateTime = localDateTime.plus(Duration.of(1, ChronoUnit.YEARS)).plus(Duration.of(1, ChronoUnit.MONTHS)).plus(Duration.of(1, ChronoUnit.WEEKS)).plus(Duration.ofDays(1));
System.out.println("plusLocalDateTime:"+plusLocalDateTime);
plusLocalDateTime = localDateTime.plus(Period.ofYears(1)).plus(Period.ofMonths(1)).plus(Period.ofWeeks(1)).plus(Period.ofDays(1));
System.out.println("plusLocalDateTime:"+plusLocalDateTime);

// 以下為減少時(shí)、分、秒
LocalDateTime minusLocalDateTime = localDateTime.minusHours(1).minusMinutes(1).minusSeconds(1);
System.out.println("minusLocalDateTime:"+minusLocalDateTime);
minusLocalDateTime = localDateTime.minus(1, ChronoUnit.HOURS).minus(1, ChronoUnit.MINUTES).minus(1, ChronoUnit.SECONDS);
System.out.println("minusLocalDateTime:"+minusLocalDateTime);
minusLocalDateTime = localDateTime.minus(Duration.ofHours(1)).minus(Duration.of(1, ChronoUnit.MINUTES)).minus(Duration.of(1, ChronoUnit.SECONDS));
System.out.println("minusLocalDateTime:"+minusLocalDateTime);

// 以下為減少年、月、日
minusLocalDateTime = localDateTime.minusYears(1).minusMonths(1).minusWeeks(1).minusDays(1);
System.out.println("minusLocalDateTime:"+minusLocalDateTime);
minusLocalDateTime = localDateTime.minus(1, ChronoUnit.YEARS).minus(1, ChronoUnit.MONTHS).minus(1, ChronoUnit.WEEKS).minus(1, ChronoUnit.DAYS);
System.out.println("minusLocalDateTime:"+minusLocalDateTime);
minusLocalDateTime = localDateTime.minus(Duration.of(1, ChronoUnit.YEARS)).minus(Duration.of(1, ChronoUnit.MONTHS)).minus(Duration.of(1, ChronoUnit.WEEKS)).minus(Duration.ofDays(1));
System.out.println("minusLocalDateTime:"+minusLocalDateTime);
minusLocalDateTime = localDateTime.minus(Period.ofYears(1)).minus(Period.ofMonths(1)).minus(Period.ofWeeks(1)).minus(Period.ofDays(1));
System.out.println("plusLocalDateTime:"+minusLocalDateTime);

2、LocalDate 加減:

  • 同樣的,plusYears(int years), plusMonths(int months), plusDays(int days) 分別用于增加年、月、日。
  • plus(1, ChronoUnit.XXX)和plus(Duration/Period duration/period) 方法在此同樣適用,用于增加指定的日期單位。
  • 與plusXxx() 方法相對(duì)應(yīng),minusXxx() 方法用于從日期時(shí)間對(duì)象中減少指定的單位。例如 minusYears(int years)、minusMonths(int months)、minusWeeks(int weeks)、minusDays(int days) 等方法用于減少年、月、周、天數(shù)。
// LocalDate 加減
LocalDate localDate = LocalDate.now();
LocalDate plusLocalDate = localDate.plusYears(1).plusMonths(1).plusWeeks(1).plusDays(1);
System.out.println("plusLocalDate:"+plusLocalDate);
plusLocalDate = localDate.plus(1, ChronoUnit.YEARS).plus(1, ChronoUnit.MONTHS).plus(1, ChronoUnit.WEEKS).plus(1, ChronoUnit.DAYS);
System.out.println("plusLocalDate:"+plusLocalDate);
plusLocalDate = localDate.plus(Duration.of(1, ChronoUnit.YEARS)).plus(Duration.of(1, ChronoUnit.MONTHS)).plus(Duration.of(1, ChronoUnit.WEEKS)).plus(Duration.ofDays(1));
System.out.println("plusLocalDate:"+plusLocalDate);
plusLocalDate = localDate.plus(Period.ofYears(1)).plus(Period.ofMonths(1)).plus(Period.ofWeeks(1)).plus(Period.ofDays(1));
System.out.println("plusLocalDate:"+plusLocalDate);

LocalDate minusLocalDate = localDate.minusYears(1).minusMonths(1).minusWeeks(1).minusDays(1);
System.out.println("minusLocalDate:"+minusLocalDate);
minusLocalDate = localDate.minus(1, ChronoUnit.YEARS).minus(1, ChronoUnit.MONTHS).minus(1, ChronoUnit.WEEKS).minus(1, ChronoUnit.DAYS);
System.out.println("minusLocalDate:"+minusLocalDate);
minusLocalDate = localDate.minus(Duration.of(1, ChronoUnit.YEARS)).minus(Duration.of(1, ChronoUnit.MONTHS)).minus(Duration.of(1, ChronoUnit.WEEKS)).minus(Duration.ofDays(1));
System.out.println("minusLocalDate:"+minusLocalDate);
minusLocalDate = localDate.minus(Period.ofYears(1)).minus(Period.ofMonths(1)).minus(Period.ofWeeks(1)).minus(Period.ofDays(1));
System.out.println("minusLocalDate:"+minusLocalDate);

3、LocalTime 加減:

  • plusHours(int hours), plusMinutes(int minutes), plusSeconds(int seconds):分別用于向 LocalTime 對(duì)象添加指定的小時(shí)數(shù)、分鐘數(shù)和秒數(shù)。
  • 同樣支持 plus(1, ChronoUnit.XXX) 和 plus(Duration duration) 方法,用于增加時(shí)間單位。
  • 與 plusXxx() 方法相對(duì)應(yīng),minusXxx() 方法用于從日期時(shí)間對(duì)象中減少指定的單位。minus(1, ChronoUnit.XXX), minus(Duration duration), minus(Period period) 方法也分別用于減少指定的日期或時(shí)間單位。例如 minusHours(int hours)、minusMinutes(int minutes)、minusSeconds(int seconds) 等方法用于減少小時(shí)、分鐘、秒數(shù)。
// LocalTime 加減
LocalTime localTime = LocalTime.now();
LocalTime plusLocalTime = localTime.plusHours(1).plusMinutes(1).plusSeconds(1);
System.out.println("plusLocalTime:"+plusLocalTime);
plusLocalTime = localTime.plus(1, ChronoUnit.HOURS).plus(1, ChronoUnit.MINUTES).plus(1, ChronoUnit.SECONDS);
System.out.println("plusLocalTime:"+plusLocalTime);
plusLocalTime = localTime.plus(Duration.ofHours(1)).plus(Duration.of(1, ChronoUnit.MINUTES)).plus(Duration.of(1, ChronoUnit.SECONDS));
System.out.println("plusLocalTime:"+plusLocalTime);

LocalTime minusLocalTime = localTime.minusHours(1).minusMinutes(1).minusSeconds(1);
System.out.println("minusLocalTime:"+minusLocalTime);
minusLocalTime = localTime.minus(1, ChronoUnit.HOURS).minus(1, ChronoUnit.MINUTES).minus(1, ChronoUnit.SECONDS);
System.out.println("minusLocalDateTime:"+minusLocalTime);
minusLocalTime = localTime.minus(Duration.ofHours(1)).minus(Duration.of(1, ChronoUnit.MINUTES)).minus(Duration.of(1, ChronoUnit.SECONDS));
System.out.println("minusLocalDateTime:"+minusLocalTime);
日期時(shí)間修改指定值

LocalDate、LocalTime、LocalDateTime、ZonedDateTime可以通過(guò)相對(duì)應(yīng)的withXxx()方法修改指定的值。

1、LocalDate:

  • LocalDate.withYear(int year):修改年份字段。
  • LocalDate.withMonth(int month):修改月份字段(注意月份是從1開(kāi)始計(jì)數(shù)的)。
  • LocalDate.withDayOfMonth(int dayOfMonth):修改日期字段。
LocalDate localDate = LocalDate.of(2024, 3, 12);
LocalDate newDate = localDate.withYear(2025).withMonth(4).with(ChronoField.DAY_OF_MONTH, 13);
System.out.println("newDate:"+newDate);

2、LocalTime:

  • LocalTime.withHour(int hour):修改小時(shí)字段。
  • LocalTime.withMinute(int minute):修改分鐘字段。
  • LocalTime.withSecond(int second):修改秒字段。
  • LocalTime.withNano(int nanoOfSecond):修改納秒字段。
LocalTime localTime = LocalTime.of(17, 25, 30);
LocalTime newTime = localTime.withHour(18).withMinute(26).with(ChronoField.SECOND_OF_MINUTE, 31);
System.out.println("newTime:"+newTime);

3、LocalDateTime:

  • LocalDateTime.withYear(int year)
  • LocalDateTime.withMonth(int month)
  • LocalDateTime.withDayOfMonth(int dayOfMonth)
  • LocalDateTime.withHour(int hour)
  • LocalDateTime.withMinute(int minute)
  • LocalDateTime.withSecond(int second)
  • LocalDateTime.withNano(int nanoOfSecond)
LocalDateTime localDateTime = LocalDateTime.of(2024, 3, 12, 17, 25, 30);
LocalDateTime newDateTime = localDateTime.withYear(2025).withMonth(4).with(ChronoField.DAY_OF_MONTH, 13).withHour(18).withMinute(26).with(ChronoField.SECOND_OF_MINUTE, 31);
System.out.println("newDateTime:"+ newDateTime);

4、ZonedDateTime:

  • 除了上述的日期和時(shí)間字段外,還有時(shí)區(qū)相關(guān)的 withZoneSameInstant(ZoneId zone) 方法,可以改變時(shí)區(qū)的同時(shí)保持同一瞬間不變。
ZonedDateTime zonedDateTime = ZonedDateTime.of(2024, 3, 12, 17, 25, 30, 0, ZoneId.of("Europe/London"));
ZonedDateTime newZonedDateTime = zonedDateTime.withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println("newZonedDateTime:"+ newZonedDateTime);

除此之外,調(diào)整日期時(shí)間還可以通過(guò)TemporalAdjusters,TemporalAdjuster 是一個(gè)函數(shù)式接口,用于根據(jù)給定的規(guī)則調(diào)整日期時(shí)間對(duì)象。Java8的 java.time.temporal 包中預(yù)定義了一系列常用的 TemporalAdjuster 實(shí)現(xiàn),例如獲取下一個(gè)工作日、月初、月末等。

LocalDate date = LocalDate.of(2024, 3, 11);
// 下一個(gè)工作日
LocalDate nextWorkingDay = date.with(TemporalAdjusters.next(DayOfWeek.MONDAY)); // 如果11號(hào)不是周一,則返回下一個(gè)周一的日期
// 下一個(gè)月的第一天
LocalDate firstDayNextMonth = date.with(TemporalAdjusters.firstDayOfMonth()); // 返回4月1日
// 當(dāng)月的最后一個(gè)工作日
LocalDate lastWorkingDay = date.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY)); // 返回3月最后一個(gè)周五的日期

// 自定義 TemporalAdjuster
TemporalAdjuster adjuster = temporal -> {
    return temporal.plusDays(10).with(TemporalAdjusters.lastDayOfMonth());
};
LocalDate tenthDayNextMonthEnd = date.with(adjuster); // 返回4月最后一個(gè)日期,前提是先加10天
日期時(shí)間的比較

在Java8及其以后版本的日期時(shí)間API中,isBefore() 和 isAfter() 方法是 java.time 包中的 LocalDate、LocalTime、LocalDateTime、ZonedDateTime 等日期時(shí)間類(lèi)所共有的方法,用于比較兩個(gè)日期時(shí)間對(duì)象的先后順序。

isBefore():

  • 此方法用于判斷當(dāng)前對(duì)象是否早于另一個(gè)日期時(shí)間對(duì)象。
  • 如果當(dāng)前對(duì)象的時(shí)間點(diǎn)在參數(shù)對(duì)象之前,則返回 true;否則返回 false。
LocalDate date1 = LocalDate.of(2024, 3, 11);
LocalDate date2 = LocalDate.of(2024, 3, 12);
boolean isEarlier = date1.isBefore(date2); // 返回 true,因?yàn)?date1 在 date2 之前

isAfter():

  • 此方法用于判斷當(dāng)前對(duì)象是否晚于另一個(gè)日期時(shí)間對(duì)象。
  • 如果當(dāng)前對(duì)象的時(shí)間點(diǎn)在參數(shù)對(duì)象之后,則返回 true;否則返回 false。
LocalDateTime time1 = LocalDateTime.of(2024, 3, 11, 10, 0);
LocalDateTime time2 = LocalDateTime.of(2024, 3, 11, 9, 0);
boolean isLater = time1.isAfter(time2); // 返回 true,因?yàn)?time1 在 time2 之后

compareTo()在Java 8的 java.time 包中,大部分日期時(shí)間類(lèi)如 LocalDate、LocalTime、LocalDateTime、ZonedDateTime 都實(shí)現(xiàn)了 Comparable 接口,從而可以直接使用 compareTo() 方法進(jìn)行比較。compareTo() 方法用于比較兩個(gè)日期時(shí)間對(duì)象的先后順序,返回值含義如下:

  • 如果當(dāng)前對(duì)象早于(時(shí)間點(diǎn)在前)參數(shù)對(duì)象,返回負(fù)數(shù)。
  • 如果當(dāng)前對(duì)象等于參數(shù)對(duì)象,返回0。
  • 如果當(dāng)前對(duì)象晚于(時(shí)間點(diǎn)在后)參數(shù)對(duì)象,返回正數(shù)。
LocalDate date1 = LocalDate.of(2024, 3, 11);
LocalDate date2 = LocalDate.of(2024, 3, 12);

int comparisonResult = date1.compareTo(date2);

if (comparisonResult < 0) {
    System.out.println("date1 is before date2");
} else if (comparisonResult > 0) {
    System.out.println("date1 is after date2");
} else {
    System.out.println("date1 is equal to date2");
}

LocalDateTime dateTime1 = LocalDateTime.of(2024, 3, 11, 10, 30);
LocalDateTime dateTime2 = LocalDateTime.of(2024, 3, 11, 11, 00);

int timeComparisonResult = dateTime1.compareTo(dateTime2);
其他操作

在Java8的 java.time 包中,各個(gè)日期時(shí)間類(lèi)如 LocalDate、LocalTime、LocalDateTime 提供了一系列 get 方法,用于獲取特定字段的值。

獲取日期中的特定字段:

LocalDate date = LocalDate.of(2024, 3, 11);
int dayOfMonth = date.getDayOfMonth(); // 獲取當(dāng)月的第幾天,此處返回11
int monthValue = date.getMonthValue(); // 獲取月份值,此處返回3
Month month = date.getMonth(); // 獲取Month枚舉,此處返回March
int year = date.getYear(); // 獲取年份,此處返回2024

對(duì)于時(shí)間部分,類(lèi)似地可以獲取小時(shí)、分鐘、秒和納秒:

LocalTime time = LocalTime.of(19, 30, 45);
int hour = time.getHour(); // 獲取小時(shí)數(shù),此處返回10
int minute = time.getMinute(); // 獲取分鐘數(shù),此處返回30
int second = time.getSecond(); // 獲取秒數(shù),此處返回45
int nano = time.getNano(); // 獲取納秒數(shù)

在SpringBoot中使用

SpringBoot默認(rèn)集成了Jackson作為JSON處理庫(kù),Jackson已經(jīng)能自動(dòng)處理 LocalDate、LocalTime 和 LocalDateTime 類(lèi)型。

如果需要使用自定義日期時(shí)間格式,我們有兩種方式:

手動(dòng)更改全局配置: 如果需要自定義日期格式,可以通過(guò) ObjectMapper 的配置類(lèi)來(lái)注冊(cè)自定義的日期格式化器:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-json</artifactId>
</dependency>
@Configuration
public class JacksonConfig {
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
        return builder -> {
            builder.simpleDateFormat("yyyy-MM-dd");
            // 使用Java 8時(shí)間API的日期格式器
            builder.dateFormat(new StdDateFormat().withColonInTimeZone(true));
            // 注冊(cè)LocalDateTime的序列化和反序列化模塊
            builder.modules(new JavaTimeModule());
        };
    }
}

手動(dòng)綁定格式化配置SpringBoot支持自動(dòng)綁定HTTP請(qǐng)求參數(shù)到控制器方法參數(shù)中,包括 LocalDate、LocalTime 和 LocalDateTime 類(lèi)型。客戶(hù)端需發(fā)送符合日期格式的字符串,Spring Boot會(huì)自動(dòng)轉(zhuǎn)換成相應(yīng)類(lèi)型。

@PostMapping("/events")
    public ResponseEntity<Event> createEvent(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date,
                                             @RequestParam @DateTimeFormat(pattern = "HH:mm:ss") LocalTime startTime,
                                             @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime timestamp) {
        // ...
    }

或者請(qǐng)求或者響應(yīng)VO中:

public static class ResponseVO{

        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private  LocalDate date;

        @DateTimeFormat(pattern = "HH:mm:ss") 
        private LocalTime startTime;

        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private  LocalDateTime timestamp;
    }

Mybatis中使用

在MyBatis中查詢(xún)MySQL數(shù)據(jù)庫(kù)時(shí),使用Java 8的 java.time.LocalDate、java.time.LocalTime 和 java.time.LocalDateTime類(lèi)型。

  1. 數(shù)據(jù)庫(kù)表結(jié)構(gòu): 在MySQL數(shù)據(jù)庫(kù)中,通常需要使用適合的日期時(shí)間類(lèi)型來(lái)存儲(chǔ)這些Java 8的日期時(shí)間對(duì)象。例如:

LocalDate 對(duì)應(yīng)MySQL的DATE類(lèi)型。LocalTime 對(duì)應(yīng)MySQL 的 TIME 類(lèi)型。LocalDateTime 對(duì)應(yīng)MySQL的 DATETIME或TIMESTAMP類(lèi)型。

CREATE TABLE `test_date`(
    `id` BIGINT ( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
    test_local_date DATE ,
    test_local_time TIME,
    test_local_date_time DATETIME,
    PRIMARY KEY ( `id` )
)
ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT = '日期時(shí)間測(cè)試';
  1. 實(shí)體類(lèi)映射: 在Java實(shí)體類(lèi)中,對(duì)應(yīng)字段應(yīng)聲明為 LocalDate、LocalTime 或 LocalDateTime 類(lèi)型。
@Data
public class TestDate implements Serializable {
    /**
    * 自增主鍵
    */
    private Long id;

    private LocalDate testLocalDate;

    private LocalTime testLocalTime;

    private LocalDateTime testLocalDateTime;

    private static final long serialVersionUID = 1L;
}

3.MyBatis配置:

  • 自動(dòng)類(lèi)型轉(zhuǎn)換:如果你使用的是較新的MyBatis版本(>=3.4.5),MyBatis已經(jīng)內(nèi)置了對(duì)Java 8日期時(shí)間類(lèi)型的處理。這意味著在執(zhí)行SQL查詢(xún)時(shí),MyBatis會(huì)自動(dòng)將數(shù)據(jù)庫(kù)中的日期時(shí)間字段轉(zhuǎn)換為相應(yīng)的Java8類(lèi)型。
@Test
public void testInsertDate(){
    TestDate testDate = new TestDate();
    testDate.setTestLocalDate(LocalDate.of(2024, 3, 12));
    testDate.setTestLocalTime(LocalTime.of(20,10,30));
    testDate.setTestLocalDateTime(LocalDateTime.of(2024, 3, 12,20,10,30,0));
    testDateMapper.insert(testDate);
}

@Test
public void testQueryDate(){
    TestDate testDate = testDateMapper.selectByPrimaryKey(1L);
    System.out.println("testLocalDate:"+testDate.getTestLocalDate());
    System.out.println("testLocalTime:"+testDate.getTestLocalTime());
    System.out.println("testLocalDateTime:"+testDate.getTestLocalDateTime());
}

image.png

  • 自定義TypeHandler:如果MyBatis版本較低或者需要自定義日期時(shí)間格式,你可能需要自定義 TypeHandler 來(lái)處理 LocalDate、LocalTime 和 LocalDateTime 與數(shù)據(jù)庫(kù)字段間的轉(zhuǎn)換。關(guān)于Mybatis使用自定義TypeHandler,請(qǐng)移步:玩轉(zhuǎn)Mybatis:自定義TypeHandler,輕松應(yīng)對(duì)Mysql的JSON類(lèi)型操作

結(jié)論

本文探討了Java 8引入的全新日期時(shí)間API相較于傳統(tǒng)的Date和Calendar類(lèi)的優(yōu)勢(shì)及實(shí)際應(yīng)用。鑒于Java 8新日期時(shí)間API在設(shè)計(jì)上的先進(jìn)性和易用性,強(qiáng)烈建議積極采納并替換掉陳舊的Date和Calendar類(lèi),轉(zhuǎn)而采用如LocalDate、LocalDateTime、ZonedDateTime等現(xiàn)代日期時(shí)間類(lèi)。

Java 8新日期時(shí)間API提供了更為清晰、直觀的操作接口,支持不可變對(duì)象設(shè)計(jì)模式,增強(qiáng)了類(lèi)型安全性,并具備豐富的日期時(shí)間運(yùn)算、解析與格式化功能,顯著提高了代碼質(zhì)量與可讀性。此外,新API對(duì)日期時(shí)間單位的精確度控制、時(shí)區(qū)管理以及與其他日期時(shí)間規(guī)范的兼容性等方面均表現(xiàn)出卓越的表現(xiàn)力和靈活性,使得我們?cè)谔幚砀黝?lèi)復(fù)雜日期時(shí)間邏輯時(shí)能夠更加得心應(yīng)手,提升開(kāi)發(fā)效率。

責(zé)任編輯:武曉燕 來(lái)源: 碼農(nóng)Academ
相關(guān)推薦

2014-12-22 10:14:31

Java8

2023-01-10 08:27:35

Java8APIJava

2021-08-13 12:53:42

StringBuildStringJoineJava

2019-12-24 09:49:02

微軟英語(yǔ)瀏覽器

2016-07-22 17:55:07

云計(jì)算

2022-05-05 12:02:45

SCSS函數(shù)開(kāi)發(fā)

2020-12-01 07:18:35

Java8日期時(shí)間

2021-04-21 10:36:47

StringBuildJava8StringJoine

2010-08-23 09:56:09

Java性能監(jiān)控

2023-01-02 10:08:42

StampedLocAQS框架

2022-07-17 06:53:24

微服務(wù)架構(gòu)

2023-05-12 07:40:01

Java8API工具

2016-11-29 12:46:24

JavaJava8時(shí)間日期庫(kù)

2021-05-12 10:48:02

蘋(píng)果技巧功能

2021-04-15 12:30:18

ServletSpringMVC 版本

2015-05-14 15:59:33

DockerLinux容器管理工具

2021-02-18 16:06:43

JavaStream代碼

2020-12-14 07:51:16

JS 技巧虛值

2025-08-18 02:55:00

Spring數(shù)據(jù)庫(kù)容器

2018-09-02 15:43:56

Python代碼編程語(yǔ)言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

同心难改在线观看| www.51av欧美视频| 国产美女在线观看一区| 国产欧美亚洲日本| 羞羞色国产精品网站| 欧美成人免费观看| h1515四虎成人| 欧美国产极速在线| 青青草成人影院| 动漫一区二区在线| 欧美一级专区| 欧美精品久久久| 蜜臀精品久久久久久蜜臀| 日韩 欧美 自拍| av欧美精品.com| 亚洲图片欧洲图片日韩av| 碰碰在线视频| 一本色道久久综合狠狠躁篇的优点 | 视频一区国产视频| 国产精品大全| 国产美女娇喘av呻吟久久| 日韩 欧美 视频| 亚洲欧美一区二区三区久本道91 | 国产欧美一区视频| 日韩伦理片在线观看| 欧美亚洲一区三区| 大桥未久在线视频| 欧美久久精品午夜青青大伊人| 懂色av一区二区| 国产精品视频福利| 亚洲男同性恋视频| 亚洲综合在线一区| 最新的欧美黄色| 国产乱码精品一区二区三区四区| 91在线看www| 久久久午夜精品理论片中文字幕| av在线不卡播放| 日韩成人在线视频观看| 少妇高潮一区二区三区99| 亚洲a级在线观看| 91蝌蚪国产九色| 蜜乳av一区| 国产成人精品综合| 国产高清亚洲一区| 国产福利视频在线| 18性欧美xxxⅹ性满足| 狠狠网亚洲精品| 日本24小时在线高清视频| 亚洲精品天天看| 亚洲高清不卡| 亚洲啪啪aⅴ一区二区三区9色| 欧美成人性生活| 久久久久久久电影| 中文成人在线| 成熟了的熟妇毛茸茸| 亚洲精品在线观看网站| 久久国产高清| 亚洲精品天堂| av免费看网址| 在线精品视频一区二区三四| 91视频亚洲| 久久伊人一区二区| 亚洲国产精品一区二区尤物区| 国产精品久久久久av电视剧| 国产精品直播网红| 成人91在线观看| 成人三级网址| 国产精品嫩草影院久久久| www.一区二区| 偷拍精品精品一区二区三区| av一区观看| 亚洲色图视频网| 午夜日韩影院| www.在线观看av| 亚洲男女性事视频| 久久在线91| 蜜桃视频网站在线| 国产精品美女www爽爽爽视频| 国产69精品久久久久777| 国产精品18久久久久久久久 | 青青草原av在线| 久久天堂av综合合色| 杨幂一区二区三区免费看视频| 日本一本中文字幕| 日韩视频免费观看高清完整版在线观看| 91亚洲一区| 免费看成人片| 午夜国产精品一区| 群体交乱之放荡娇妻一区二区| 六月婷婷激情网| 亚洲男人天堂2023| 麻豆91小视频| 欧美偷拍自拍| 福利片在线观看| 国产区精品在线观看| 91丨国产丨九色丨pron| 欧美一级片网址| 成人黄色激情网站| 国产精品久久精品视| 欧美一区二区精美| 亚洲精品欧美| 国产探花视频在线观看| 国产日韩视频在线播放| 色妞久久福利网| 色综合久久中文综合久久97| 日韩电影在线一区二区| 亚洲欧洲日韩精品在线| 夜夜嗨aⅴ免费视频| 欧美成人第一区| 久久av红桃一区二区小说| 午夜精品爽啪视频| 久久成人综合网| 欧美挤奶吃奶水xxxxx| 黄色在线播放| 免费在线a视频| 国产精品视频免费在线| 亚洲国产精品久久久久秋霞蜜臀 | 国产精品天美传媒| 一区二区三区四区五区在线 | 久久成人免费网| 日本一二区不卡| 一本色道69色精品综合久久| 川上优的av在线一区二区| 乱子伦视频在线看| 国外成人在线视频网站| 午夜精品一区二区三区在线视频| 欧洲一区二区三区免费视频| 亚洲欧洲av在线| 美女性感视频久久| 石原莉奈一区二区三区在线观看 | 一本大道久久a久久精二百| 成人短视频下载| 日韩国产欧美一区二区三区| 国产精品成久久久久| 精品国产影院| 欧美最新精品| 欧洲亚洲两性| www.成人爱| 性感美女一区二区在线观看| 一个人www视频在线免费观看| bt在线麻豆视频| 欧美男男video| mm视频在线视频| 97久久精品一区二区三区的观看方式| videos性欧美另类高清| 日韩福利一区| 亚洲人体在线| 伊人久久大香线蕉综合网蜜芽| 亚洲国产一区二区三区网站| 狼人天天伊人久久| 免费精品国产| 欧美日本三区| 久久国产夜色精品鲁鲁99| 国产不卡视频一区二区三区| 不卡av在线网| 亚洲成av人影院| 91精品国产手机| 亚洲女人被黑人巨大进入al| 亚洲欧洲午夜一线一品| 欧美劲爆第一页| 2014亚洲精品| h无码动漫在线观看| 色视频www在线播放国产| 成人免费在线电影| 天堂中文av在线资源库| 亚洲一区电影| 免费国产自线拍一欧美视频| 成人毛片老司机大片| 亚洲人成伊人成综合网小说| 91国偷自产一区二区开放时间 | 婷婷伊人综合| 国产伦精品一区二区三区免费迷 | 美女av免费观看| 麻豆一区二区三区四区精品蜜桃| 粉嫩一区二区三区国产精品| 欧美精选视频一区二区| 香蕉精品视频在线观看| 国产一区二区三区黄视频| 一区二区三区四区在线免费观看| 亚洲电影免费观看高清完整版在线| 欧美精品在线观看| 久久精品二区| 360天大佬第二季在线观看| 日本综合视频| 国产欧美短视频| 亚洲成人福利片| 午夜精品一区二区三区在线 | 国产激情在线观看视频| 免费**毛片在线| 欧美一区二区三区激情视频| 99国产欧美另类久久久精品| 欧美精品亚洲一区二区在线播放| 国产精品欧美久久久| 日本www在线播放| 综合久久2023| 久久国产尿小便嘘嘘| 69堂精品视频| 欧美一区二区三区四区五区六区| 日韩av中文| 奇米精品一区二区三区四区 |