引用自Java譯站http://it.deepinmind.com/java/2015/03/17/20-examples-of-date-and-time-api-from-Java8.html
除了lambda表達式,stream以及幾個小的改進之外,Java 8還引入了一套全新的時間日期API,在本篇教程中我們將通過幾個簡單的任務示例來學習如何使用Java 8的這套API。Java對日期,日歷及時間的處理一直以來都飽受詬病,尤其是它決定將java.util.Date定義為可修改的以及將SimpleDateFormat實現成非線程安全的。看來Java已經意識到需要為時間及日期功能提供更好的支持了,這對已經習慣使用Joda時間日期庫的社區而言也是件好事。關於這個新的時間日期庫的最大的優點就在於它定義清楚了時間日期相關的一些概念,比方說,瞬時時間(Instant),持續時間(duration),日期(date),時間(time),時區(time-zone)以及時間段(Period)。同時它也借鑒了Joda庫的一些優點,比如將人和機器對時間日期的理解區分開的。Java 8仍然延用了ISO的日歷體系,並且與它的前輩們不同,java.time包中的類是不可變且線程安全的。新的時間及日期API位於java.time包中,下面是里面的一些關鍵的類:
- Instant——它代表的是時間戳,可以理解為瞬時時間
- LocalDate——不包含具體時間的日期,比如2014-01-14。它可以用來存儲生日,周年紀念日,入職日期等。
- LocalTime——它代表的是不含日期的時間
- LocalDateTime——它包含了日期及時間,不過還是沒有偏移信息或者說時區。
- ZonedDateTime——這是一個包含時區的完整的日期時間,偏移量是以UTC/格林威治時間為基准的。
新的庫還增加了ZoneOffset及Zoned,可以為時區提供更好的支持。有了新的DateTimeFormatter之后日期的解析及格式化也變得煥然一新了。
示例1 如何 在Java 8中獲取當天的日期
Java 8中有一個叫LocalDate的類,它能用來表示今天的日期。這個類與java.util.Date略有不同,因為它只包含日期,沒有時間。因此,如果你只需要表示日期而不包含時間,就可以使用它。
LocalDate today = LocalDate.now(); System.out.println("Today's Local date : " + today); Today's Local date : 2020-02-11
你可以看到它創建了今天的日期卻不包含時間信息。它還將日期格式化完了再輸出出來,不像之前的Date類那樣,打印出來的數據都是未經格式化的。
示例2 如何在Java 8中獲取當前的年月日
LocalDate類中提供了一些很方便的方法可以用於提取出年月日以及其它的日期屬性。使用這些方法,你可以獲取到任何你所需要的日期屬性,而不再需要使用java.util.Calendar這樣的類了:
LocalDate today = LocalDate.now(); int year = today.getYear(); int month = today.getMonthValue(); int day = today.getDayOfMonth(); System.out.printf("Year : %d Month : %d day : %d \t %n", year, month, day);
Year : 2020 Month : 2 day : 11
可以看到,在Java 8中獲取年月信息非常簡單,只需使用對應的getter方法就好了,無需記憶,非常直觀。
示例3 在Java 8中如何獲取某個特定的日期
在第一個例子中,我們看到通過靜態方法now()來生成當天日期是非常簡單的,不過通過另一個十分有用的工廠方法LocalDate.of(),則可以創建出任意一個日期,它接受年月日的參數,然后返回一個等價的LocalDate實例。關於這個方法還有一個好消息就是它沒有再犯之前API中的錯,比方說,年只能從1900年開始,月必須從0開始,等等。這里的日期你寫什么就是什么,比如說,下面這個例子中它代表的就是1月14日,沒有什么隱藏邏輯。
LocalDate dateOfBirth = LocalDate.of(2010, 01, 14); System.out.println("Your Date of birth is : " + dateOfBirth); Your Date of birth is : 1994-04-01
示例4 在Java 8中如何檢查兩個日期是否相等
如果說起現實中實際的處理時間及日期的任務,有一個常見的就是要檢查兩個日期是否相等。你可能經常會碰到要判斷今天是不是某個特殊的日子,比如生日啊,周年紀念日啊,或者假期之類。有的時候,會給你一個日期,讓你檢查它是不是某個日子比方說假日。下面這個例子將會幫助你在Java 8中完成這類任務。正如你所想的那樣,LocalDate重寫了equals方法來進行日期的比較,如下所示:
LocalDate today = LocalDate.now(); LocalDate date1 = LocalDate.of(2020, 02, 11); if(date1.equals(today)) { System.out.printf("Today %s and date1 %s are same date %n", today, date1);} Today 2020-02-11 and date1 2020-02-11 are same date
在本例中我們比較的兩個日期是相等的。同時,如果在代碼中你拿到了一個格式化好的日期串,你得先將它解析成日期然后才能比較。
示例5 在Java 8中如何檢查重復事件,比如說生日
在Java中還有一個與時間日期相關的實際任務就是檢查重復事件,比如說每月的帳單日,結婚紀念日,每月還款日或者是每年交保險費的日子。如果你在一家電商公司工作的話,那么肯定會有這么一個模塊,會去給用戶發送生日祝福並且在每一個重要的假日給他們捎去問候,比如說聖誕節,感恩節,在印度則可能是萬燈節(Deepawali)。如何在Java中判斷是否是某個節日或者重復事件?使用MonthDay類。這個類由月日組合,不包含年信息,也就是說你可以用它來代表每年重復出現的一些日子。當然也有一些別的組合,比如說YearMonth類。它和新的時間日期庫中的其它類一樣也都是不可變且線程安全的,並且它還是一個值類(value class)。我們通過一個例子來看下如何使用MonthDay來檢查某個重復的日期:
LocalDate dateOfBirth = LocalDate.of(2010, 01, 14); MonthDay birthday = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth()); MonthDay currentMonthDay = MonthDay.from(today); if(currentMonthDay.equals(birthday)){ System.out.println("Many Many happy returns of the day !!"); }else{ System.out.println("Sorry, today is not your birthday"); }
Output: Many Many happy returns of the day !!
示例6 如何在Java 8中獲取當前時間
這與第一個例子中獲取當前日期非常相似。這次我們用的是一個叫LocalTime的類,它是沒有日期的時間,與LocalDate是近親。這里你也可以用靜態工廠方法now()來獲取當前時間。默認的格式是hh:mm:ss:nnn,這里的nnn是納秒。可以和Java 8以前如何獲取當前時間做一下比較。
LocalTime time = LocalTime.now(); System.out.println("local time now : " + time);
local time now : 20:28:20.822
可以看到,當前時間是不包含日期的,因為LocalTime只有時間,沒有日期。
示例7 如何增加時間里面的小時數
很多時候我們需要增加小時,分或者秒來計算出將來的時間。Java 8不僅提供了不可變且線程安全的類,它還提供了一些更方便的方法譬如plusHours()來替換原來的add()方法。順便說一下,這些方法返回的是一個新的LocalTime實例的引用,因為LocalTime是不可變的,可別忘了存儲好這個新的引用。
LocalTime time = LocalTime.now(); LocalTime newTime = time.plusHours(2); // adding two hours System.out.println("Time after 2 hours : " + newTime); Time after 2 hours : 22:31:40.250
示例8 如何獲取1周后的日期
這與前一個獲取2小時后的時間的例子類似,這里我們將學會如何獲取到1周后的日期。LocalDate是用來表示無時間的日期的,它有一個plus()方法可以用來增加日,星期,或者月,ChronoUnit則用來表示這個時間單位。由於LocalDate也是不可變的,因此任何修改操作都會返回一個新的實例,因此別忘了保存起來。
LocalDate today = LocalDate.now(); LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS); System.out.println("Today is : " + today); System.out.println("Date after 1 week : " + nextWeek);
Today is : 2020-02-11
Date after 1 week : 2020-02-18
可以看到7天也就是一周后的日期是什么。你可以用這個方法來增加一個月,一年,一小時,一分鍾,甚至是十年,查看下Java API中的ChronoUnit類來獲取更多選項。
示例9 一年前后的日期
這是上個例子的續集。上例中,我們學習了如何使用LocalDate的plus()方法來給日期增加日,周或者月,現在我們來學習下如何用minus()方法來找出一年前的那天。
LocalDate today = LocalDate.now(); LocalDate previousYear = today.minus(1, ChronoUnit.YEARS); System.out.println("Date before 1 year : " + previousYear); LocalDate nextYear = today.plus(1, ChronoUnit.YEARS); System.out.println("Date after 1 year : " + nextYear); Date before 1 year : 2019-02-11 Date after 1 year : 2021-02-11
可以看到現在一共有兩年,一個前,一個后.
示例10 在Java 8中使用時鍾
Java 8中自帶了一個Clock類,你可以用它來獲取某個時區下當前的瞬時時間,日期或者時間。可以用Clock來替代System.currentTimeInMillis()與 TimeZone.getDefault()方法。
// Returns the current time based on your system clock and set to UTC. Clock clock = Clock.systemUTC();//獲取系統所在時區下的clock
System.out.println("Clock : " + clock);
//如何獲取其他時區下的clock public static Clock system(ZoneId zone)
/*你可以用指定的日期來和這個時鍾進行比較,比如下面這樣:*/
LocalDate birthDate = LocalDate.of(1994,04,01);
System.out.println(birthDate.isBefore(LocalDate.now(clock)));
如果你需要對不同時區的日期進行處理的話這是相當方便的。
