關(guān)于LocalDateTime使用詳解
使用 LocalDateTime 替代 Date
JDK 中的 Date 的缺點:
- Date 如果不格式化,打印出的日期可讀性差;
- 使用 SimpleDateFormat 可以對日期時間進行格式化,但是 SimpleDateFormat 并非線性安全;
- Date 對時間處理比較麻煩;
- Date 這個類名的命名并不嚴謹。
另外,《阿里巴巴開發(fā)手冊》中明確禁用 static 關(guān)鍵字修飾 SimpleDateFormat 。
Java 官方請著名的第三方日期時間包 joda-time 的作者重新設(shè)計了與日期時間有關(guān)的 API 部分,并把它們放在了 jdk 8 的 java.time 包下。
新增了:LocalDate、LocalTime、LocalDateTime 三個類及相關(guān)新的 API 用以替代 Date 及其舊的使用方式。
1. LocalDate
只會獲取 年月日 信息。
LocalDate 中并不包含『時區(qū)』信息。即,一個單獨的 LocalDate 對象所表達的含義是不嚴謹?shù)摹?LocalTime 和 LocalDateTime 也一樣。
- 創(chuàng)建 LocalDate 對象
LocalDate localDate = LocalDate.now(); LocalDate localDate = LocalDate.of(2000, 1, 1);
- 獲取年、月、日、星期幾
LocalDate localDate = LocalDate.now(); int year = localDate.getYear(); int year = localDate.get(ChronoField.YEAR); Month month = localDate.getMonth(); int month = localDate.get(ChronoField.MONTH_OF_YEAR); int day = localDate.getDayOfMonth(); int day = localDate.get(ChronoField.DAY_OF_MONTH); DayOfWeek dayOfWeak = localDate.getDayOfWeek(); int dayOfWeak = localDate.get(ChronoField.DAY_OF_WEEK);
2. LocalTime
只會獲取 時分秒 信息。
- 創(chuàng)建 LocalTime 對象
LocalTime localTime = LocalTime.now(); LocalTime localTime = LocalTime.of(17, 30, 0);
- 獲取時分秒
int hour = localTime.getHour(); int hour = localTime.get(ChronoField.HOUR_OF_DAY); int minute = localTime.getMinute(); int minute = localTime.get(ChronoField.MINUTE_OF_HOUR); int second = localTime.getSecond(); int second = localTime.get(ChronoField.SECOND_OF_MINUTE);
3. LocaDateTime
獲取 年月日時分秒,等于 LocalDate + LocalTime 。
- 創(chuàng)建 LocalDateTime
LocalDateTime localDateTime = LocalDateTime.now(); LocalDateTime localDateTime = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56); LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime); LocalDateTime localDateTime = localDate.atTime(localTime); LocalDateTime localDateTime = localTime.atDate(localDate);
- 獲取 LocalDate
LocalDate localDate = localDateTime.toLocalDate();
- 獲取 LocalTime
LocalTime localTime = localDateTime.toLocalTime();
4. Instant
在 Java 中,一個 Instant 對象標識時間軸上的一個點,代表著一個概念上的瞬間。
『原點』是眾所周知的 1970 年 1 月 1 日的午夜,此時本初子午線正在穿過倫敦格林威治皇家天文臺。
從『原點』開始,時間按照每天 86400 秒進行正向、反向計算,向前、向后分別以納秒為單位。
- warning 注意:
- Instant 是有時區(qū)概念的,在你未指定時,它的默認時區(qū)時 0 時區(qū),即,格林威治時間。
雖然 Instant 內(nèi)部是以納秒為單位進行存儲、運算的,但是很顯然你可以將它轉(zhuǎn)換成相較于『原點 (epoch) 』的時、分、秒。
在編程世界中,我們?nèi)粘I钪兴f的『秒』使用的是 second ;而『相較于原點的秒』使用的是 epoch second 。 epoch 是時代、紀元等含義。
另外,在 Java 8 中,使用 Duration 對象來代表兩個 Instant 之間的時間跨度。
- 創(chuàng)建 Instant 對象
Instant instant = Instant.now();
- 獲取秒數(shù)
long currentSecond = instant.getEpochSecond();
- 獲取毫秒數(shù)
long currentMilli = instant.toEpochMilli();
個人覺得如果只是為了獲取秒數(shù)或者毫秒數(shù),使用 System.currentTimeMillis() 來得更為方便。
5. 修改 LocalDate、LocalTime、LocalDateTime、Instant
LocalDate、LocalTime、LocalDateTime、Instant 為『不可變對象』,修改這些對象對象會返回一個副本,即生成并返回一個新對象。
- 增加、減少年數(shù)、月數(shù)、天數(shù)等 以 LocalDateTime 為例
LocalDateTime localDateTime = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56); // 增加一年 localDateTime = localDateTime.plusYears(1); localDateTime = localDateTime.plus(1, ChronoUnit.YEARS); // 減少一個月 localDateTime = localDateTime.minusMonths(1); localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);
- 通過 with 修改某些值
// 修改年為 2019 localDateTime = localDateTime.withYear(2020); // 修改為 2022 localDateTime = localDateTime.with(ChronoField.YEAR, 2022); // 還可以修改月、日
6. 使用 TemporalAdjuster 和 TemporalAdjusters
有的時候,你需要進行一些更加復(fù)雜的日期操作,比如,將日期調(diào)整到下個周日、下個工作日,或者是本月的最后一天。這時,你可以使用重載版本的 withXXX 方法,向其傳遞一個提供了更多定制化選擇的 TemporalAdjuster 對象, 更加靈活地處理日期。
比如有些時候想知道這個月的最后一天是幾號、下個周末是幾號,通過提供的時間和日期API可以很快得到答案。
對于最常見的用例,日期和時間 API 已經(jīng)提供了大量預(yù)定義的 TemporalAdjuster 對象。你可以通過 TemporalAdjusters (注意,此處有 s) 類的靜態(tài)工廠方法訪問它們。
TemporalAdjusters 類中的常用工廠方法:
- dayOfWeekInMonth 創(chuàng)建一個新的日期,它的值為同一個月中每一周的第幾天
- firstDayOfMonth 創(chuàng)建一個新的日期,它的值為當月的第一天
- firstDayOfNextMonth 創(chuàng)建一個新的日期,它的值為下月的第一天
- firstDayOfNextYear 創(chuàng)建一個新的日期,它的值為明年的第一天
- firstDayOfYear 創(chuàng)建一個新的日期,它的值為當年的第一天
- firstInMonth 創(chuàng)建一個新的日期,它的值為同一個月中,第一個符合星期幾要求的值
- lastDayOfMonth 創(chuàng)建一個新的日期,它的值為當月的最后一天
- lastDayOfNextMonth 創(chuàng)建一個新的日期,它的值為下月的最后一天
- lastDayOfNextYear 創(chuàng)建一個新的日期,它的值為明年的最后一天
- lastDayOfYear 創(chuàng)建一個新的日期,它的值為今年的最后一天
- lastInMonth 創(chuàng)建一個新的日期,它的值為同一個月中,最后一個符合星期幾要求的值
- next / previous 創(chuàng)建一個新的日期,并將其值設(shè)定為日期調(diào)整后或者調(diào)整前,第一個符合指定星 期幾要求的日期
- nextOrSame / previousOrSame 創(chuàng)建一個新的日期,并將其值設(shè)定為日期調(diào)整后或者調(diào)整前,第一個符合指定星 期幾要求的日期,如果該日期已經(jīng)符合要求,直接返回該對象
7. 格式化時間
DateTimeFormatter 默認提供了多種格式化方式,如果默認提供的不能滿足要求,可以通過 DateTimeFormatter 的 ofPattern 方法創(chuàng)建自定義格式化方式。
LocalDate localDate = LocalDate.of(2019, 9, 10); String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE); String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE); // 自定義格式化 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); String s3 = localDate.format(dateTimeFormatter);
8. 解析時間
相較于傳統(tǒng)的 SimpleDateFormat,DateTimeFormatter 是線程安全的
LocalDate localDate1 = LocalDate.parse("20190910", DateTimeFormatter.BASIC_ISO_DATE); LocalDate localDate2 = LocalDate.parse("2019-09-10", DateTimeFormatter.ISO_LOCAL_DATE);
Date 與 LocalDate 互轉(zhuǎn):
- Date 轉(zhuǎn) LocalDate
// Date 轉(zhuǎn) LocalDate public static LocalDate date2LocalDate(Date date) { return (date == null) ? (null) : (date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()); }
- LocalDate 轉(zhuǎn) Date
// LocalDate轉(zhuǎn)Date public static Date localDate2Date(LocalDate localDate) { return (localDate == null) ? (null) : (Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant())); }
9. 帶時區(qū)的時間
LocalDate、LocalTime 和 LocalDateTime 是不帶時區(qū)信息的。在 JDK 8 中,帶有時區(qū)信息的日期時間類是 ZonedDateTime 。
因特網(wǎng)編號管理局 (IANA) 維護著一份全球所有已知時區(qū)的數(shù)據(jù)庫(http://www.iana.org/time-zones),每年會更新幾次(這些更新主要處理夏令時規(guī)則的改變)。Java 就是使用了 IANA 的數(shù)據(jù)庫。
在 Java 中,每個時區(qū)都有一個 ID,例如 Asia/Shanghai 。想要獲得所有可用的時區(qū),你可以調(diào)用 ZoneId.getAvailableZoneIds() 。 大概有 600 個。
如果你想獲得 ZonedDateTime 對象,你有 2 種途徑:
- 直接使用 ZonedDateTime.of() 方法創(chuàng)建;
- 先創(chuàng)建一個 LocalDateTime 對象 (它不含時區(qū)概念) ,再調(diào)用它的 atZone 方法,賦予它時區(qū)的概念,生成 ZonedDateTime 對象。
10. SpringBoot 中應(yīng)用 LocalDateTime
將 LocalDateTime 字段以時間戳的方式返回給前端。
添加日期轉(zhuǎn)化類:
public class LocalDateTimeConverter extends JsonSerializer<LocalDateTime> { @Override public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeNumber(value.toInstant(ZoneOffset.of("+8")).toEpochMilli()); } }
并在 LocalDateTime 字段上添加 @JsonSerialize(using = LocalDateTimeConverter.class) 注解,如下:
@JsonSerialize(using = LocalDateTimeConverter.class) protected LocalDateTime gmtModified;
將 LocalDateTime 字段以指定格式化日期的方式返回給前端
在 LocalDateTime 字段上添加 @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss") 注解即可,如下:
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss") protected LocalDateTime gmtModified;
對前端傳入的日期進行格式化
在 LocalDateTime 字段上添加 @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 注解即可,如下:
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") protected LocalDateTime gmtModified;
Java Date and Time API 用在持久層
LocalDateTime in Mybatis
MyBatis 從 3.4.5 版本開始就完全支持這種類型了,不在需要自己去寫類型轉(zhuǎn)換 。
LocalDateTime in spring-data-jpa
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-java8</artifactId> </dependency>
LocalDateTime in spring-data-redis
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency>
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot整合Shiro框架,實現(xiàn)用戶權(quán)限管理
Apache Shiro是一個強大且易用的Java安全框架,執(zhí)行身份驗證、授權(quán)、密碼和會話管理。作為一款安全框架Shiro的設(shè)計相當巧妙。Shiro的應(yīng)用不依賴任何容器,它不僅可以在JavaEE下使用,還可以應(yīng)用在JavaSE環(huán)境中。2021-06-06public?static?void?main(String[]?args)使用解讀
這篇文章主要介紹了public?static?void?main(String[]?args)的使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01SpringMvc+Mybatis+Pagehelper分頁詳解
這篇文章主要介紹了SpringMvc+Mybatis+Pagehelper分頁詳解,非常不錯,具有參考借鑒價值,需要的朋友可以參考下的相關(guān)資料2017-01-01Spring Boot應(yīng)用開發(fā)初探與實例講解
這篇文章主要介紹了Spring Boot應(yīng)用開發(fā)初探與實例講解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07SpringMVC 中HttpMessageConverter簡介和Http請求415 的問題
本文介紹且記錄如何解決在SpringMVC 中遇到415 Unsupported Media Type 的問題,并且順便介紹Spring MVC的HTTP請求信息轉(zhuǎn)換器HttpMessageConverter2016-07-07使用Spring boot + jQuery上傳文件(kotlin)功能實例詳解
本文通過實例代碼給大家介紹了使用Spring boot + jQuery上傳文件(kotlin) 功能,需要的朋友可以參考下2017-07-07