Java 8 日期時間 API

Java 8 日期時間 API

在舊版本的Java中,日期時間API存在諸多問題,其中有:

  • 非線程安全 - java.util.Date 是非線程安全的,所有的日期類都是可變的,這是Java日期類最大的問題之一。
  • 設計很差 - Java的日期/時間類的定義並不一致,在java.util和java.sql的包中都有日期類,此外用於格式化和解析的類在java.text包中定義。java.Date同時包含日期和時間,而java.Date僅包含日期,將其納入java.sql包並不合理,另外這兩個類都有相同的名字,本身就是一個非常糟糕的設計。
  • 時區處理麻煩 - 日期類並不提供國際化,沒有時區支持,因此Java引入了java.util.Calenda和java.util.TimeZone類,單他們同樣存在上述的所有問題。

Java 8 在java.time包下提供了很多新的API。以下爲兩個比較重要的API:

  • Local(本地) - 簡化了日期時間的處理,沒有時區的問題。
  • Zoned(時區) - 通過制定的時區處理日期時間。

新的java.time包涵蓋了所有處理日期,時間,日期/時間,時區,時刻(instants),過程(during),與時鐘(clock)的操作。

1.本地化日期時間 API

LocalDate/LocalTime和LocalDateTime類可以在處理時區不是必須的情況。代碼如下

public class Java8Tester{
    public static void main(String args[]){
        Java8Tester java8Tester = new Java8Tester();
        java8Tester.testLocalDateTime();
    }

    public void testLocalDateTime(){
        //獲取當前日期時間
        LocalDateTime currentTime = LocalDateTime.now();
        System.out.println("當前時間:"+currentTime);
        LocalDate date1 = currentTime.toLocalDate();
        System.out.println("date1: "+date1);
        Month month = currentTime.getMonth();
        int day = currentTime.getDayOfMonth();
        int senconds = currentTime.getSecond();
        System.out.println("月:"+ month + ",日:" + day + ",秒:" + senconds);

        //指定年日 2019/09/10
        LocalDateTime date2  = currentTime.withDayOfMonth(10).withYear(2019);
        System.out.println("date2: "+ date2);

        //指定年月日   2019-11-10
        LocalDate date3 = LocalDate.of(2019,Month.NOVEMBER,10);
        System.out.println("date3: "+ date3);

        //22時15分鐘
        LocalTime date4 = LocalTime.of(22,10);
        System.out.println("date4: "+ date4);

        //解析字符串
        LocalTime date5 = LocalTime.parse("20:15:30");
        System.out.println(date5);
    }
}

執行以上腳本,輸出結果爲:

當前時間: 2018-06-08T15:19:16.910

date1:2018-06-08

月: JUNE, 日: 8, 秒: 16

date2:2012-06-10T15:19:16.910

date3:2014-12-12

date4:22:15

date5:20:15:30

2 使用時區的日期時間API

如果我們需要考慮到時區,就可以使用時區的日期時間API:

public class Java8Tester {
    public static void main(String args[]) {
        Java8Tester java8Tester = new Java8Tester();
        java8Tester.testZonedDateTime();
    }

    public void testZonedDateTime() {
        // 獲取當前時間日期
        ZonedDateTime date1 = ZonedDateTime.parse("2019-12-03T10:15:30+05:30[Asia/Shanghai]");
        System.out.println("date1: " + date1);
        ZoneId id = ZoneId.of("Europe/Paris");
        System.out.println("ZoneId: " + id);
        ZoneId currentZone = ZoneId.systemDefault();
        System.out.println("當期時區: " + currentZone);
    }
}

執行以上腳本,輸出結果爲:

date1:2015-12-03T10:15:30+08:00[Asia/Shanghai]

ZoneId:Europe/Paris

當期時區: Asia/Shanghai

3.常用代碼

LocalDate today = LocalDate.now();
      System.out.println("今天的日期是:"+today);
      System.out.println("-----------------------------");
      int year = today.getYear();
      int month = today.getMonthValue();
      int day = today.getDayOfMonth();
      System.out.println("年:"+year+",月:"+month+",日:"+day);
      System.out.println("-----------------------------");
      LocalDate birthday = LocalDate.of(2011, 11, 11);
      System.out.println("特定日期:"+birthday);
      System.out.println("-----------------------------");
      System.out.println("今天的日期是2011-11-11嗎?"+today.equals(birthday));
      System.out.println("-----------------------------");
      LocalDate dayofbirth = LocalDate.of(2008, 11, 20);
      LocalDate tday = LocalDate.now();
   // 獲取生日的月、日
      MonthDay birthMonthDay = MonthDay.of(dayofbirth.getMonth(), dayofbirth.getDayOfMonth());
      MonthDay currentMonthDay = MonthDay.from(tday);
      if (currentMonthDay.equals(birthMonthDay)) {
          System.out.println("今天是你的生日");
      }else{
          System.out.println("對不起,今天不是你的生日");
      }
      System.out.println("-----------------------------");
      LocalTime localTime = LocalTime.now();
      System.out.println("現在的時間是"+localTime);
      System.out.println("-----------------------------");
      LocalTime twoHourLaterTime = localTime.plusHours(2);
      System.out.println("當前時間兩小時後的時間是"+twoHourLaterTime);
      System.out.println("-----------------------------");
      LocalDate oneWeekLaterDate = today.plus(1,ChronoUnit.WEEKS);
      System.out.println("兩週後的日期是:"+oneWeekLaterDate);
      System.out.println("-----------------------------");
      LocalDate oneYearBeforeDate = today.minus(1, ChronoUnit.YEARS);
      System.out.println("一年前的日期是:"+oneYearBeforeDate);
      LocalDate oneYearLaterDate = today.plus(1, ChronoUnit.YEARS);
      System.out.println("一年後的日期是:"+oneYearLaterDate);
      System.out.println("-----------------------------");
      Clock clock = Clock.systemUTC();
      System.out.println("Clock:"+clock);
      Clock.systemDefaultZone();
      System.out.println("Clock:"+clock.millis());
      System.out.println("-----------------------------");
      LocalDate day1 = LocalDate.of(2011, 12, 15);
      LocalDate day2 = LocalDate.of(2011, 9, 17);
      System.out.println("day1是否在day2之後:"+day1.isAfter(day2));
      System.out.println("day1是否在day2之前:"+day1.isBefore(day2));
      System.out.println("-----------------------------");
      LocalDateTime todaytime = LocalDateTime.now();
      System.out.println("當前的日期時間:"+todaytime);
      ZoneId zone = ZoneId.of(ZoneId.SHORT_IDS.get("ACT"));
      ZonedDateTime dateandtimeinNewYork = ZonedDateTime.of(todaytime, zone);
      System.out.println("現在時區的時間在特定時區的時間:"+dateandtimeinNewYork);
      System.out.println("-----------------------------");
      YearMonth currentYearMonth = YearMonth.now();
      System.out.println("今年的當前月"+currentYearMonth+"有"+currentYearMonth.lengthOfMonth()+"天");
      YearMonth creditCardExpiry = YearMonth.of(2018, Month.FEBRUARY);
      System.out.println("您輸入的年月日期是:"+creditCardExpiry);
      System.out.println("-----------------------------");
      System.out.println("今年"+today+"是否是閏年:"+today.isLeapYear());
      System.out.println("-----------------------------");
      LocalDate day3 = LocalDate.of(2002, 12, 10);
      LocalDate day4 = LocalDate.of(2001, 9, 12);
      Period period = Period.between(day3, day4);
      System.out.println(day3+"和"+day4+"之間相差"+period.getMonths()+"月");
      System.out.println("-----------------------------");
      LocalDateTime datetime = LocalDateTime.of(2016, Month.APRIL, 14, 14, 02, 24);
      ZoneOffset offset = ZoneOffset.of("+05:30");
      OffsetDateTime offsetdatetime = OffsetDateTime.of(datetime, offset);
      System.out.println("日期和時間在時區上的偏移時間:"+offsetdatetime);
      System.out.println("-----------------------------");
      Instant timestamp = Instant.now();
      System.out.println("當前時間戳:"+timestamp);
      System.out.println("-----------------------------");
      String dayaftertommrow = "20160205";
      LocalDate formatdate = LocalDate.parse(dayaftertommrow,DateTimeFormatter.BASIC_ISO_DATE);
      System.out.println(dayaftertommrow+"格式化後的日期是"+formatdate);
      System.out.println("-----------------------------");
      String goodFriday = "04 14 2016";
      DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM dd yyyy");
      LocalDate holiday = LocalDate.parse(goodFriday,dateTimeFormatter);
      System.out.println(goodFriday+"自定義格式化後的日期是"+holiday);
      System.out.println("-----------------------------");
      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM dd yyyy HH:mm a");
      String datestr = todaytime.format(formatter);
      System.out.println("自定義格式化後的當前日期時間是"+datestr);

4.注意點

 

  • Instant 它代表的是時間戳,比如2016-04-14T14:20:13.592Z,這可以從java.time.Clock類中獲取,像這樣: Instant current = Clock.system(ZoneId.of(“Asia/Tokyo”)).instant();

  • LocalDate 它表示的是不帶時間的日期,比如2016-04-14。它可以用來存儲生日,週年紀念日,入職日期等。

  • LocalTime - 它表示的是不帶日期的時間

  • LocalDateTime - 它包含了時間與日期,不過沒有帶時區的偏移量

  • ZonedDateTime - 這是一個帶時區的完整時間,它根據UTC/格林威治時間來進行時區調整

  • 這個庫的主包是java.time,裏面包含了代表日期,時間,瞬時以及持續時間的類。它有兩個子package,一個是java.time.foramt,這個是什麼用途就很明顯了,還有一個是java.time.temporal,它能從更低層面對各個字段進行訪問。

  • 時區指的是地球上共享同一標準時間的地區。每個時區都有一個唯一標識符,同時還有一個地區/城市(Asia/Tokyo)的格式以及從格林威治時間開始的一個偏移時間。比如說,東京的偏移時間就是+09:00。

  • OffsetDateTime類實際上包含了LocalDateTime與ZoneOffset。它用來表示一個包含格林威治時間偏移量(+/-小時:分,比如+06:00或者 -08:00)的完整的日期(年月日)及時間(時分秒,納秒)。

  • DateTimeFormatter類用於在Java中進行日期的格式化與解析。與SimpleDateFormat不同,它是不可變且線程安全的,如果需要的話,可以賦值給一個靜態變量。DateTimeFormatter類提供了許多預定義的格式器,你也可以自定義自己想要的格式。當然了,根據約定,它還有一個parse()方法是用於將字符串轉換成日期的,如果轉換期間出現任何錯誤,它會拋出DateTimeParseException異常。類似的,DateFormatter類也有一個用於格式化日期的format()方法,它出錯的話則會拋出DateTimeException異常。

  • 再說一句,“MMM d yyyy”與“MMm dd yyyy”這兩個日期格式也略有不同,前者能識別出”Jan 2 2014”與”Jan 14 2014”這兩個串,而後者如果傳進來的是”Jan 2 2014”則會報錯,因爲它期望月份處傳進來的是兩個字符。爲了解決這個問題,在天爲個位數的情況下,你得在前面補0,比如”Jan 2 2014”應該改爲”Jan 02 2014”。

 

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