JDK8——日期相關API

背景

JDK8中增加了一套全新的日期時間API,這裏進行總結下,方便查詢使用:

作用 備註
Instant 表示時間戳 對應jdk7之前的Date,可通過Epoch Time 紀元時相互轉換
LocalDateTime 獲取當前系統的日期時間(內部不記錄時區) 可以認爲由LocalDate和LocalTime組成
LocalDate 獲取當前系統的日期 年月日,對應java.sql.date
LocalTime 獲取當前系統的時間 時分秒,對應java.sql.time
ZoneId 時區,"+01:00"和"Europe/Paris" ZoneId除了處理與標準時間的時間差還處理地區時(夏令時,冬令時等)
ZoneOffset 時區,只處理 "+01:00" ZoneOffset是ZoneId的子類,只處理與格林尼治的時間差
ZoneDateTime 特定時區的日期和時間

LocalDateTime內部不記錄時區,ZoneDateTime記錄

DateTimeFormatter 格式化日期 替換SimpleDateFormat,線程安全
Period 計算年月日格式的時間差異 只能精確到年月日
Duration 計算時間戳的時間差異 可用於LocalDateTime、Instant類
ChronoUnit 標準的日期單位 可用於日期計算時指定日期單位

獲取日期時間的信息

LocalDate

LocalDate類獲取日期信息。格式爲 2018-09-06

        LocalDate nowDate = LocalDate.now();
        System.out.println("今天的日期:" + nowDate);//今天的日期:2018-09-06
        int year = nowDate.getYear();//年:一般用這個方法獲取年
        System.out.println("year:" + year);//year:2018
        int month = nowDate.getMonthValue();//月:一般用這個方法獲取月
        System.out.println("month:" + month);//month:9
        int day = nowDate.getDayOfMonth();//日:當月的第幾天,一般用這個方法獲取日
        System.out.println("day:" + day);//day:6
        
        int dayOfYear = nowDate.getDayOfYear();//日:當年的第幾天
        System.out.println("dayOfYear:" + dayOfYear);//dayOfYear:249
        
        //星期
        System.out.println(nowDate.getDayOfWeek());//THURSDAY
        System.out.println(nowDate.getDayOfWeek().getValue());//4
        //月份
        System.out.println(nowDate.getMonth());//SEPTEMBER
        System.out.println(nowDate.getMonth().getValue());//9

LocalTime

LocalTime類獲取時間信息。格式爲 15:33:56.749

        LocalTime nowTime = LocalTime.now();
        System.out.println("今天的時間:" + nowTime);//今天的時間:15:33:56.749
        int hour = nowTime.getHour();//時
        System.out.println("hour:" + hour);//hour:15
        int minute = nowTime.getMinute();//分
        System.out.println("minute:" + minute);//minute:33
        int second = nowTime.getSecond();//秒
        System.out.println("second:" + second);//second:56
        int nano = nowTime.getNano();//納秒
        System.out.println("nano:" + nano);//nano:749000000

LocalDateTime

LocalDateTime類獲取日期時間信息。格式爲 2018-09-06T15:33:56.750

        LocalDateTime nowDateTime = LocalDateTime.now();
        System.out.println("今天是:" + nowDateTime);//今天是:2018-09-06T15:33:56.750
        System.out.println(nowDateTime.getYear());//年
        System.out.println(nowDateTime.getMonthValue());//月
        System.out.println(nowDateTime.getDayOfMonth());//日
        System.out.println(nowDateTime.getHour());//時
        System.out.println(nowDateTime.getMinute());//分
        System.out.println(nowDateTime.getSecond());//秒
        System.out.println(nowDateTime.getNano());//納秒
        //日:當年的第幾天
        System.out.println("dayOfYear:" + nowDateTime.getDayOfYear());//dayOfYear:249
        //星期
        System.out.println(nowDateTime.getDayOfWeek());//THURSDAY
        System.out.println(nowDateTime.getDayOfWeek().getValue());//4
        //月份
        System.out.println(nowDateTime.getMonth());//SEPTEMBER
        System.out.println(nowDateTime.getMonth().getValue());//9

獲取指定的時間日期

LocalDate

        System.out.println(LocalDate.of(1991, 11, 11));//直接傳入對應的年月日
        System.out.println(LocalDate.of(1991, Month.NOVEMBER, 11));//相對上面只是把月換成了枚舉
        LocalDate birDay = LocalDate.of(1991, 11, 11);
        System.out.println(LocalDate.ofYearDay(1991, birDay.getDayOfYear()));//第一個參數爲年,第二個參數爲當年的第多少天
        System.out.println(LocalDate.ofEpochDay(birDay.toEpochDay()));//參數爲距離1970-01-01的天數
        
        System.out.println(LocalDate.parse("1991-11-11"));
        System.out.println(LocalDate.parse("19911111",DateTimeFormatter.ofPattern("yyyyMMdd")));

LocalTime

        System.out.println(LocalTime.of(8, 20));//時分
        System.out.println(LocalTime.of(8, 20, 30));//時分秒
        System.out.println(LocalTime.of(8, 20, 30, 150));//時分秒納秒
        LocalTime mTime = LocalTime.of(8, 20, 30, 150);
        System.out.println(LocalTime.ofSecondOfDay(mTime.toSecondOfDay()));//參數爲距離當天零時的秒數
        System.out.println(LocalTime.ofNanoOfDay(mTime.toNanoOfDay()));//參數爲距離當天零時的納秒數
        
        System.out.println(LocalTime.parse("08:20:30"));
        System.out.println(LocalTime.parse("082030", DateTimeFormatter.ofPattern("HHmmss")));

LocalDateTime

這裏的 birDay 和 mTime 複用上面的變量。

        System.out.println(LocalDateTime.of(birDay, mTime));//參數爲LocalDate和LocalTime
        System.out.println(LocalDateTime.of(1991, 11, 11, 8, 20));
        System.out.println(LocalDateTime.of(1991, Month.NOVEMBER, 11, 8, 20));
        System.out.println(LocalDateTime.of(1991, 11, 11, 8, 20, 30));
        System.out.println(LocalDateTime.of(1991, Month.NOVEMBER, 11, 8, 20, 30));
        System.out.println(LocalDateTime.of(1991, 11, 11, 8, 20, 30, 150));
        System.out.println(LocalDateTime.of(1991, Month.NOVEMBER, 11, 8, 20, 30, 150));
        
        System.out.println(LocalDateTime.parse("1991-11-11T08:20:30"));
        System.out.println(LocalDateTime.parse("1991-11-11 08:20:30", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

日期時間的比較

在JDK8中,LocalDate類中使用isBefore()、isAfter()、equals()方法來比較兩個日期,可直接進行比較。

以LocalDate爲例。

         LocalDate myDate = LocalDate.of(2018, 9, 5);
         LocalDate nowDate = LocalDate.now();
         System.out.println("今天是2018-09-06嗎? " + nowDate.equals(myDate));//今天是2018-09-06嗎? false
         System.out.println(myDate + "是否在" + nowDate + "之前? " + myDate.isBefore(nowDate));//2018-09-05是否在2018-09-06之前? true
         System.out.println(myDate + "是否在" + nowDate + "之後? " + myDate.isAfter(nowDate));//2018-09-05是否在2018-09-06之後? false

如何在java中判斷是否是某個節日或者重複事件,使用MonthDay類。這個類由月日組合,不包含年信息,可以用來代表每年重複出現的一些日期。它和新的日期庫中的其他類一樣也都是不可變且線程安全的。

         LocalDate birDate = LocalDate.of(1991, 10, 1);
         LocalDate nowDate = LocalDate.now();
         MonthDay nowDay = MonthDay.of(birDate.getMonthValue(), birDate.getDayOfMonth());
         //MonthDay monthDay = MonthDay.of(birDate.getMonth(), birDate.getDayOfMonth());
         MonthDay birDay = MonthDay.from(nowDate);
         System.out.println("今天是你的生日嗎? " + nowDay.equals(birDay));//今天是你的生日嗎? false

 YearMonth表示固定的日期。Year表示年。

         YearMonth yearMonth = YearMonth.of(2004, 2);
         System.out.println(yearMonth + "有多少天? " + yearMonth.lengthOfMonth());//2004-02有多少天? 29
         Year year = Year.of(2004);
         System.out.println(year + "有多少天? " + year.length());//2004有多少天? 366
         System.out.println(year + "是否是閏年? " + year.isLeap());//2004是否是閏年? true

新版本的日期時間API中的這幾個類中好多方法都是一樣的作用,使用時可靈活選擇。

對日期時間的修改

LocalDateTime 綜合了 LocalDate 和 LocalTime 裏面的方法,所以下面只用 LocalDate 和 LocalTime 來舉例。

這些方法返回的是一個新的實例引用,因爲LocalDateTime 、LocalDate 、LocalTime 都是不可變的。

        LocalDate nowDate = LocalDate.now();
        System.out.println(nowDate);//當前日期
        System.out.println(nowDate.minusYears(1));//一年前
        System.out.println(nowDate.minusMonths(1));//一月前
        System.out.println(nowDate.minusWeeks(1));//一週前
        System.out.println(nowDate.minusDays(1));//一天前
        
        System.out.println(nowDate.plusYears(1));//一年後
        System.out.println(nowDate.plusMonths(1));//一月後
        System.out.println(nowDate.plusWeeks(1));//一週後
        System.out.println(nowDate.plusDays(1));//一天後

        LocalTime nowTime = LocalTime.now();
        System.out.println(nowTime);//當前時間
        System.out.println(nowTime.minusHours(1));//一小時前
        System.out.println(nowTime.minusMinutes(1));//一分鐘前
        System.out.println(nowTime.minusSeconds(1));//一秒前
        System.out.println(nowTime.minusNanos(1));//一納秒前
        
        System.out.println(nowTime.plusHours(1));//一小時後
        System.out.println(nowTime.plusMinutes(1));//一分鐘後
        System.out.println(nowTime.plusSeconds(1));//一秒後
        System.out.println(nowTime.plusNanos(1));//一納秒後

還可以直接使用 minus 和 plus 方法來增加和減少日期時間。LocalDateTime 、LocalDate 、LocalTime 都是類似的。

         System.out.println(nowDate.minus(1, ChronoUnit.YEARS));
         System.out.println(nowDate.plus(1, ChronoUnit.YEARS));

ChronoUnit 用來表示時間單位, ChronoUnit 後面只需要替換成相應的年、月、周、日、時、分、秒、納秒,就能減少或增加相應的單位。

時間戳

JDK8獲取時間戳特別簡單。Instant類由一個靜態的工廠方法now()可以返回當前時間戳。

         Instant instant = Instant.now();
         System.out.println("當前時間戳是:" + instant);//當前時間戳是:2018-09-06T10:14:29.460Z
         Date date = Date.from(instant);
         System.out.println("當前時間戳是:" + date);//當前時間戳是:Thu Sep 06 18:14:29 CST 2018
         instant = date.toInstant();

可以看到,當前時間戳是包含日期和時間的,與java.util.Date很類似,事實上Instant就是JDK8以前的Date,可以使用這兩個類中的方法在這兩個類型之間進行轉換。

日期時間格式化

在JDK8之前,時間日期的格式化非常麻煩,經常使用SimpleDateFormat來進行格式化,但是SimpleDateFormat並不是線程安全的。在JDK8中,引入了一個全新的線程安全的日期與時間格式器DateTimeFormatter。

        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);//2018-09-06T18:22:47.366
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String ldtStr = ldt.format(dtf);
        System.out.println(ldtStr);//2018-09-06 18:22:47
        String ldtStr1 = dtf.format(ldt);
        System.out.println(ldtStr1);//2018-09-06 18:22:47

正反都能調用format方法。

計算日期時間差

在Java8中,我們可以使用以下類來計算日期時間差異:

java.time.Period

主要是 Period 類方法 getYears(),getMonths() 和 getDays() 來計算。只能精確到年月日。

用於 LocalDate 之間的比較。

        LocalDate today = LocalDate.now();
        System.out.println(today);//2018-09-06
        LocalDate birthDate = LocalDate.of(1992, 1, 11);
        System.out.println(birthDate);//1990-10-01
        
        Period period = Period.between(birthDate, today);//第二個參數減第一個參數
        System.out.printf("年齡 : %d 年 %d 月 %d 日", period.getYears(), period.getMonths(), period.getDays());//年齡 : 27 年 11 月 5 日

java.time.Duration

提供了使用基於時間的值測量時間量的方法。

用於 LocalDateTime 之間的比較。也可用於 Instant 之間的比較。

        LocalDateTime today = LocalDateTime.now();
        System.out.println(today);
        LocalDateTime birthDate = LocalDateTime.of(1990,10,1,10,50,30);
        System.out.println(birthDate);
        
        Duration duration = Duration.between(birthDate, today);//第二個參數減第一個參數
        System.out.println(duration.toDays());//兩個時間差的天數
        System.out.println(duration.toHours());//兩個時間差的小時數
        System.out.println(duration.toMinutes());//兩個時間差的分鐘數
        System.out.println(duration.toMillis());//兩個時間差的毫秒數
        System.out.println(duration.toNanos());//兩個時間差的納秒數

java.time.temporal.ChronoUnit

ChronoUnit類可用於在單個時間單位內測量一段時間,這個工具類是最全的了,可以用於比較所有的時間單位。

        LocalDateTime today = LocalDateTime.now();
        System.out.println(today);
        LocalDateTime birthDate = LocalDateTime.of(1990,10,1,10,50,30);
        System.out.println(birthDate);
        
        System.out.println("相差的年數:" + ChronoUnit.YEARS.between(birthDate, today));
        System.out.println("相差的月數:" + ChronoUnit.MONTHS.between(birthDate, today));
        System.out.println("相差的週數:" + ChronoUnit.WEEKS.between(birthDate, today));
        System.out.println("相差的天數:" + ChronoUnit.DAYS.between(birthDate, today));
        System.out.println("相差的時數:" + ChronoUnit.HOURS.between(birthDate, today));
        System.out.println("相差的分數:" + ChronoUnit.MINUTES.between(birthDate, today));
        System.out.println("相差的秒數:" + ChronoUnit.SECONDS.between(birthDate, today));
        System.out.println("相差的毫秒數:" + ChronoUnit.MILLIS.between(birthDate, today));
        System.out.println("相差的微秒數:" + ChronoUnit.MICROS.between(birthDate, today));
        System.out.println("相差的納秒數:" + ChronoUnit.NANOS.between(birthDate, today));
        
        System.out.println("相差的半天數:" + ChronoUnit.HALF_DAYS.between(birthDate, today));
        System.out.println("相差的十年數:" + ChronoUnit.DECADES.between(birthDate, today));
        System.out.println("相差的世紀(百年)數:" + ChronoUnit.CENTURIES.between(birthDate, today));
        System.out.println("相差的千年數:" + ChronoUnit.MILLENNIA.between(birthDate, today));
        System.out.println("相差的紀元數:" + ChronoUnit.ERAS.between(birthDate, today));

ZoneId/ZoneOffSet

ZoneId/ZoneOffSet的區別。
ZoneOffSet只處理與標準時的時區差,ZoneId除了處理與標準時的時間差,還處理地區時(夏令時,冬令時等時間調整)

        (ZoneOffset) ZoneId.of("+01:00")
        //ZoneOffset只處理("+01:00")類型的時區問題,所以下面的代碼會拋出異常
        (ZoneOffset) ZoneId.of("Europe/Paris")

ZonedDateTime

與LocalDateTime的區別是,ZonedDateTime內部記錄了時區,而LocalDateTime沒有。
因此LocalDateTime轉Instant需要指定ZoneOffSet而ZoneDateTime不需要。

        LocalDateTime.now().toInstant(ZoneOffset.of("+01:00"));
        ZonedDateTime.now().toInstant();

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章