Java8 日期/時間(Date Time)API指南
Java 8日期/時間( Date/Time)API是開發人員最受追捧的變化之一,Java從一開始就沒有對日期時間處理的一致性方法,因此日期/時間API也是除Java核心API以外另一項倍受歡迎的內容。
爲什麼我們需要新的Java日期/時間API?
- Java的日期/時間類的定義並不一致,在java.util和java.sql的包中都有日期類,此外用於格式化和解析的類在java.text包中定義。
- java.util.Date同時包含日期和時間,而java.sql.Date僅包含日期,將其納入java.sql包並不合理。另外這兩個類都有相同的名字,這本身就是一個非常糟糕的設計。
- 對於時間、時間戳、格式化以及解析,並沒有一些明確定義的類。對於格式化和解析的需求,我們有java.text.DateFormat抽象類,但通常情況下,SimpleDateFormat類被用於此類需求。
- 所有的日期類都是可變的,因此他們都不是線程安全的,這是Java日期類最大的問題之一。
- 日期類並不提供國際化,沒有時區支持,因此Java引入了java.util.Calendar和java.util.TimeZone類,但他們同樣存在上述所有的問題。
Java 8日期/時間API
- 不變性:新的日期/時間API中,所有的類都是不可變的,這對多線程環境有好處。
- 關注點分離:新的API將人可讀的日期時間和機器時間(unix timestamp)明確分離,它爲日期(Date)、時間(Time)、日期時間(DateTime)、時間戳(unix timestamp)以及時區定義了不同的類。
- 清晰:在所有的類中,方法都被明確定義用以完成相同的行爲。舉個例子,要拿到當前實例我們可以使用now()方法,在所有的類中都定義了format()和parse()方法,而不是像以前那樣專門有一個獨立的類。爲了更好的處理問題,所有的類都使用了工廠模式和策略模式,一旦你使用了其中某個類的方法,與其他類協同工作並不困難。
- 實用操作:所有新的日期/時間API類都實現了一系列方法用以完成通用的任務,如:加、減、格式化、解析、從日期/時間中提取單獨部分,等等。
- 可擴展性:新的日期/時間API是工作在ISO-8601日曆系統上的,但我們也可以將其應用在非IOS的日曆上。
Java日期/時間API包
- java.time包:這是新的Java日期/時間API的基礎包,所有的主要基礎類都是這個包的一部分,如:LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration等等。所有這些類都是不可變的和線程安全的,在絕大多數情況下,這些類能夠有效地處理一些公共的需求。
- java.time.chrono包:這個包爲非ISO的日曆系統定義了一些泛化的API,我們可以擴展AbstractChronology類來創建自己的日曆系統。
- java.time.format包:這個包包含能夠格式化和解析日期時間對象的類,在絕大多數情況下,我們不應該直接使用它們,因爲java.time包中相應的類已經提供了格式化和解析的方法。
- java.time.temporal包:這個包包含一些時態對象,我們可以用其找出關於日期/時間對象的某個特定日期或時間,比如說,可以找到某月的第一天或最後一天。你可以非常容易地認出這些方法,因爲它們都具有“withXXX”的格式。
- java.time.zone包:這個包包含支持不同時區以及相關規則的類。
Java日期/時間API示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
package com.journaldev.java8.time; import java.time.LocalDate; import java.time.Month; import java.time.ZoneId; /** *
LocalDate Examples *
@author pankaj * */ public class
LocalDateExample { public static
void
main(String[] args) { //Current
Date LocalDate
today = LocalDate.now(); System.out.println( "Current
Date=" +today); //Creating
LocalDate by providing input arguments LocalDate
firstDay_2014 = LocalDate.of( 2014 ,
Month.JANUARY, 1 ); System.out.println( "Specific
Date=" +firstDay_2014); //Try
creating date by providing invalid inputs //LocalDate
feb29_2014 = LocalDate.of(2014, Month.FEBRUARY, 29); //Exception
in thread "main" java.time.DateTimeException: //Invalid
date 'February 29' as '2014' is not a leap year //Current
date in "Asia/Kolkata", you can get it from ZoneId javadoc LocalDate
todayKolkata = LocalDate.now(ZoneId.of( "Asia/Kolkata" )); System.out.println( "Current
Date in IST=" +todayKolkata); //java.time.zone.ZoneRulesException:
Unknown time-zone ID: IST //LocalDate
todayIST = LocalDate.now(ZoneId.of("IST")); //Getting
date from the base date i.e 01/01/1970 LocalDate
dateFromBase = LocalDate.ofEpochDay( 365 ); System.out.println( "365th
day from base date= " +dateFromBase); LocalDate
hundredDay2014 = LocalDate.ofYearDay( 2014 , 100 ); System.out.println( "100th
day of 2014=" +hundredDay2014); } } |
1
2
3
4
5
|
Current
Date= 2014 - 04 - 28 Specific
Date= 2014 - 01 - 01 Current
Date in IST= 2014 - 04 - 29 365th
day from base date= 1971 - 01 - 01 100th
day of 2014 = 2014 - 04 - 10 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package com.journaldev.java8.time; import java.time.LocalTime; import java.time.ZoneId; /** *
LocalTime Examples *
@author pankaj * */ public class
LocalTimeExample { public static
void
main(String[] args) { //Current
Time LocalTime
time = LocalTime.now(); System.out.println( "Current
Time=" +time); //Creating
LocalTime by providing input arguments LocalTime
specificTime = LocalTime.of( 12 , 20 , 25 , 40 ); System.out.println( "Specific
Time of Day=" +specificTime); //Try
creating time by providing invalid inputs //LocalTime
invalidTime = LocalTime.of(25,20); //Exception
in thread "main" java.time.DateTimeException: //Invalid
value for HourOfDay (valid values 0 - 23): 25 //Current
date in "Asia/Kolkata", you can get it from ZoneId javadoc LocalTime
timeKolkata = LocalTime.now(ZoneId.of( "Asia/Kolkata" )); System.out.println( "Current
Time in IST=" +timeKolkata); //java.time.zone.ZoneRulesException:
Unknown time-zone ID: IST //LocalTime
todayIST = LocalTime.now(ZoneId.of("IST")); //Getting
date from the base date i.e 01/01/1970 LocalTime
specificSecondTime = LocalTime.ofSecondOfDay( 10000 ); System.out.println( "10000th
second time= " +specificSecondTime); } } |
1
2
3
4
|
Current
Time= 15 : 51 : 45.240 Specific
Time of Day= 12 : 20 : 25.000000040 Current
Time in IST= 04 : 21 : 45.276 10000th
second time= 02 : 46 : 40 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
package com.journaldev.java8.time; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; import java.time.ZoneId; import java.time.ZoneOffset; public class
LocalDateTimeExample { public static
void
main(String[] args) { //Current
Date LocalDateTime
today = LocalDateTime.now(); System.out.println( "Current
DateTime=" +today); //Current
Date using LocalDate and LocalTime today
= LocalDateTime.of(LocalDate.now(), LocalTime.now()); System.out.println( "Current
DateTime=" +today); //Creating
LocalDateTime by providing input arguments LocalDateTime
specificDate = LocalDateTime.of( 2014 ,
Month.JANUARY, 1 , 10 , 10 , 30 ); System.out.println( "Specific
Date=" +specificDate); //Try
creating date by providing invalid inputs //LocalDateTime
feb29_2014 = LocalDateTime.of(2014, Month.FEBRUARY, 28, 25,1,1); //Exception
in thread "main" java.time.DateTimeException: //Invalid
value for HourOfDay (valid values 0 - 23): 25 //Current
date in "Asia/Kolkata", you can get it from ZoneId javadoc LocalDateTime
todayKolkata = LocalDateTime.now(ZoneId.of( "Asia/Kolkata" )); System.out.println( "Current
Date in IST=" +todayKolkata); //java.time.zone.ZoneRulesException:
Unknown time-zone ID: IST //LocalDateTime
todayIST = LocalDateTime.now(ZoneId.of("IST")); //Getting
date from the base date i.e 01/01/1970 LocalDateTime
dateFromBase = LocalDateTime.ofEpochSecond( 10000 , 0 ,
ZoneOffset.UTC); System.out.println( "10000th
second time from 01/01/1970= " +dateFromBase); } } |
1
2
3
4
5
|
Current
DateTime= 2014 - 04 -28T16: 00 : 49.455 Current
DateTime= 2014 - 04 -28T16: 00 : 49.493 Specific
Date= 2014 - 01 -01T10: 10 : 30 Current
Date in IST= 2014 - 04 -29T04: 30 : 49.493 10000th
second time from 01 / 01 / 1970 = 1970 - 01 -01T02: 46 : 40 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.journaldev.java8.time; import java.time.Duration; import java.time.Instant; public class
InstantExample { public static
void
main(String[] args) { //Current
timestamp Instant
timestamp = Instant.now(); System.out.println( "Current
Timestamp = " +timestamp); //Instant
from timestamp Instant
specificTime = Instant.ofEpochMilli(timestamp.toEpochMilli()); System.out.println( "Specific
Time = " +specificTime); //Duration
example Duration
thirtyDay = Duration.ofDays( 30 ); System.out.println(thirtyDay); } } |
<span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">上述程序的輸出是:</span>
1
2
3
|
Current
Timestamp = 2014 - 04 -28T23: 20 : 08 .489Z Specific
Time = 2014 - 04 -28T23: 20 : 08 .489Z PT720H |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package com.journaldev.java8.time; import java.time.LocalDate; import java.time.LocalTime; import java.time.Period; import java.time.temporal.TemporalAdjusters; public class
DateAPIUtilities { public static
void
main(String[] args) { LocalDate
today = LocalDate.now(); //Get
the Year, check if it's leap year System.out.println( "Year
" +today.getYear()+ "
is Leap Year? " +today.isLeapYear()); //Compare
two LocalDate for before and after System.out.println( "Today
is before 01/01/2015? " +today.isBefore(LocalDate.of( 2015 , 1 , 1 ))); //Create
LocalDateTime from LocalDate System.out.println( "Current
Time=" +today.atTime(LocalTime.now())); //plus
and minus operations System.out.println( "10
days after today will be " +today.plusDays( 10 )); System.out.println( "3
weeks after today will be " +today.plusWeeks( 3 )); System.out.println( "20
months after today will be " +today.plusMonths( 20 )); System.out.println( "10
days before today will be " +today.minusDays( 10 )); System.out.println( "3
weeks before today will be " +today.minusWeeks( 3 )); System.out.println( "20
months before today will be " +today.minusMonths( 20 )); //Temporal
adjusters for adjusting the dates System.out.println( "First
date of this month= " +today.with(TemporalAdjusters.firstDayOfMonth())); LocalDate
lastDayOfYear = today.with(TemporalAdjusters.lastDayOfYear()); System.out.println( "Last
date of this year= " +lastDayOfYear); Period
period = today.until(lastDayOfYear); System.out.println( "Period
Format= " +period); System.out.println( "Months
remaining in the year= " +period.getMonths()); } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Year 2014 is
Leap Year? false Today
is before 01 / 01 / 2015 ? true Current
Time= 2014 - 04 -28T16: 23 : 53.154 10 days
after today will be 2014 - 05 - 08 3 weeks
after today will be 2014 - 05 - 19 20 months
after today will be 2015 - 12 - 28 10 days
before today will be 2014 - 04 - 18 3 weeks
before today will be 2014 - 04 - 07 20 months
before today will be 2012 - 08 - 28 First
date of this month=
2014 - 04 - 01 Last
date of this year=
2014 - 12 - 31 Period
Format= P8M3D Months
remaining in the year= 8 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package com.journaldev.java8.time; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class
DateParseFormatExample { public static
void
main(String[] args) { //Format
examples LocalDate
date = LocalDate.now(); //default
format System.out.println( "Default
format of LocalDate=" +date); //specific
format System.out.println(date.format(DateTimeFormatter.ofPattern( "d::MMM::uuuu" ))); System.out.println(date.format(DateTimeFormatter.BASIC_ISO_DATE)); LocalDateTime
dateTime = LocalDateTime.now(); //default
format System.out.println( "Default
format of LocalDateTime=" +dateTime); //specific
format System.out.println(dateTime.format(DateTimeFormatter.ofPattern( "d::MMM::uuuu
HH::mm::ss" ))); System.out.println(dateTime.format(DateTimeFormatter.BASIC_ISO_DATE)); Instant
timestamp = Instant.now(); //default
format System.out.println( "Default
format of Instant=" +timestamp); //Parse
examples LocalDateTime
dt = LocalDateTime.parse( "27::Apr::2014
21::39::48" , DateTimeFormatter.ofPattern( "d::MMM::uuuu
HH::mm::ss" )); System.out.println( "Default
format after parsing = " +dt); } } |
當運行以上程序時,可以看到如下輸出。
1
2
3
4
5
6
7
8
|
Default
format of LocalDate= 2014 - 04 - 28 28 ::Apr:: 2014 20140428 Default
format of LocalDateTime= 2014 - 04 -28T16: 25 : 49.341 28 ::Apr:: 2014 16 :: 25 :: 49 20140428 Default
format of Instant= 2014 - 04 -28T23: 25 : 49 .342Z Default
format after parsing = 2014 - 04 -27T21: 39 : 48 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
package com.journaldev.java8.time; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; public class
DateAPILegacySupport { public static
void
main(String[] args) { //Date
to Instant Instant
timestamp = new Date().toInstant(); //Now
we can convert Instant to LocalDateTime or other similar classes LocalDateTime
date = LocalDateTime.ofInstant(timestamp, ZoneId.of(ZoneId.SHORT_IDS.get( "PST" ))); System.out.println( "Date
= " +date); //Calendar
to Instant Instant
time = Calendar.getInstance().toInstant(); System.out.println(time); //TimeZone
to ZoneId ZoneId
defaultZone = TimeZone.getDefault().toZoneId(); System.out.println(defaultZone); //ZonedDateTime
from specific Calendar ZonedDateTime
gregorianCalendarDateTime = new GregorianCalendar().toZonedDateTime(); System.out.println(gregorianCalendarDateTime); //Date
API to Legacy classes Date
dt = Date.from(Instant.now()); System.out.println(dt); TimeZone
tz = TimeZone.getTimeZone(defaultZone); System.out.println(tz); GregorianCalendar
gc = GregorianCalendar.from(gregorianCalendarDateTime); System.out.println(gc); } } |
1
2
3
4
5
6
7
|
Date
= 2014 - 04 -28T16: 28 : 54.340 2014 - 04 -28T23: 28 : 54 .395Z America/Los_Angeles 2014 - 04 -28T16: 28 : 54.404 - 07 : 00 [America/Los_Angeles] Mon
Apr 28 16 : 28 : 54 PDT
2014 sun.util.calendar.ZoneInfo[id= "America/Los_Angeles" ,offset=- 28800000 ,dstSavings= 3600000 ,useDaylight= true ,transitions= 185 ,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=- 28800000 ,dstSavings= 3600000 ,useDaylight= true ,startYear= 0 ,startMode= 3 ,startMonth= 2 ,startDay= 8 ,startDayOfWeek= 1 ,startTime= 7200000 ,startTimeMode= 0 ,endMode= 3 ,endMonth= 10 ,endDay= 1 ,endDayOfWeek= 1 ,endTime= 7200000 ,endTimeMode= 0 ]] java.util.GregorianCalendar[time= 1398727734404 ,areFieldsSet= true ,areAllFieldsSet= true ,lenient= true ,zone=sun.util.calendar.ZoneInfo[id= "America/Los_Angeles" ,offset=- 28800000 ,dstSavings= 3600000 ,useDaylight= true ,transitions= 185 ,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=- 28800000 ,dstSavings= 3600000 ,useDaylight= true ,startYear= 0 ,startMode= 3 ,startMonth= 2 ,startDay= 8 ,startDayOfWeek= 1 ,startTime= 7200000 ,startTimeMode= 0 ,endMode= 3 ,endMonth= 10 ,endDay= 1 ,endDayOfWeek= 1 ,endTime= 7200000 ,endTimeMode= 0 ]],firstDayOfWeek= 2 ,minimalDaysInFirstWeek= 4 ,ERA= 1 ,YEAR= 2014 ,MONTH= 3 ,WEEK_OF_YEAR= 18 ,WEEK_OF_MONTH= 5 ,DAY_OF_MONTH= 28 ,DAY_OF_YEAR= 118 ,DAY_OF_WEEK= 2 ,DAY_OF_WEEK_IN_MONTH= 4 ,AM_PM= 1 ,HOUR= 4 ,HOUR_OF_DAY= 16 ,MINUTE= 28 ,SECOND= 54 ,MILLISECOND= 404 ,ZONE_OFFSET=- 28800000 ,DST_OFFSET= 3600000 ] |
譯文鏈接: http://www.importnew.com/14140.html
[ 轉載請保留原文出處、譯者和譯文鏈接。]