18 個示例帶你掌握 Java 8 日期時間處理!

2021-12-29 程式設計師大咖

作者|胖先森

來源丨java後端

https://juejin.im/post/5a795bad6fb9a0634f407ae5

Java 8 推出了全新的日期時間API,在教程中我們將通過一些簡單的實例來學習如何使用新API。
Java處理日期、日曆和時間的方式一直為社區所詬病,將 java.util.Date設定為可變類型,以及SimpleDateFormat的非線程安全使其應用非常受限。新API基於ISO標準日曆系統,java.time包下的所有類都是不可變類型而且線程安全。

包含日期和時間,比如:2018-02-05 23:14:21java.time.format.DateTimeFormatterJava 8 中的 LocalDate 用於表示當天日期。和java.util.Date不同,它只有日期,不包含時間。當你僅需要表示日期時就用這個類。

package com.shxt.demo02;

import java.time.LocalDate;

public class Demo01 {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        System.out.println("今天的日期:"+today);
    }
}

package com.shxt.demo02;

import java.time.LocalDate;

public class Demo02 {
    public static void main(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);

    }
}

我們通過靜態工廠方法now()非常容易地創建了當天日期,你還可以調用另一個有用的工廠方法LocalDate.of()創建任意日期, 該方法需要傳入年、月、日做參數,返回對應的LocalDate實例。這個方法的好處是沒再犯老API的設計錯誤,比如年度起始於1900,月份是從0開 始等等。

import java.time.LocalDate;

public class Demo03 {
    public static void main(String[] args) {
        LocalDate date = LocalDate.of(2018,2,6);
        System.out.println("自定義日期:"+date);
    }
}

import java.time.LocalDate;

public class Demo04 {
    public static void main(String[] args) {
        LocalDate date1 = LocalDate.now();

        LocalDate date2 = LocalDate.of(2018,2,5);

        if(date1.equals(date2)){
            System.out.println("時間相等");
        }else{
            System.out.println("時間不等");
        }

    }
}

import java.time.LocalDate;
import java.time.MonthDay;

public class Demo05 {
    public static void main(String[] args) {
        LocalDate date1 = LocalDate.now();

        LocalDate date2 = LocalDate.of(2018,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("你的生日還沒有到");
        }

    }
}

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

import java.time.LocalTime;

public class Demo06 {
    public static void main(String[] args) {
        LocalTime time = LocalTime.now();
        System.out.println("獲取當前的時間,不含有日期:"+time);

    }
}

通過增加小時、分、秒來計算將來的時間很常見。Java 8除了不變類型和線程安全的好處之外,還提供了更好的plusHours()方法替換add(),並且是兼容的。注意,這些方法返回一個全新的LocalTime實例,由於其不可變性,返回後一定要用變量賦值。

import java.time.LocalTime;

public class Demo07 {
    public static void main(String[] args) {
        LocalTime time = LocalTime.now();
        LocalTime newTime = time.plusHours(3);
        System.out.println("三個小時後的時間為:"+newTime);

    }
}

和上個例子計算3小時以後的時間類似,這個例子會計算一周後的日期。LocalDate日期不包含時間信息,它的plus()方法用來增加天、周、月,ChronoUnit類聲明了這些時間單位。由於LocalDate也是不變類型,返回後一定要用變量賦值。

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public class Demo08 {
    public static void main(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類。

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public class Demo09 {
    public static void main(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);

    }
}

Java 8增加了一個Clock時鐘類用於獲取當時的時間戳,或當前時區下的日期時間信息。以前用到System.currentTimeInMillis()和TimeZone.getDefault()的地方都可用Clock替換。

import java.time.Clock;

public class Demo10 {
    public static void main(String[] args) {
        
        Clock clock = Clock.systemUTC();
        System.out.println("Clock : " + clock.millis());

        
        Clock defaultClock = Clock.systemDefaultZone();
        System.out.println("Clock : " + defaultClock.millis());

    }
}

示例11:如何用Java判斷日期是早於還是晚於另一個日期另一個工作中常見的操作就是如何判斷給定的一個日期是大於某天還是小於某天?在Java 8中,LocalDate類有兩類方法isBefore()和isAfter()用於比較日期。調用isBefore()方法時,如果給定日期小於當前日期則返回true。

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;


public class Demo11 {
    public static void main(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);
        }
    }
}

Java 8不僅分離了日期和時間,也把時區分離出來了。現在有一系列單獨的類如ZoneId來處理特定時區,ZoneDateTime類來表示某時區下的時間。關注微信公眾號:Java技術棧,在後臺回覆:新特性,可以獲取我整理的 N 篇最新 Java 新特性教程,都是乾貨。這在Java 8以前都是 GregorianCalendar類來做的。下面這個例子展示了如何把本時區的時間轉換成另一個時區的時間。

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Demo12 {
    public static void main(String[] args) {
        
        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天時非常有用。

import java.time.*;

public class Demo13 {
    public static void main(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);
    }
}

import java.time.LocalDate;

public class Demo14 {
    public static void main(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");
        }

    }
}

有一個常見日期操作是計算兩個日期之間的天數、周數或月數。在Java 8中可以用java.time.Period類來做計算。下面這個例子中,我們計算了當天和將來某一天之間的月數。

import java.time.LocalDate;
import java.time.Period;

public class Demo15 {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();

        LocalDate java8Release = LocalDate.of(2018, 12, 14);

        Period periodToNextJavaRelease = Period.between(today, java8Release);
        System.out.println("Months left between today and Java 8 release : "
                + periodToNextJavaRelease.getMonths() );


    }
}

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

package com.shxt.demo02;

import java.time.Instant;

public class Demo16 {
    public static void main(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中如何使用預定義的格式化工具去解析或格式化日期

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Demo17 {
    public static void main(String[] args) {
        String dayAfterTommorrow = "20180205";
        LocalDate formatted = LocalDate.parse(dayAfterTommorrow,
                DateTimeFormatter.BASIC_ISO_DATE);
        System.out.println(dayAfterTommorrow+" 格式化後的日期為: "+formatted);
    }
}

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Demo18 {
    public static void main(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);

    }
}

相關焦點

  • 這些 Java 8 官方挖的坑,你踩過幾個?
    日期明明間隔1年卻輸出1天,難不成這是天上人間?1582年神秘消失的10天JDK能否識別?Stream很高大上,List轉Map卻全失敗……這些JDK8官方挖的坑,你踩過幾個?好在千呼萬喚之後,使出來了,Java8帶來了全新的日期和時間API,還帶來了Period和Duration用於時間日期計算的兩個API。Duraction和Period,都表示一段時間的間隔,Duraction正常用來表示時、分、秒甚至納秒之間的時間間隔,Period正常用於年、月、日之間的時間間隔。
  • 初識Java8 Stream、流的基本操作
    數據處理操作流的側重點並不在數據存儲,而在於數據處理,例如示例中的filter、map、forEach等。迭代方式流的迭代方式為內部迭代,而集合的迭代方式為外部迭代。例如我們遍歷Collection接口需要用戶去做迭代,例如for-each,然後在循環體中寫對應的處理代碼,這叫外部迭代。
  • Java 15 正式發布, 14 個新特性,刷新你的認知!!
    現在的 JDK 真變成了「版本帝」,無力吐槽啊,版本發到 15,大部分人卻都還在用著 JDK 7/8,甚至 6。不過沒關係,多了解一下,多掌握一點新東西,對你來說沒有壞處。,下面棧長帶大家來解讀下這些新特性!
  • Java 訪問權限控制:你真的了解 protected 關鍵字嗎?
    (o.hashCode());    }} 我們給自己的程序設置的包名是java.lang,事實上,java.lang是JDK使用的包名。在Java中,類成員的訪問權限修飾詞有四個:private,無(包訪問權限),protected 和 public,其權限控制如下表所示:     特別要注意的是,不同於類成員的訪問權限類別,對於非內部類而言,類的訪問權限修飾詞僅有public和包訪問權限兩種(內部類可以是private或protected的。
  • GitHub 上那些值得一試的 Java 開源庫
    在這多達330,000個JAVA開源庫中,我收集了下面這些或許也值得你一試的Java開源庫。Strmen-java是一個字符串處理工具,你可以通過maven將它引入到項目中。除了Java本身的字符串處理方式外,我們還可以使用Apache Common Langs裡的StringUtils來簡化String的操作。
  • 20個非常有用的Java程序片段
    點擊上方「程式設計師共讀」,選擇「置頂公眾號」關鍵時刻,第一時間送達
  • Java學到什麼程度才能叫精通?
    我個人覺得「精通」這個詞有點過,一般人是不會說自己精通某個東西,通常用熟練並掌握來說明你對某個技術有研究。下面是我總結的一些初中級Java程式設計師必備的知識:總結:初中級 Java 程式設計師必須掌握的知識。熟練掌握數據結構、算法、作業系統、計算機網絡等基礎知識。
  • Java 9 中的 9 個新特性
    Java 8 發布三年多之後,即將快到2017年7月下一個版本發布的日期了。
  • 2020 年,你還在使用 Java 中的 SimpleDateFormat 嗎?
    :22:52CST 2020因此,我們經常需要把時間進行格式化處理,然後在進行存儲,方便閱讀。String datestr = df.format(date); System.out.println(datestr);最終輸出的時間為2020-06-07 16:45:58由於在java 8之前 SimpleDateFormat 是一個比較常用的類
  • Python日期的處理——datetime模塊
    本次培訓採用理論與案例相結合的方式,旨在幫助零基礎學員輕鬆入門Python,由淺入深學習和掌握Python爬蟲技術,並明確未來更進一步的學習方向。詳細培訓大綱及報名方式,請點擊文末閱讀原文呦~Python中用於處理日期和時間的模塊包括time、datetime和calendar。
  • 阿里內部學習指南《Effective Java中文 第3版》程式設計師進階必備
    經典Jolt獲獎作品《Effective Java》的第3版這本書,對上一版內容進行了徹底的更新,介紹了如何充分利用從泛型到枚舉、從註解到自動裝箱的各種特性,幫助讀者更加有效地使用Java程式語言及其基本類庫:java.lang. java.util和java.io,以及子包,如java.util. concurrent和java.util.function等。
  • 20張示例照,教你5個「小臉」拍攝秘籍
    其實,想要拍照顯臉小一些,掌握技巧就可以了。不妨一起隨著下面20張示例照,跟大家分享5個「小臉」拍攝秘籍,解決「大餅臉」難題,希望你也能自信面對鏡頭。1、善「尋」角度經常自拍的女生肯定深有體會,選擇恰當的拍攝視角不僅可以增強美感,而且可以起到「小臉」的作用,要做的就是多多嘗試,了解自己。
  • 昨天你用的 YYYY-MM-dd 被 CTO 捶了嗎?
    這不,就有胖友聊到一個經典的「神坑」:錯誤使用 YYYY-MM-dd 格式化時間,導致生產翻車。帶有馬賽克的群聊下面,艿艿帶大家寫一個翻車的 Java 示例代碼:import java.text.SimpleDateFormat
  • java程式設計師常用的11個API,趕緊收藏
    15.Arrays.parallelSetAll(T[] array, IntFunctionInteger[] data = {2, 3, 4, 5};// 第一個元素2不變,將其與第二個元素3一起作為參數x, y傳入,得到乘積6,作為數組新的第二個元素// 再將6和第三個元素4一起作為參數x, y傳入,得到乘積24,作為數組新的第三個元素,以此類推
  • Java中10大常問的關於String的問題
    即使新手覺得String引用變了實際上只是(指針)引用指向了另一個(新的)對象而程式設計師可以明確地對字符數組進行修改因此敏感信息(如密碼)不容易在其他地方暴露(只要你用完後對char[]置0)3. 在switch語句中使用String作為case條件?
  • [博客更新]Java 中 final 關鍵詞的使用
    上一篇文章我們講了 java 中 static 關鍵字的使用,這裡再將一下 final 關鍵字的使用。final 在 java 中可以看做一個「終結者」,它可以定義類、定義方法和定義變量。哎呀,好像沒別的可說了,就這樣吧,這可能是我寫過的字數最少的一篇文章了 算了,最後加一個示例程序吧,當然是錯誤的程序,包含了以上三種使用方法的錯誤使用報錯信息:package com.example.finalDemo;/** * User: sunriseydy * 2018-4-25 22:04 */finalclassPerson{String name
  • Java中文語言處理HanLP
    ;import java.util.List;/*** @Author:sks* @Description:* @Date:Created in 16:00 2018/1/19\n" +"算法可以寬泛的分為三類,\n" +"一,有限的確定性算法,這類算法在有限的一段時間內終止。他們可能要花很長時間來執行指定的任務,但仍將在一定的時間內終止。這類算法得出的結果常取決於輸入值。\n" +"二,有限的非確定算法,這類算法在有限的時間內終止。
  • StackOverflow 上面最流行的 7 個 Java 問題!
    為了回答這個問題,你需要使用分支預測(branch prediction)。分支預測是一種架構,旨在通過在真實的路徑發生前猜測某一分支的下一步來提升處理過程。分支在這裡即一個if語句。這樣的話,如果是一個排序數組,那麼分支預測將會進行,否則不會進行。
  • 20張示例照,教你5個「小臉」拍攝秘籍
    其實,想要拍照顯臉小一些,掌握技巧就可以了。不妨一起隨著下面20張示例照,跟大家分享5個「小臉」拍攝秘籍,解決「大餅臉」難題,希望你也能自信面對鏡頭。1、善「尋」角度經常自拍的女生肯定深有體會,選擇恰當的拍攝視角不僅可以增強美感,而且可以起到「小臉」的作用,要做的就是多多嘗試,了解自己。
  • Java 集合框架綜述,這篇讓你吃透!
    2、集合接口:6 個接口(短虛線表示),表示不同集合類型,是集合框架的基礎。3、抽象類:5 個抽象類(長虛線表示),對集合接口的部分實現。可擴展為自定義集合類。4、實現類:8 個實現類(實線表示),對接口的具體實現。5、Collection 接口是一組允許重複的對象。6、Set 接口繼承 Collection,集合元素不重複。