原文鏈接 作者:Javin Paul 譯者:之諸暇
除了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之後日期的解析及格式化也變得煥然一新了。隨便提一句,我是在去年這個時候Java正要推出這個新功能時寫的這篇文章,所以你會發現示例中的時間都還是去年的。你運行下這些例子,它們返回的值肯定都是正確的。
Java 8是如何處理時間及日期的
有人問我學習一個新庫的最佳途徑是什麼?我的回答是,就是在實際項目中那樣去使用它。在一個真實的項目中會有各種各樣的需求,這會促使開發人員去探索和研究這個新庫。簡言之,只有任務本身才會真正促使你去探索及學習。java 8的新的日期及時間API也是一樣。爲了學習Java 8的這個新庫,這裏我創建了20個以任務爲導向的例子。我們先從一個簡單的任務開始,比如說如何用Java 8的時間日期庫來表示今天,接着再進一步生成一個帶時間及時區的完整日期,然後再研究下如何完成一些更實際的任務,比如說開發一個提醒類的應用,來找出距離一些特定日期比如生日,週日紀念日,下一個帳單日,下一個溢價日或者信用卡過期時間還有多少天。
示例1 如何 在Java 8中獲取當天的日期
Java 8中有一個叫LocalDate的類,它能用來表示今天的日期。這個類與java.util.Date略有不同,因爲它只包含日期,沒有時間。因此,如果你只需要表示日期而不包含時間,就可以使用它。
1 |
LocalDate
today = LocalDate.now(); System.out.println( "Today's
Local date : " +
today); |
4 |
Today's
Local date : 2014 - 01 - 14 |
你可以看到它創建了今天的日期卻不包含時間信息。它還將日期格式化完了再輸出出來,不像之前的Date類那樣,打印出來的數據都是未經格式化的。
示例2 如何在Java 8中獲取當前的年月日
LocalDate類中提供了一些很方便的方法可以用於提取出年月日以及其它的日期屬性。使用這些方法,你可以獲取到任何你所需要的日期屬性,而不再需要使用java.util.Calendar這樣的類了:
1 |
LocalDate
today = LocalDate.now(); |
2 |
int year
= today.getYear(); |
3 |
int month
= today.getMonthValue(); |
4 |
int day
= today.getDayOfMonth(); |
5 |
System.out.printf( "Year
: %d Month : %d day : %d \t %n" ,
year, month, day); |
8 |
Today's
Local date : 2014 - 01 - 14 |
9 |
Year
: 2014 Month
: 1 day
: 14 |
可以看到,在Java 8中獲取年月信息非常簡單,只需使用對應的getter方法就好了,無需記憶,非常直觀。你可以拿它和Java中老的獲取當前年月日的寫法進行一下比較。
示例3 在Java 8中如何獲取某個特定的日期
在第一個例子中,我們看到通過靜態方法now()來生成當天日期是非常簡單的,不過通過另一個十分有用的工廠方法LocalDate.of(),則可以創建出任意一個日期,它接受年月日的參數,然後返回一個等價的LocalDate實例。關於這個方法還有一個好消息就是它沒有再犯之前API中的錯,比方說,年只能從1900年開始,月必須從0開始,等等。這裏的日期你寫什麼就是什麼,比如說,下面這個例子中它代表的就是1月14日,沒有什麼隱藏邏輯。
1 |
LocalDate
dateOfBirth = LocalDate.of( 2010 , 01 , 14 ); |
2 |
System.out.println( "Your
Date of birth is : " +
dateOfBirth); |
4 |
Output
: Your Date of birth is : 2010 - 01 - 14 |
可以看出,創建出來的日期就是我們所寫的那樣,2014年1月14日。
示例4 在Java 8中如何檢查兩個日期是否相等
如果說起現實中實際的處理時間及日期的任務,有一個常見的就是要檢查兩個日期是否相等。你可能經常會碰到要判斷今天是不是某個特殊的日子,比如生日啊,週年紀念日啊,或者假期之類。有的時候,會給你一個日期,讓你檢查它是不是某個日子比方說假日。下面這個例子將會幫助你在Java 8中完成這類任務。正如你所想的那樣,LocalDate重寫了equals方法來進行日期的比較,如下所示:
1 |
LocalDate
date1 = LocalDate.of( 2014 , 01 , 14 ); if (date1.equals(today)){ |
2 |
System.out.printf( "Today
%s and date1 %s are same date %n" ,
today, date1); |
6 |
today 2014 - 01 - 14 and
date1 2014 - 01 - 14 are
same date |
在本例中我們比較的兩個日期是相等的。同時,如果在代碼中你拿到了一個格式化好的日期串,你得先將它解析成日期然後才能比較。你可以將這個例子與Java之前比較日期的方式進行下比較,你會發現它真是爽多了。
示例5 在Java 8中如何檢查重複事件,比如說生日
在Java中還有一個與時間日期相關的實際任務就是檢查重複事件,比如說每月的帳單日,結婚紀念日,每月還款日或者是每年交保險費的日子。如果你在一家電商公司工作的話,那麼肯定會有這麼一個模塊,會去給用戶發送生日祝福並且在每一個重要的假日給他們捎去問候,比如說聖誕節,感恩節,在印度則可能是萬燈節(Deepawali)。如何在Java中判斷是否是某個節日或者重複事件?使用MonthDay類。這個類由月日組合,不包含年信息,也就是說你可以用它來代表每年重複出現的一些日子。當然也有一些別的組合,比如說YearMonth類。它和新的時間日期庫中的其它類一樣也都是不可變且線程安全的,並且它還是一個值類(value
class)。我們通過一個例子來看下如何使用MonthDay來檢查某個重複的日期:
01 |
LocalDate
dateOfBirth = LocalDate.of( 2010 , 01 , 14 ); |
02 |
MonthDay
birthday = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth()); |
03 |
MonthDay
currentMonthDay = MonthDay.from(today); |
04 |
if (currentMonthDay.equals(birthday)){ |
05 |
System.out.println( "Many
Many happy returns of the day !!" ); |
07 |
System.out.println( "Sorry,
today is not your birthday" ); |
10 |
Output:
Many Many happy returns of the day !! |
雖然年不同,但今天就是生日的那天,所以在輸出那裏你會看到一條生日祝福。你可以調整下系統的時間再運行下這個程序看看它是否能提醒你下一個生日是什麼時候,你還可以試着用你的下一個生日來編寫一個JUnit單元測試看看代碼能否正確運行。
示例6 如何在Java 8中獲取當前時間
這與第一個例子中獲取當前日期非常相似。這次我們用的是一個叫LocalTime的類,它是沒有日期的時間,與LocalDate是近親。這裏你也可以用靜態工廠方法now()來獲取當前時間。默認的格式是hh:mm:ss:nnn,這裏的nnn是納秒。可以和Java
8以前如何獲取當前時間做一下比較。
1 |
LocalTime
time = LocalTime.now(); System.out.println( "local
time now : " +
time); |
4 |
local
time now : 16 : 33 : 33.369 |
可以看到,當前時間是不包含日期的,因爲LocalTime只有時間,沒有日期。
示例7 如何增加時間裏面的小時數
很多時候我們需要增加小時,分或者秒來計算出將來的時間。Java 8不僅提供了不可變且線程安全的類,它還提供了一些更方便的方法譬如plusHours()來替換原來的add()方法。順便說一下,這些方法返回的是一個新的LocalTime實例的引用,因爲LocalTime是不可變的,可別忘了存儲好這個新的引用。
1 |
LocalTime
time = LocalTime.now(); |
2 |
LocalTime
newTime = time.plusHours( 2 ); |
3 |
System.out.println( "Time
after 2 hours : " +
newTime); |
6 |
Time
after 2 hours
: 18 : 33 : 33.369 |
可以看到當前時間2小時後是16:33:33.369。現在你可以將它和Java中增加或者減少小時的老的方式進行下比較。一看便知哪種方式更好。
示例8 如何獲取1周後的日期
這與前一個獲取2小時後的時間的例子類似,這裏我們將學會如何獲取到1周後的日期。LocalDate是用來表示無時間的日期的,它有一個plus()方法可以用來增加日,星期,或者月,ChronoUnit則用來表示這個時間單位。由於LocalDate也是不可變的,因此任何修改操作都會返回一個新的實例,因此別忘了保存起來。
1 |
LocalDate
nextWeek = today.plus( 1 ,
ChronoUnit.WEEKS); |
2 |
System.out.println( "Today
is : " +
today); |
3 |
System.out.println( "Date
after 1 week : " +
nextWeek); |
8 |
Date
after 1 week
: 2014 - 01 - 21 |
可以看到7天也就是一週後的日期是什麼。你可以用這個方法來增加一個月,一年,一小時,一分鐘,甚至是十年,查看下Java API中的ChronoUnit類來獲取更多選項。
示例9 一年前後的日期
這是上個例子的續集。上例中,我們學習瞭如何使用LocalDate的plus()方法來給日期增加日,周或者月,現在我們來學習下如何用minus()方法來找出一年前的那天。
1 |
LocalDate
previousYear = today.minus( 1 ,
ChronoUnit.YEARS); |
2 |
System.out.println( "Date
before 1 year : " +
previousYear); |
3 |
LocalDate
nextYear = today.plus( 1 ,
YEARS); |
4 |
System.out.println( "Date
after 1 year : " +
nextYear); |
7 |
Date
before 1 year
: 2013 - 01 - 14 |
8 |
Date
after 1 year
: 2015 - 01 - 14 |
可以看到現在一共有兩年,一個是2013年,一個是2015年,分別是2014的前後那年。
示例10 在Java 8中使用時鐘
Java 8中自帶了一個Clock類,你可以用它來獲取某個時區下當前的瞬時時間,日期或者時間。可以用Clock來替代System.currentTimeInMillis()與 TimeZone.getDefault()方法。
02 |
Clock
clock = Clock.systemUTC(); |
03 |
System.out.println( "Clock
: " +
clock); |
06 |
Clock.systemDefaultZone(); |
07 |
System.out.println( "Clock
: " +
clock); |
10 |
Clock
: SystemClock[Z] |
11 |
Clock
: SystemClock[Z] |
你可以用指定的日期來和這個時鐘進行比較,比如下面這樣:
01 |
public class MyClass
{ |
04 |
public void process(LocalDate
eventDate) { |
06 |
if (eventDate.isBefore(LocalDate.now(clock))
{ |
如果你需要對不同時區的日期進行處理的話這是相當方便的。
示例11 在Java中如何判斷某個日期是在另一個日期的前面還是後面
這也是實際項目中常見的一個任務。你怎麼判斷某個日期是在另一個日期的前面還是後面,或者正好相等呢?在Java 8中,LocalDate類有一個isBefore()和isAfter()方法可以用來比較兩個日期。如果調用方法的那個日期比給定的日期要早的話,isBefore()方法會返回true。
01 |
LocalDate
tomorrow = LocalDate.of( 2014 , 1 , 15 );
、 if (tommorow.isAfter(today)){ |
02 |
System.out.println( "Tomorrow
comes after today" ); |
04 |
LocalDate
yesterday = today.minus( 1 ,
DAYS); |
05 |
if (yesterday.isBefore(today)){ |
06 |
System.out.println( "Yesterday
is day before today" ); |
10 |
Tomorrow
comes after today |
11 |
Yesterday
is day before today |
可以看到在Java 8中進行日期比較非常簡單。不需要再用像Calendar這樣的另一個類來完成類似的任務了。
示例12 在Java 8中處理不同的時區
Java 8不僅將日期和時間進行了分離,同時還有時區。現在已經有好幾組與時區相關的類了,比如ZonId代表的是某個特定的時區,而ZonedDateTime代表的是帶時區的時間。它等同於Java 8以前的GregorianCalendar類。使用這個類,你可以將本地時間轉換成另一個時區中的對應時間,比如下面這個例子:
2 |
LocalDateTime
localtDateAndTime = LocalDateTime.now(); |
3 |
ZonedDateTime
dateAndTimeInNewYork = ZonedDateTime.of(localtDateAndTime, america ); |
4 |
System.out.println( "Current
date and time in a particular timezone : " +
dateAndTimeInNewYork); |
7 |
Current
date and time in a particular timezone : 2014 - 01 -14T16: 33 : 33.373 - 05 : 00 [America/New_York] |
可以拿它跟之前將本地時間轉換成GMT時間的方式進行下比較。順便說一下,正如Java 8以前那樣,對應時區的那個文本可別弄錯了,否則你會碰到這麼一個異常:
1 |
Exception
in thread "main" java.time.zone.ZoneRulesException:
Unknown time-zone ID: ASIA/Tokyo |
2 |
at
java.time.zone.ZoneRulesProvider.getProvider(ZoneRulesProvider.java: 272 ) |
3 |
at
java.time.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java: 227 ) |
4 |
at
java.time.ZoneRegion.ofId(ZoneRegion.java: 120 ) |
5 |
at
java.time.ZoneId.of(ZoneId.java: 403 ) |
6 |
at
java.time.ZoneId.of(ZoneId.java: 351 ) |
示例13 如何表示固定的日期,比如信用卡過期時間
正如MonthDay表示的是某個重複出現的日子的,YearMonth又是另一個組合,它代表的是像信用卡還款日,定期存款到期日,options到期日這類的日期。你可以用這個類來找出那個月有多少天,lengthOfMonth()這個方法返回的是這個YearMonth實例有多少天,這對於檢查2月到底是28天還是29天可是非常有用的。
1 |
YearMonth
currentYearMonth = YearMonth.now(); System.out.printf( "Days
in month year %s: %d%n" ,
currentYearMonth, currentYearMonth.lengthOfMonth()); |
2 |
YearMonth
creditCardExpiry = YearMonth.of( 2018 ,
Month.FEBRUARY); |
3 |
System.out.printf( "Your
credit card expires on %s %n" ,
creditCardExpiry); |
6 |
Days
in month year 2014 - 01 : 31 |
7 |
Your
credit card expires on 2018 - 02 |
示例14 如何在Java 8中檢查閏年
這並沒什麼複雜的,LocalDate類有一個isLeapYear()的方法能夠返回當前LocalDate對應的那年是否是閏年。如果你還想重複造輪子的話,可以看下這段代碼,這是純用Java編寫的判斷某年是否是閏年的邏輯。
1 |
if (today.isLeapYear()){ |
2 |
System.out.println( "This
year is Leap year" ); |
4 |
System.out.println( "2014
is not a Leap year" ); |
8 |
Output: 2014 is
not a Leap year |
你可以多檢查幾年看看結果是否正確,最好寫一個單元測試來對正常年份和閏年進行下測試。
示例15 兩個日期之間包含多少天,多少個月
還有一個常見的任務就是計算兩個給定的日期之間包含多少天,多少周或者多少年。你可以用java.time.Period類來完成這個功能。在下面這個例子中,我們將計算當前日期與將來的一個日期之前一共隔着幾個月。
1 |
LocalDate
java8Release = LocalDate.of( 2014 ,
Month.MARCH, 14 ); |
2 |
Period
periodToNextJavaRelease = |
3 |
Period.between(today,
java8Release); |
4 |
System.out.println( "Months
left between today and Java 8 release : " +
periodToNextJavaRelease.getMonths() ); |
7 |
Months
left between today and Java 8 release
: 2 |
可以看到,本月是1月,而Java 8的發佈日期是3月,因此中間隔着2個月。
示例16 帶時區偏移量的日期與時間
在Java 8裏面,你可以用ZoneOffset類來代表某個時區,比如印度是GMT或者UTC5:30,你可以使用它的靜態方法ZoneOffset.of()方法來獲取對應的時區。只要獲取到了這個偏移量,你就可以拿LocalDateTime和這個偏移量創建出一個OffsetDateTime。
1 |
LocalDateTime
datetime = LocalDateTime.of( 2014 ,
Month.JANUARY, 14 , 19 , 30 ); |
2 |
ZoneOffset
offset = ZoneOffset.of( "+05:30" ); |
3 |
OffsetDateTime
date = OffsetDateTime.of(datetime, offset); |
4 |
System.out.println( "Date
and Time with timezone offset in Java : " +
date); |
7 |
Date
and Time with timezone offset in Java : 2014 - 01 -14T19: 30 + 05 : 30 |
可以看到現在時間日期與時區是關聯上了。還有一點就是,OffSetDateTime主要是給機器來理解的,如果是給人看的,可以使用ZoneDateTime類。
示例17 在Java 8中如何獲取當前時間戳
如果你還記得在Java 8前是如何獲取當前時間戳的,那現在這簡直就是小菜一碟了。Instant類有一個靜態的工廠方法now()可以返回當前時間戳,如下:
1 |
Instant
timestamp = Instant.now(); |
2 |
System.out.println( "What
is value of this instant " +
timestamp); |
5 |
What
is value of this instant 2014 - 01 -14T08: 33 : 33 .379Z |
可以看出,當前時間戳是包含日期與時間的,與java.util.Date很類似,事實上Instant就是Java 8前的Date,你可以使用這兩個類中的方法來在這兩個類型之間進行轉換,比如Date.from(Instant)是用來將Instant轉換成java.util.Date的,而Date.toInstant()是將Date轉換成Instant的。
示例18 如何在Java 8中使用預定義的格式器來對日期進行解析/格式化
在Java 8之前,時間日期的格式化可是個技術活,我們的好夥伴SimpleDateFormat並不是線程安全的,而如果用作本地變量來格式化的話又顯得有些笨重。多虧了線程本地變量,這使得它在多線程環境下也算有了用武之地,但Java維持這一狀態也有很長一段時間了。這次它引入了一個全新的線程安全的日期與時間格式器。它還自帶了一些預定義好的格式器,包含了常用的日期格式。比如說,本例
中我們就用了預定義的BASIC_ISO_DATE格式,它會將2014年2月14日格式化成20140114。
1 |
String
dayAfterTommorrow = "20140116" ; |
2 |
LocalDate
formatted = LocalDate.parse(dayAfterTommorrow, |
3 |
DateTimeFormatter.BASIC_ISO_DATE); |
4 |
System.out.printf( "Date
generated from String %s is %s %n" ,
dayAfterTommorrow, formatted); |
7 |
Date
generated from String 20140116 is 2014 - 01 - 16 |
你可以看到生成的日期與指定字符串的值是匹配的,就是日期格式上略有不同。
示例19 如何在Java中使用自定義的格式器來解析日期
在上例中,我們使用了內建的時間日期格式器來解析日期字符串。當然了,預定義的格式器的確不錯但有時候你可能還是需要使用自定義的日期格式,這個時候你就得自己去創建一個自定義的日期格式器實例了。下面這個例子中的日期格式是”MMM
dd yyyy”。你可以給DateTimeFormatter的ofPattern靜態方法()傳入任何的模式,它會返回一個實例,這個模式的字面量與前例中是相同的。比如說M還是代表月,而m仍是分。無效的模式會拋出DateTimeParseException異常,但如果是邏輯上的錯誤比如說該用M的時候用成m,這樣就沒辦法了。
01 |
String
goodFriday = "Apr
18 2014" ; |
03 |
DateTimeFormatter
formatter = DateTimeFormatter.ofPattern( "MMM
dd yyyy" ); |
04 |
LocalDate
holiday = LocalDate.parse(goodFriday, formatter); |
05 |
System.out.printf( "Successfully
parsed String %s, date is %s%n" ,
goodFriday, holiday); |
06 |
} catch (DateTimeParseException
ex) { |
07 |
System.out.printf( "%s
is not parsable!%n" ,
goodFriday); |
12 |
Successfully
parsed String Apr 18 2014 ,
date is 2014 - 04 - 18 |
可以看到日期的值與傳入的字符串的確是相符的,只是格式不同。
示例20 如何在Java 8中對日期進行格式化,轉換成字符串
在上兩個例子中,儘管我們用到了DateTimeFormatter類但我們主要是進行日期字符串的解析。在這個例子中我們要做的事情正好相反。這裏我們有一個LocalDateTime類的實例,我們要將它轉換成一個格式化好的日期串。這是目前爲止Java中將日期轉換成字符串最簡單便捷的方式了。下面這個例子將會返回一個格式化好的字符串。與前例相同的是,我們仍需使用指定的模式串去創建一個DateTimeFormatter類的實例,但調用的並不是LocalDate類的parse方法,而是它的format()方法。這個方法會返回一個代表當前日期的字符串,對應的模式就是傳入的DateTimeFormatter實例中所定義好的。
01 |
LocalDateTime
arrivalDate = LocalDateTime.now(); |
03 |
DateTimeFormatter
format = DateTimeFormatter.ofPattern( "MMM
dd yyyy hh:mm a" ); |
04 |
String
landing = arrivalDate.format(format); |
05 |
System.out.printf( "Arriving
at : %s %n" ,
landing); |
06 |
} catch (DateTimeException
ex) { |
07 |
System.out.printf( "%s
can't be formatted!%n" ,
arrivalDate); |
11 |
Output
: Arriving at : Jan 14 2014 04 : 33 PM |
可以看到,當前時間是用給定的”MMM dd yyyy hh:mm a”模式來表示的,它包含了三個字母表示的月份以及用AM及PM來表示的時間。
Java 8中日期與時間API的幾個關鍵點
看完了這些例子後,我相信你已經對Java 8這套新的時間日期API有了一定的瞭解了。現在我們來回顧下關於這個新的API的一些關鍵的要素。
1. 它提供了javax.time.ZoneId用來處理時區。
2. 它提供了LocalDate與LocalTime類
3. Java 8中新的時間與日期API中的所有類都是不可變且線程安全的,這與之前的Date與Calendar API中的恰好相反,那裏面像java.util.Date以及SimpleDateFormat這些關鍵的類都不是線程安全的。
4. 新的時間與日期API中很重要的一點是它定義清楚了基本的時間與日期的概念,比方說,瞬時時間,持續時間,日期,時間,時區以及時間段。它們都是基於ISO日曆體系的。
5. 每個Java開發人員都應該至少了解這套新的API中的這五個類:
– Instant 它代表的是時間戳,比如2014-01-14T02:20:13.592Z,這可以從java.time.Clock類中獲取,像這樣:
Instant current = Clock.system(ZoneId.of(“Asia/Tokyo”)).instant();
– LocalDate 它表示的是不帶時間的日期,比如2014-01-14。它可以用來存儲生日,週年紀念日,入職日期等。
– LocalTime – 它表示的是不帶日期的時間
– LocalDateTime – 它包含了時間與日期,不過沒有帶時區的偏移量
– ZonedDateTime – 這是一個帶時區的完整時間,它根據UTC/格林威治時間來進行時區調整
6. 這個庫的主包是java.time,裏面包含了代表日期,時間,瞬時以及持續時間的類。它有兩個子package,一個是java.time.foramt,這個是什麼用途就很明顯了,還有一個是java.time.temporal,它能從更低層面對各個字段進行訪問。
7. 時區指的是地球上共享同一標準時間的地區。每個時區都有一個唯一標識符,同時還有一個地區/城市(Asia/Tokyo)的格式以及從格林威治時間開始的一個偏移時間。比如說,東京的偏移時間就是+09:00。
8. OffsetDateTime類實際上包含了LocalDateTime與ZoneOffset。它用來表示一個包含格林威治時間偏移量(+/-小時:分,比如+06:00或者 -08:00)的完整的日期(年月日)及時間(時分秒,納秒)。
9. DateTimeFormatter類用於在Java中進行日期的格式化與解析。與SimpleDateFormat不同,它是不可變且線程安全的,如果需要的話,可以賦值給一個靜態變量。DateTimeFormatter類提供了許多預定義的格式器,你也可以自定義自己想要的格式。當然了,根據約定,它還有一個parse()方法是用於將字符串轉換成日期的,如果轉換期間出現任何錯誤,它會拋出DateTimeParseException異常。類似的,DateFormatter類也有一個用於格式化日期的format()方法,它出錯的話則會拋出DateTimeException異常。
10. 再說一句,“MMM d yyyy”與“MMm dd yyyy”這兩個日期格式也略有不同,前者能識別出”Jan 2 2014″與”Jan 14 2014″這兩個串,而後者如果傳進來的是”Jan 2 2014″則會報錯,因爲它期望月份處傳進來的是兩個字符。爲了解決這個問題,在天爲個位數的情況下,你得在前面補0,比如”Jan 2 2014″應該改爲”Jan 02 2014″。
關於Java 8這個新的時間日期API就講到這了。這幾個簡短的示例 對於理解這套新的API中的一些新增類已經足夠了。由於它是基於實際任務來講解的,因此後面再遇到Java中要對時間與日期進行處理的工作時,就不用再四處尋找了。我們學習瞭如何創建與修改日期實例。我們還了解了純日期,日期加時間,日期加時區的區別,知道如何比較兩個日期,如何找到某天到指定日期比如說下一個生日,週年紀念日或者保險日還有多少天。我們還學習瞭如何在Java 8中用線程安全的方式對日期進行解析及格式化,而無需再使用線程本地變量或者第三方庫這種取巧的方式。新的API能勝任任何與時間日期相關的任務。