Java 8 Date-Time API 详解
從Java版本1.0開始就支持日期和時間,主要通過java.util.Date類。 但是,Date類設計不佳。 例如,Date中的月份從1開始,但從日期卻從0開始。在JDK 1.1中使用它的許多方法已經廢棄,同時java.util.Calendar被引入來接管Date中的一些功能。 這兩個是處理日期和時間的主要類,直到JDK 1.7,盡管他們被認為是不足夠并且不容易處理,導致許多人訴諸第三方替代品,例如Joda Time(http://[joda.org](http://joda.org))。 JDK 1.8中的新日期和時間API解決了舊API中的許多問題,并且與Joda Time API類似。
這里介紹JDK 1.8中的日期 - 時間的API。
?Overview
新的日期和時間API使得使用日期和時間非常容易。java.time包中包含API中的核心類。 另外,還有其他四個包,其成員使用較少:java.time.chrono,java.time.format,java.time.temporal和java.time.zone。
在java.time包中,Instant類表示時間線上的一個點,通常用于對時間進行操作。 LocalDate類為沒有時間和時區部分的日期建模,例如,用于表示生日。
如果你需要日期和時間,那么LocalDateTime就是為你準備的。 例如,訂單發貨日期可能需要一個日期以外的時間來使訂單更容易跟蹤。 如果你需要一段時間但不關心日期,那么可以使用LocalTime。
如果時區很重要,日期和時間API提供ZonedDateTime類。 顧名思義,這個類表示帶有時區日期時間。 例如,你可以使用此類來計算位于不同時區的兩個機場之間的飛行時間。
然后有兩個類來測量時間總計,即Duration類和Period類。 這兩個類是相似的,除了Duration是基于時間,但而Period是基于日期的。 Duration提供了納秒精度的時間量。 例如,可以模擬飛行時間,因為它通常以小時數和分鐘數表示。 另一方面,如果只關心天數,月數或年數,例如計算一個人的年齡,則Period更為適用。
java.time包也帶有兩個枚舉DayOfWeek和Month。 DayOfWeek表示從一周的一天,從周一開始到周日。 Month枚舉代表這一年的十二個月,從1月到12月。
處理日期和時間通常涉及解析和格式。 日期和時間API通過在所有主要類中提供parse和format方法來解決這兩個問題。 另外,java.time.format包含一個用于格式化日期和時間的DateTimeFormatter類。
?Instant類
Instant實例表示時間線上的一個點。 參考點是標準的Java紀元(epoch),即1970-01-01T00:00:00Z(1970年1月1日00:00 GMT)。 Instant類的EPOCH屬性返回表示Java紀元的Instant`實例。 在紀元之后的時間是正值,而在此之前的時間即是負值。
Instant的靜態now方法返回一個表示當前時間的Instant對象:
Instant now = Instant.now();getEpochSecond方法返回自紀元以來經過的秒數。 getNano方法返回自上一秒開始以來的納秒數。
Instant類的一個常用用途是用來操作時間,如以下代碼所示。
import java.time.Duration;import java.time.Instant;public class InstantDemo1 {public static void main(String[] args) {Instant start = Instant.now();// do something hereInstant end = Instant.now();System.out.println(Duration.between(start, end).toMillis());}}如上面代碼所示,Duration類用于返回兩個Instant之間時間數量的差異。
LocalDate類
LocalDate類只包括日期沒有時間的部分。 它也沒有時區。 下表顯示了LocalDate中一些重要的方法。
| now | 靜態方法,返回今天的日期 |
| of | ?從指定年份,月份和日期創建LocalDate的靜態方法 |
| ?getDayOfMonth, getMonthValue, getYear | ?以int形式返回此LocalDate的日,月或年 |
| getMonth | ?以Month枚舉常量返回此LocalDate的月份 |
| ?plusDays, minusDays | ?給LocalDate添加或減去指定的天數 |
| plusWeeks, minusWeeks | ?給LocalDate添加或減去指定的星期數 |
| plusMonths, minusMonths | ?給LocalDate添加或減去指定的月份數 |
| ?plusYears, minusYears | ?給LocalDate添加或減去指定的年數 |
| ?isLeapYear | ?檢查LocalDate指定的年份是否為閏年 |
| ?isAfter, isBefore | ?檢查此LocalDate是在給定日期之后還是之前 |
| ?lengthOfMonth | ?返回此LocalDate中月份的天數 |
| ?withDayOfMonth | ?返回此LocalDate的拷貝,將月份中的某天設置為給定值 |
| ?withMonth | ?返回此LocalDate的拷貝,其月份設置為給定值 |
| ?withYear | ?返回此LocalDate的拷貝,并將年份設置為給定值 |
LocalDate提供了各種創建日期的方法。 例如,要創建代表今天日期的LocalDate,使用靜態now方法。
LocalDate today = LocalDate.now();要創建代表特定年,月和日的LocalDate,使用of方法,該方法也是靜態的。 例如,以下代碼創建了一個代表2018年3月7日的LocalDate實例。
LocalDate date = LocalDate.of(2018, 3, 7);還有一個接受java.time.Month枚舉的常量作為第二個參數的of方法。 例如,下面是使用第二種方法重載構造相同日期的代碼。
LocalDate date = LocalDate.of(2018, Month.MARCH, 7);還有獲取LocalDate的日,月或年的方法,例如getDayOfMonth,getMonth,getMonthValue和getYear。 他們都沒有任何參數,并返回一個int或Month的枚舉常量。 另外,還有一個get方法,它接受一個TemporalField并返回這個LocalDate的一部分。 例如,傳遞ChronoField.YEAR以獲取LocalDate的年份部分。
int year = localDate.get(ChronoField.YEAR);ChronoField是一個實現TemporalField接口的枚舉,因此可以傳遞一個ChronoField常量來獲取。 TemporalField和ChronoField都是java.time.temporal包的一部分。 但是,并非ChronoField中的所有常量都可以get獲取,因為并非所有常量都受支持。 例如,傳遞ChronoField.SECOND_OF_DAY以引發異常。 因此,取而代之,最好使用getMonth,getYear或類似方法來獲取LocalDate的組件。
此外,還有拷貝LocalDate的方法,例如plusDays,plusYears,minusMonths等等。 例如,要獲取表示明天的LocalDate,可以創建一個代表今天的LocalDate,然后調用其plusDays方法。
LocalDate tomorrow = LocalDate.now().plusDays(1);要獲取昨天表示的LocalDate,可以使用minusDays方法。
LocalDate yesterday = LocalDate.now().minusDays(1);另外,還有plus和minus方法以更通用的方式獲得LocalDate的拷貝。 兩者都接受一個int參數和一個TemporalUnit參數。 這些方法的簽名如下。
public LocalDate plus(long amountToAdd,java.time.temporal.TemporalUnit unit)public LocalDate minus(long amountToSubtract,java.time.temporal.TemporalUnit unit)例如,獲得一個從今天開始前20年的LocalDate,可以使用這段代碼。
LocalDate pastDate = LocalDate.now().minus(2, ChronoUnit.DECADES);ChronoUnit是一個實現TemporalUnit的枚舉,因此可以將ChronoUnit常量傳遞給plus和minus方法。
LocalDate是不可變的,因此無法更改。 任何返回LocalDate的方法都返回LocalDate的新實例。
以下是使用LocalDate的例子。
import java.time.LocalDate; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit;public class LocalDateDemo1 {public static void main(String[] args) {LocalDate today = LocalDate.now();LocalDate tomorrow = today.plusDays(1);LocalDate oneDecadeAgo = today.minus(1, ChronoUnit.DECADES);System.out.println("Day of month: " + today.getDayOfMonth());System.out.println("Today is " + today);System.out.println("Tomorrow is " + tomorrow);System.out.println("A decade ago was " + oneDecadeAgo);System.out.println("Year : " + today.get(ChronoField.YEAR));System.out.println("Day of year:" + today.getDayOfYear());} }?Period類
Period類基于日期的時間數量構建,例如五天,一周或三年。 下面列出了一些重要的方法。
| ?between | ?在兩個LocalDates之間創建一個Period示例 |
| ?ofDays, ofWeeks, ofMonths, ofYears | ?創建代表給定天數/周/月/年的Period實例 |
| ?of | ?根據給定的年數,月數和天數創建一個Period實例 |
| ?getDays, getMonths, getYears | ?以int形式返回此Period的天數/月/年 |
| isNegative | ?如果此Period的三個部分中的任何一個為負數,則返回true。 否則返回false |
| ?isZero | ?如果此Period的所有三個部分均為零,則返回true。 否則,返回false |
| plusDays, minusDays | ?在此Period上添加或減去給定的天數 |
| ?plusMonths, minusMonths | ?在此Period上增加或減去給定的月數 |
| ?plusYears, minusYears | ?在此Period增加或減去給定的年數 |
| ?withDays | ?以指定的天數返回此Period的拷貝 |
| ?withMonths | ?以指定的月數返回此Period的拷貝 |
| ?withYears | ?以指定的年數返回此Period的拷貝 |
創建一個Period很簡單,這要感謝between,of,ofDays / ofWeeks / ofMonths / ofYears等靜態工廠方法。 例如,以下是如何創建代表兩周的Period實例。
Period twoWeeks = Period.ofWeeks(2);要創建代表一年兩個月三天的Period實例,請使用of方法。
Period p = Period.of(1, 2, 3);要獲取某個期間的年/月/日組件,調用其getYears / getMonths / getDays方法。 例如,以下代碼中的howManyDays變量的值是14。
Period twoWeeks = Period.ofWeeks(2);int howManyDays = twoWeeks.getDays();最后,可以使用plusXXX或minusXXX方法以及withXXX方法來創建Period的拷貝。 Period是不可變的,所以這些方法返回新的Period實例。
例如,下面的代碼顯示了一個計算個人年齡的年齡計算器。 它從兩個LocalDate創建一個Period并調用它的getDays,getMonths和getYears方法。
import java.time.LocalDate; import java.time.Period;public class PeriodDemo1 {public static void main(String[] args) {LocalDate dateA = LocalDate.of(1978, 8, 26);LocalDate dateB = LocalDate.of(1988, 9, 28);Period period = Period.between(dateA, dateB);System.out.printf("Between %s and %s"+ " there are %d years, %d months"+ " and %d days%n", dateA, dateB,period.getYears(),period.getMonths(),period.getDays());} }運行PeriodDemo1類打印下面字符串。
Between 1978-08-26 and 1988-09-28 there are 10 years, 1 months and 2 days?LocalDateTime類
LocalDateTime類是一個沒有時區的日期時間的構建。 下表顯示了LocalDateTime中一些重要的方法。 這些方法類似于LocalDate的方法,以及用于修改時間部分的一些其他方法,例如在LocalDate中不可用的plusHours,plusMinutes和plusSeconds。
| now | ?返回當前日期和時間的靜態方法。 |
| of | ?從指定年份,月份,日期,小時,分鐘,秒和毫秒創建LocalDateTime的靜態方法。 |
| ?getYear, getMonthValue, getDayOfMonth, getHour, getMinute, getSecond | ?以int形式返回此LocalDateTime的年,月,日,小時,分鐘或秒部分。 |
| ?plusDays, minusDays | ?給當前LocalDateTime添加或減去指定的天數。 |
| ?plusWeeks, minusWeeks | ?給當前LocalDateTime添加或減去指定的周數。 |
| ?plusMonths, minusMonths | ?給當前LocalDateTime添加或減去指定的月數。 |
| plusYears, minusYears | ?給當前LocalDateTime添加或減去指定的年數。 |
| ?plusHours, minusHours | ?給當前LocalDateTime添加或減去指定的小時數 |
| ?plusMinutes, minusMinutes | ?給當前LocalDateTime添加或減去指定的分鐘數 |
| ?plusSeconds, minusSeconds | ?給當前LocalDateTime添加或減去指定的秒數 |
| ?IsAfter, isBefore | ?檢查此LocalDateTime是否在指定的日期時間之后或之前 |
| ?withDayOfMonth | ?返回此LocalDateTime的拷貝,并將月份中的某天設置為指定值 |
| ?withMonth, withYear | ?返回此LocalDateTime的拷貝,其月或年設置為指定值 |
| ?withHour, withMinute, withSecond | ?返回此LocalDateTime的拷貝,其小時/分鐘/秒設置為指定值 |
LocalDateTime提供了各種靜態方法來創建日期時間。 該方法現在帶有三個重載方法返回當前的日期時間。 無參的方法是最容易使用的:
LocalDateTime now = LocalDateTime.now();要創建具有特定日期和時間的LocalDateTime,請使用of方法。 此方法有多個重載,并允許傳遞日期時間或LocalDate和LocalTime的單個部分。 以下是一些方法的簽名。
public static LocalDateTime of(int year, int month, int dayOfMonth,int hour, int minute)public static LocalDateTime of(int year, int month, int dayOfMonth,int hour, int minute)public static LocalDateTime of(int year, Month month,int dayOfMonth, int hour, int minute)public static LocalDateTime of(int year, Month month,int dayOfMonth, int hour, int minute)public static LocalDateTime of(LocalDate date, LocalTime time)例如,下面的代碼段創建一個LocalDateTime,代表2015年12月31日早上八點。
LocalDateTime endOfYear = LocalDateTime.of(2015, 12, 31, 8, 0);可以使用plusXXX或minusXXX方法創建LocalDateTime的拷貝。 例如,此代碼創建一個LocalDateTime,它表示明天的同一時間。
LocalDateTime now = LocalDateTime.now();LocalDateTime sameTimeTomorrow = now.plusHours(24);Time Zones
互聯網數字分配機構(IANA)維護一個可從此網頁下載的時區數據庫:
[http://www.iana.org/time-zones](http://www.iana.org/time-zones)但為了便于查看,可以訪問此Wikipedia頁面:
http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
Java日期和時間API也適用于時區。 抽象類ZoneId(在java.time包中)表示一個區域標識符。 它有一個名為getAvailableZoneIds的靜態方法,它返回所有區域標識符。 下面展示了如何使用這種方法打印所有時區的排序列表。
import java.time.ZoneId; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set;public class TimeZoneDemo1 {public static void main(String[] args) {Set<String> allZoneIds = ZoneId.getAvailableZoneIds();List<String> zoneList = new ArrayList<>(allZoneIds);Collections.sort(zoneList);??????for (String zoneId : zoneList) {System.out.println(zoneId);}// alternatively, you can use this line of code to// print a sorted list of zone ids// ZoneId.getAvailableZoneIds().stream().sorted().//??????? forEach(System.out::println);} }getAvailableZoneIds返回字符串的Set集合。 可以使用Collections.sort()或更優雅地通過調用它的stream方法對Set進行排序。 可以編寫此代碼對區域標識符進行排序。
ZoneId.getAvailableZoneIds().stream().sorted().forEach(System.out::println);getAvailableZoneIds返回586個區域標識符的Set集合。 以下是上述代碼中的一部分區域標識符。
Africa/Cairo Africa/Johannesburg America/Chicago America/Los_Angeles America/Mexico_City America/New_York America/Toronto Antarctica/South_Pole Asia/Hong_Kong Asia/Shanghai Asia/Tokyo Australia/Melbourne Australia/Sydney Canada/Atlantic Europe/Amsterdam Europe/London Europe/Paris US/Central US/Eastern US/PacificZonedDateTime
ZonedDateTime類以一個時區為日期時間的構建。例如,以下是一個時區的日期時間:
2015-12-31T10:59:59+01:00 Europe/ParisZonedDateTime始終是不可變的,時間分量的存儲精度為納秒。
ZonedDateTIme中一些重要方法的使用與LocalDateTime類似,只是多了一個時區的概念。可自行查閱API。
像LocalDateTime一樣,ZonedDateTime類現在提供靜態now和of方法,并構造一個ZonedDateTime實例。 now方法創建一個ZonedDateTime代表執行的日期和時間。 無參now方法會使用計算機的默認時區創建ZonedDateTime。
ZonedDateTime now = ZonedDateTime.now();now的另一個重載方法允許傳遞區域標識符:
ZonedDateTime parisTime =ZonedDateTime.now(ZoneId.of("Europe/Paris"));of方法也有好幾個重載的方法。在所有情況下,都需要傳遞區域標識符。 第一個重載方法允許傳遞時區日期時間的每個部分,從年份到納秒。
public static ZonedDateTime of(int year, int month, int dayOfMonth,int hour, int minute, int second, int nanosecond,ZoneId zone)of方法的第二個重載方法需要LocalDate,LocalTime和ZoneId參數:
public static ZonedDateTime of(LocalDate date, LocalTime time,ZoneId zone)of方法的最后一個重載方法需要LocalDateTime和ZoneId參數。
public static ZonedDateTime of(LocalDateTime datetime, ZoneId zone)像LocalDate和LocalDateTime一樣,ZonedDateTime提供了使用plusXXX,minusXXX和withXXX方法創建實例拷貝的方法。
例如,下面代碼行創建一個帶默認時區的ZonedDateTime,并調用它的minusDays方法以在三天前創建相同的ZonedDateTime。
ZonedDateTime now = ZonedDateTime.now(); ZonedDateTime threeDaysEarlier = now.minusDays(3);?Duration
Duration類是基于時間的持續時間的構建。 它與Period類似,不同之處在于Duration的時間分量為納秒精度,并考慮了ZonedDateTime實例之間的時區。 下表顯示了Duration中重要的方法。
| between | ?在兩個時差的對象之間創建一個Duration實例,例如在兩個LocalDateTime或兩個ZonedDateTime之間。 |
| ?ofYears, ofMonths, ofWeeks, ofDays, ofHours, ofMinutes, ofSeconds, ofNano | ?創建給定年數/月/周/天/小時/分鐘/秒/納秒的Duration實例 |
| ?of | ?根據指定數量的時間單位創建Duration實例 |
| ?toDays, toHours, toMinutes | ?以int形式返回此Duration的天數/小時/分鐘數 |
| ?isNegative | ?如果此Duration為負,則返回true。 否則返回false。 |
| ?isZero | ?如果此Duration長度為零,則返回true。 否則,返回false |
| ?plusDays, minusDays | ?在此Duration內添加或減去指定的天數。 |
| ?plusMonths, minusMonths | ?在此Duration內添加或減去指定的月數。 |
| ?plusYears, minusYears | ?在Duration內添加或減去指定的年數 |
| ?withSeconds | ?以指定的秒數返回此Duration的拷貝。 |
可以通過調用靜態方法between或of來創建Duration。 下面的代碼會在2015年1月26日11:10至2015年1月26日12:40之間創建兩個LocalDateTime的Duration。
import java.time.Duration; import java.time.LocalDateTime;public class DurationDemo1 {public static void main(String[] args) {LocalDateTime dateTimeA = LocalDateTime.of(2015, 1, 26, 8, 10, 0, 0);LocalDateTime dateTimeB = LocalDateTime.of(2015, 1, 26, 11, 40, 0, 0);Duration duration = Duration.between(dateTimeA, dateTimeB);System.out.printf("There are %d hours and %d minutes.%n",duration.toHours(),duration.toMinutes() % 60);} }運行DurationDemo1類的結果是這樣的。
There are 3 hours and 30 minutes.下面的代碼在兩個ZoneDateTime之間創建一個Duration,具有相同的日期和時間,但時區不同。
import java.time.Duration; import java.time.LocalDateTime; import java.time.Month; import java.time.ZoneId; import java.time.ZonedDateTime;public class DurationDemo2 {public static void main(String[] args) {ZonedDateTime zdt1 = ZonedDateTime.of(LocalDateTime.of(2015, Month.JANUARY, 1,8, 0),ZoneId.of("America/Denver"));ZonedDateTime zdt2 = ZonedDateTime.of(LocalDateTime.of(2015, Month.JANUARY, 1,8, 0),ZoneId.of("America/Toronto"));Duration duration = Duration.between(zdt1, zdt2);System.out.printf("There are %d hours and %d minutes.%n",duration.toHours(),duration.toMinutes() % 60);} }運行DurationDemo2類在控制臺上打印如下結果。
There are -2 hours and 0 minutes.這是預料之中的,因為時區America/Denver和America/Toronto之間有兩個小時的差異。
作為一個更復雜的例子,下面的代碼顯示了一個公交車旅行時間計算器。 它有一個方法calculateTravelTime,它需要一個離開的ZonedDateTime實例和一個到達的ZonedDateTime實例。 該代碼調用calculateTravelTime方法兩次。 這兩次公交車都在丹佛早上8點從科羅拉多州丹佛出發,并于多倫多時間第二天早上8點抵達多倫多。 公交車首次于2014年3月8日啟程,第二次于2014年3月18日啟程。
兩種情況下的旅行時間是多少?
import java.time.Duration; import java.time.LocalDateTime; import java.time.Month; import java.time.ZoneId; import java.time.ZonedDateTime;public class TravelTimeCalculator {public Duration calculateTravelTime(ZonedDateTime departure, ZonedDateTime arrival) {return Duration.between(departure, arrival);}public static void main(String[] args) {TravelTimeCalculator calculator =new TravelTimeCalculator();ZonedDateTime departure1 = ZonedDateTime.of(LocalDateTime.of(2014, Month.MARCH, 8,8, 0),ZoneId.of("America/Denver"));ZonedDateTime arrival1 = ZonedDateTime.of(LocalDateTime.of(2014, Month.MARCH, 9,8, 0),ZoneId.of("America/Toronto"));Duration travelTime1 = calculator.calculateTravelTime(departure1, arrival1);System.out.println("Travel time 1: "+ travelTime1.toHours() + " hours");ZonedDateTime departure2 = ZonedDateTime.of(LocalDateTime.of(2014, Month.MARCH, 18,8, 0),ZoneId.of("America/Denver"));ZonedDateTime arrival2 = ZonedDateTime.of(LocalDateTime.of(2014, Month.MARCH, 19,8, 0),ZoneId.of("America/Toronto"));Duration travelTime2 = calculator.calculateTravelTime(departure2, arrival2);System.out.println("Travel time 2: "+ travelTime2.toHours() + " hours");} }運行結果為:
Travel time 1: 21 hoursTravel time 2: 22 hours為什么有這個區別? 因為2014年的夏令時從3月9日星期日凌晨2點開始。 因此,在2014年3月8日至2014年3月9日之間“失去”了一小時。
?Formatting A Date-Time
可以使用java.time.format.DateTimeFormatter格式化本地或時區日期時間。LocalDate,LocalDateTime,LocalTime和ZoneDateTime類提供具有以下簽名的格式方法。
public java.lang.String format(java.time.format.DateTimeFormatterformatter)很明顯,要格式化日期或時間,必須首先創建DateTimeFormatter實例。
下面的代碼使用兩個格式化實例格式化當前日期。
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle;public class DateTimeFormatterDemo1 {public static void main(String[] args) {DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);LocalDateTime example = LocalDateTime.of(2000, 3, 19, 10, 56, 59);System.out.println("Format 1: " + example.format(formatter1));???????DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MMMM dd, yyyy HH:mm:ss");System.out.println("Format 2: " +example.format(formatter2));} }運行結果如下:(第一個結果取決于你的區域設置)。
Format 1: 19-Mar-2000 10:56:59 AMFormat 2: March 19, 2000 10:56:59?Parsing A Date-Time
在Java Date和Time API的許多類中有兩種parse方法。第一個需要格式化實例,第二個則不需要。后一個方法會根據默認模式解析日期時間。要使用自己的格式化模式,請使用DateTimeFormatter。如果傳遞的字符串不能被解析,那么解析方法將拋出一個DateTimeParseException。
import java.time.LocalDate; import java.time.Period; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.Scanner;public class AgeCalculator {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-M-d");public Period calculateAge(LocalDate birthday) {LocalDate today = LocalDate.now();return Period.between(birthday, today);}public LocalDate getBirthday() {Scanner scanner = new Scanner(System.in);LocalDate birthday;while (true) {System.out.println("Please enter your birthday "+ "in yyyy-MM-dd format (e.g. 1980-9-28): ");String input = scanner.nextLine();try {birthday = LocalDate.parse(input, formatter);return birthday;} catch(DateTimeParseException e) {System.out.println("Error! Please try again");}}}public static void main(String[] args) {AgeCalculator ageCalculator = new AgeCalculator();LocalDate birthday = ageCalculator.getBirthday();Period age = ageCalculator.calculateAge(birthday);System.out.printf("Today you are %d years, %d months"+ " and %d days old%n",age.getYears(), age.getMonths(), age.getDays());} }AgeCalculator類有兩個方法,getBirthday和calculateAge。 getBirthday方法使用Scanner類來讀取用戶輸入,并使用DateTimeFormatter類將輸入解析到LocalDate中。 getBirthday方法一直請求一個日期,直到用戶輸入正確格式的日期,在這種情況下,方法返回。 calculateAge方法需要一個生日,并在生日和今天的日期之間創建一個Period實例。
如果運行這個例子,會在控制臺上看到這個。
Please enter your birthday in yyyy-MM-dd format (e.g. 1980-9-28):如果以正確的格式輸入日期,則程序將打印計算的年齡,如下所示。
Today you are 79 years, 0 months and 15 days old?Summary
Java 8帶來了全新的Date-Time API來替代以java.util.Date類為中心的舊的API。 通過本篇文章,學習如何使用新API中的核心類,如Instant,LocalDate,LocalDateTime,ZonedDateTime,Period和Duration,以及學習如何格式化和解析日期時間。
總結
以上是生活随笔為你收集整理的Java 8 Date-Time API 详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql备份和还原数据库
- 下一篇: Ubuntu安装设置nginx和nohu