當前位置: 妍妍網 > 碼農

CTO說: 誰再用 Calendar 處理時間,明天別來了

2024-04-28碼農

Java 8 釋出已經10年了,可是還在有人用 Java Calendar 處理時間和日期,不僅僅效能差,很切程式碼很冗余, 所以 CTO 強制要求,必須使用 Java 8 新的API 處理日期,否則一律不用來了。下面是整理的 18 種處理日期的方式,可以收藏起來,一定有用。

Java 處理日期、行事曆和時間的方式一直為社群所詬病,將 java.util.Date 設定為可變型別,以及 SimpleDateFormat 的非執行緒安全使其套用非常受限。

新 API 基於 ISO 標準行事曆系統,java.time 包下的所有類都是不可變型別而且執行緒安全。

18 個 Java8 日期處理實踐

範例1:Java 8 中獲取今天的日期

Java 8 中的 LocalDate 用於表示當天日期。和 java.util.Date 不同,它只有日期,不包含時間。當你僅需要表示日期時就用這個類。

package com.shxt.demo02;
import java.time.LocalDate;
public classDemo01{
publicstaticvoidmain(String[] args){
LocalDate today = LocalDate.now();
System.out.println("今天的日期:"+today);
}
}
/*
 執行結果:
今天的日期:2020-02-05
*/

範例 2:Java 8 中獲取年、月、日資訊

package com.shxt.demo02;
import java.time.LocalDate;
public classDemo02{
publicstaticvoidmain(String[] args){
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);
}
}


範例 3:Java 8 中處理特定日期

我們透過靜態工廠方法 now() 非常容易地建立了當天日期,你還可以呼叫另一個有用的工廠方法 LocalDate.of() 建立任意日期, 該方法需要傳入年、月、日做參數,返回對應的 LocalDate 例項。

這個方法的好處是沒再犯老 API 的設計錯誤,比如年度起始於 1900,月份是從 0 開始等等。

package com.shxt.demo02;
import java.time.LocalDate;
public classDemo03{
publicstaticvoidmain(String[] args){
LocalDate date = LocalDate.of(2020,2,6);
System.out.println("自訂日期:"+date);
}
}

範例 4:Java 8 中判斷兩個日期是否相等

package com.shxt.demo02;
import java.time.LocalDate;
public classDemo04{
publicstaticvoidmain(String[] args){
LocalDate date1 = LocalDate.now();
LocalDate date2 = LocalDate.of(2020,2,5);
if(date1.equals(date2)){
System.out.println("時間相等");
}else{
System.out.println("時間不等");
}
}
}



範例 5:Java 8 中檢查像生日這種周期性事件

package com.shxt.demo02;
import java.time.LocalDate;
import java.time.MonthDay;
public classDemo05{
publicstaticvoidmain(String[] args){
LocalDate date1 = LocalDate.now();
LocalDate date2 = LocalDate.of(2020,2,6);
MonthDay birthday = MonthDay.of(date2.getMonth(),date2.getDayOfMonth());
MonthDay currentMonthDay = MonthDay.from(date1);
if(currentMonthDay.equals(birthday)){
System.out.println("是你的生日");
}else{
System.out.println("你的生日還沒有到");
}
}
}



只要當天的日期和生日匹配,無論是哪一年都會打印出祝賀資訊。你可以把程式整合進系統時鐘,看看生日時是否會受到提醒,或者寫一個單元測試來檢測程式碼是否執行正確。

範例 6:Java 8 中獲取當前時間

package com.shxt.demo02;
import java.time.LocalTime;
public classDemo06{
publicstaticvoidmain(String[] args){
LocalTime time = LocalTime.now();
System.out.println("獲取當前的時間,不含有日期:"+time);
}
}

可以看到當前時間就只包含時間資訊,沒有日期。

範例 7:Java 8 中獲取當前時間

透過增加小時、分、秒來計算將來的時間很常見。Java 8 除了不變型別和執行緒安全的好處之外,還提供了更好的 plusHours() 方法替換 add(),並且是相容的。

註意,這些方法返回一個全新的 LocalTime 例項,由於其不可變性,返回後一定要用變量賦值。

package com.shxt.demo02;
import java.time.LocalTime;
public classDemo07{
publicstaticvoidmain(String[] args){
LocalTime time = LocalTime.now();
LocalTime newTime = time.plusHours(3);
System.out.println("三個小時後的時間為:"+newTime);
}
}

範例 8:Java 8 如何計算一周後的日期

和上個例子計算 3 小時以後的時間類似,這個例子會計算一周後的日期。

LocalDate 日期不包含時間資訊,它的 plus() 方法用來增加天、周、月,ChronoUnit 類別宣告了這些時間單位。由於 LocalDate 也是不變型別,返回後一定要用變量賦值。

package com.shxt.demo02;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public classDemo08{
publicstaticvoidmain(String[] args){
LocalDate today = LocalDate.now();
System.out.println("今天的日期為:"+today);
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
System.out.println("一周後的日期為:"+nextWeek);
}
}

可以看到新日期離當天日期是 7 天,也就是一周。你可以用同樣的方法增加 1 個月、1 年、1 小時、1 分鐘甚至一個世紀,更多選項可以檢視 Java 8 API 中的 ChronoUnit 類。

範例 9:Java 8 計算一年前或一年後的日期

利用 minus() 方法計算一年前的日期:

package com.shxt.demo02;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public classDemo09{
publicstaticvoidmain(String[] args){
LocalDate today = LocalDate.now();
LocalDate previousYear = today.minus(1, ChronoUnit.YEARS);
System.out.println("一年前的日期 : " + previousYear);
LocalDate nextYear = today.plus(1, ChronoUnit.YEARS);
System.out.println("一年後的日期:"+nextYear);
}
}



範例 10:Java 8 的 Clock 時鐘類

Java 8 增加了一個 Clock 時鐘類用於獲取當時的時間戳,或當前時區下的日期時間資訊。

以前用到 System.currentTimeInMillis() 和 TimeZone.getDefault() 的地方都可用 Clock 替換。

package com.shxt.demo02;
import java.time.Clock;
public classDemo10{
publicstaticvoidmain(String[] args){
// Returns the current time based on your system clock and set to UTC.
Clock clock = Clock.systemUTC();
System.out.println("Clock : " + clock.millis());
// Returns time based on system clock zone
Clock defaultClock = Clock.systemDefaultZone();
System.out.println("Clock : " + defaultClock.millis());
}
}


範例 11:如何用 Java 判斷日期是早於還是晚於另一個日期

另一個工作中常見的操作就是如何判斷給定的一個日期是大於某天還是小於某天?

在 Java 8 中,LocalDate 類有兩類方法 isBefore() 和 isAfter() 用於比較日期。呼叫 isBefore() 方法時,如果給定日期小於當前日期則返回 true。

package com.shxt.demo02;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public classDemo11{
publicstaticvoidmain(String[] args){
LocalDate today = LocalDate.now();
LocalDate tomorrow = LocalDate.of(2018,2,6);
if(tomorrow.isAfter(today)){
System.out.println("之後的日期:"+tomorrow);
}
LocalDate yesterday = today.minus(1, ChronoUnit.DAYS);
if(yesterday.isBefore(today)){
System.out.println("之前的日期:"+yesterday);
}
}
}


範例 12:Java 8 中處理時區

Java 8 不僅分離了日期和時間,也把時區分離出來了。現在有一系列單獨的類如 ZoneId 來處理特定時區,ZoneDateTime 類來表示某時區下的時間。

這在 Java 8 以前都是 GregorianCalendar 類來做的。下面這個例子展示了如何把本時區的時間轉換成另一個時區的時間。

package com.shxt.demo02;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public classDemo12{
publicstaticvoidmain(String[] args){
// Date and time with timezone in Java 8
ZoneId america = ZoneId.of("America/New_York");
LocalDateTime localtDateAndTime = LocalDateTime.now();
ZonedDateTime dateAndTimeInNewYork = ZonedDateTime.of(localtDateAndTime, america );
System.out.println("Current date and time in a particular timezone : " + dateAndTimeInNewYork);
}
}

範例 13:如何表示信用卡到期這類固定日期,答案就在 YearMonth

與 MonthDay 檢查重復事件的例子相似,YearMonth 是另一個組合類,用於表示信用卡到期日、FD 到期日、期貨期權到期日等。

還可以用這個類得到當月共有多少天,YearMonth 例項的 lengthOfMonth() 方法可以返回當月的天數,在判斷 2 月有 28 天還是 29 天時非常有用。

package com.shxt.demo02;
import java.time.*;
public classDemo13{
publicstaticvoidmain(String[] args){
YearMonth currentYearMonth = YearMonth.now();
System.out.printf("Days in month year %s: %d%n", currentYearMonth, currentYearMonth.lengthOfMonth());
YearMonth creditCardExpiry = YearMonth.of(2019, Month.FEBRUARY);
System.out.printf("Your credit card expires on %s %n", creditCardExpiry);
}
}

範例 14:如何在 Java 8 中檢查閏年

package com.shxt.demo02;
import java.time.LocalDate;
public classDemo14{
publicstaticvoidmain(String[] args){
LocalDate today = LocalDate.now();
if(today.isLeapYear()){
System.out.println("This year is Leap year");
}else {
System.out.println("2018 is not a Leap year");
}
}
}

範例 15:計算兩個日期之間的天數和月數

有一個常見日期操作是計算兩個日期之間的天數、周數或月數。在 Java 8 中可以用 java.time.Period 類來做計算。

下面這個例子中,我們計算了當天和將來某一天之間的月數。

package com.shxt.demo02;
import java.time.LocalDate;
import java.time.Period;
public classDemo15{
publicstaticvoidmain(String[] args){
LocalDate today = LocalDate.now();
LocalDate java8Release = LocalDate.of(20181214);
Period periodToNextJavaRelease = Period.between(today, java8Release);
System.out.println("Months left between today and Java 8 release : "
+ periodToNextJavaRelease.getMonths() );

}
}



範例 16:在 Java 8 中獲取當前的時間戳

Instant 類有一個靜態工廠方法 now() 會返回當前的時間戳,如下所示:

package com.shxt.demo02;
import java.time.Instant;
public classDemo16{
publicstaticvoidmain(String[] args){
Instant timestamp = Instant.now();
System.out.println("What is value of this instant " + timestamp.toEpochMilli());
}
}

時間戳資訊裏同時包含了日期和時間,這和 java.util.Date 很像。

實際上 Instant 類確實等同於 Java 8 之前的 Date 類,你可以使用 Date 類和 Instant 類各自的轉換方法互相轉換。

例如:Date.from(Instant) 將 Instant 轉換成 java.util.Date,Date.toInstant() 則是將 Date 類轉換成 Instant 類。

範例 17:Java 8 中如何使用預定義的格式化工具去解析或格式化日期

package com.shxt.demo02;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public classDemo17{
publicstaticvoidmain(String[] args){
String dayAfterTommorrow = "20180205";
LocalDate formatted = LocalDate.parse(dayAfterTommorrow,
DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(dayAfterTommorrow+" 格式化後的日期為: "+formatted);
}
}

範例 18:字串互轉日期型別

package com.shxt.demo02;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public classDemo18{
publicstaticvoidmain(String[] args){
LocalDateTime date = LocalDateTime.now();
DateTimeFormatter format1 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
//日期轉字串
String str = date.format(format1);
System.out.println("日期轉換為字串:"+str);
DateTimeFormatter format2 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
//字串轉日期
LocalDate date2 = LocalDate.parse(str,format2);
System.out.println("日期型別:"+date2);
}
}



文章來源:juejin.cn/post/6937888716438372389

>>

END

精品資料,超贊福利,免費領

微信掃碼/長按辨識 添加【技術交流群

群內每天分享精品學習資料

最近開發整理了一個用於速刷面試題的小程式;其中收錄了上千道常見面試題及答案(包含基礎並行JVMMySQLRedisSpringSpringMVCSpringBootSpringCloud訊息佇列等多個型別),歡迎您的使用。

👇👇

👇點選"閱讀原文",獲取更多資料(持續更新中