深入了解Java 8日期和时间API
在這篇文章中,我們將更深入地了解通過Java 8獲得的新的Date / Time API(
JSR 310 )。 請(qǐng)注意,本文主要由顯示新API功能的代碼示例驅(qū)動(dòng)。 我認(rèn)為這些示例是不言自明的,因此我沒有花太多時(shí)間在它們周圍寫文本:-)
讓我們開始吧!
處理日期和時(shí)間對(duì)象
Java 8 Date / Time API的所有類都位于java.time包內(nèi)。 我們要看的第一類是java.time.LocalDate。 LocalDate表示沒有時(shí)間的年月日日期。 我們從創(chuàng)建新的LocalDate實(shí)例開始:
//?the?current?date LocalDate?currentDate?=?LocalDate.now();//?2014-02-10 LocalDate?tenthFeb2014?=?LocalDate.of(2014,?Month.FEBRUARY,?10);//?months?values?start?at?1?(2014-08-01) LocalDate?firstAug2014?=?LocalDate.of(2014,?8,?1);//?the?65th?day?of?2010?(2010-03-06) LocalDate?sixtyFifthDayOf2010?=?LocalDate.ofYearDay(2010,?65);LocalTime和LocalDateTime是我們要研究的下一個(gè)類。 兩者的工作方式都與LocalDate類似。 LocalTime可用于時(shí)間(無日期),而LocalDateTime可將日期和時(shí)間組合在一個(gè)類中:
LocalTime?currentTime?=?LocalTime.now();?//?current?time LocalTime?midday?=?LocalTime.of(12,?0);?//?12:00 LocalTime?afterMidday?=?LocalTime.of(13,?30,?15);?//?13:30:15//?12345th?second?of?day?(03:25:45) LocalTime?fromSecondsOfDay?=?LocalTime.ofSecondOfDay(12345);//?dates?with?times,?e.g.?2014-02-18 19:08:37.950 LocalDateTime?currentDateTime?=?LocalDateTime.now();//?2014-10-02?12:30 LocalDateTime?secondAug2014?=?LocalDateTime.of(2014,?10,?2,?12,?30);//?2014-12-24?12:00 LocalDateTime?christmas2014?=?LocalDateTime.of(2014,?Month.DECEMBER,?24,?12,?0);默認(rèn)情況下,LocalDate / Time類將使用默認(rèn)時(shí)區(qū)中的系統(tǒng)時(shí)鐘。 我們可以通過提供時(shí)區(qū)或其他Clock實(shí)現(xiàn)來更改此設(shè)置:
//?current?(local)?time?in?Los?Angeles LocalTime?currentTimeInLosAngeles?=?LocalTime.now(ZoneId.of("America/Los_Angeles"));//?current?time?in?UTC?time?zone LocalTime?nowInUtc?=?LocalTime.now(Clock.systemUTC());從LocalDate / Time對(duì)象,我們可以獲得我們可能需要的各種有用信息。 一些例子:
LocalDate?date?=?LocalDate.of(2014,?2,?15);?//?2014-02-15boolean?isBefore?=?LocalDate.now().isBefore(date);?//?false//?information?about?the?month Month?february?=?date.getMonth();?//?FEBRUARY int?februaryIntValue?=?february.getValue();?//?2 int?minLength?=?february.minLength();?//?28 int?maxLength?=?february.maxLength();?//?29 Month?firstMonthOfQuarter?=?february.firstMonthOfQuarter();?//?JANUARY//?information?about?the?year int?year?=?date.getYear();?//?2014 int?dayOfYear?=?date.getDayOfYear();?//?46 int?lengthOfYear?=?date.lengthOfYear();?//?365 boolean?isLeapYear?=?date.isLeapYear();?//?falseDayOfWeek?dayOfWeek?=?date.getDayOfWeek(); int?dayOfWeekIntValue?=?dayOfWeek.getValue();?//?6 String?dayOfWeekName?=?dayOfWeek.name();?//?SATURDAYint?dayOfMonth?=?date.getDayOfMonth();?//?15 LocalDateTime?startOfDay?=?date.atStartOfDay();?//?2014-02-15 00:00//?time?information LocalTime?time?=?LocalTime.of(15,?30);?//?15:30:00 int?hour?=?time.getHour();?//?15 int?second?=?time.getSecond();?//?0 int?minute?=?time.getMinute();?//?30 int?secondOfDay?=?time.toSecondOfDay();?//?55800無需提供特定日期即可獲得某些信息。 例如,如果我們需要有關(guān)特定年份的信息,則可以使用Year類:
Year?currentYear?=?Year.now(); Year?twoThousand?=?Year.of(2000); boolean?isLeap?=?currentYear.isLeap();?//?false int?length?=?currentYear.length();?//?365//?sixtyFourth?day?of?2014?(2014-03-05) LocalDate?date?=?Year.of(2014).atDay(64);我們可以使用加號(hào)和減號(hào)方法來添加或減去特定的時(shí)間量。 請(qǐng)注意,這些方法總是返回一個(gè)新實(shí)例(Java 8日期/時(shí)間類是不可變的)。
LocalDate?tomorrow?=?LocalDate.now().plusDays(1);//?before?5?houres?and?30?minutes LocalDateTime?dateTime?=?LocalDateTime.now().minusHours(5).minusMinutes(30);TemporalAdjusters是日期處理的另一種不錯(cuò)的方法。 TemporalAdjuster是一個(gè)單一方法接口,用于將調(diào)整過程與實(shí)際日期/時(shí)間對(duì)象分開。 可以使用TemporalAdjusters類的靜態(tài)方法訪問一組常見的TemporalAdjusters 。
LocalDate?date?=?LocalDate.of(2014,?Month.FEBRUARY,?25);?//?2014-02-25//?first?day?of?february?2014?(2014-02-01) LocalDate?firstDayOfMonth?=?date.with(TemporalAdjusters.firstDayOfMonth());//?last?day?of?february?2014?(2014-02-28) LocalDate?lastDayOfMonth?=?date.with(TemporalAdjusters.lastDayOfMonth());靜態(tài)導(dǎo)入使它更通俗易懂:
import?static?java.time.temporal.TemporalAdjusters.*;...//?last?day?of?2014?(2014-12-31) LocalDate?lastDayOfYear?=?date.with(lastDayOfYear());//?first?day?of?next?month?(2014-03-01) LocalDate?firstDayOfNextMonth?=?date.with(firstDayOfNextMonth());//?next?sunday?(2014-03-02) LocalDate?nextSunday?=?date.with(next(DayOfWeek.SUNDAY));時(shí)區(qū)
使用時(shí)區(qū)是新API簡(jiǎn)化的另一個(gè)重要主題。 到目前為止,我們已經(jīng)看到的LocalDate / Time類不包含有關(guān)時(shí)區(qū)的信息。 如果我們要使用某個(gè)時(shí)區(qū)中的日期/時(shí)間,可以使用ZonedDateTime或OffsetDateTime :
ZoneId?losAngeles?=?ZoneId.of("America/Los_Angeles"); ZoneId?berlin?=?ZoneId.of("Europe/Berlin");//?2014-02-20?12:00 LocalDateTime?dateTime?=?LocalDateTime.of(2014,?02,?20,?12,?0);//?2014-02-20?12:00,?Europe/Berlin?(+01:00) ZonedDateTime?berlinDateTime?=?ZonedDateTime.of(dateTime,?berlin);//?2014-02-20?03:00,?America/Los_Angeles?(-08:00) ZonedDateTime?losAngelesDateTime?=?berlinDateTime.withZoneSameInstant(losAngeles);int?offsetInSeconds?=?losAngelesDateTime.getOffset().getTotalSeconds();?//?-28800//?a?collection?of?all?available?zones Set<String>?allZoneIds?=?ZoneId.getAvailableZoneIds();//?using?offsets LocalDateTime?date?=?LocalDateTime.of(2013,?Month.JULY,?20,?3,?30); ZoneOffset?offset?=?ZoneOffset.of("+05:00");//?2013-07-20 03:30?+05:00 OffsetDateTime?plusFive?=?OffsetDateTime.of(date,?offset);//?2013-07-19?20:30?-02:00 OffsetDateTime?minusTwo?=?plusFive.withOffsetSameInstant(ZoneOffset.ofHours(-2));時(shí)間戳記
諸如LocalDate和ZonedDateTime之類的類提供了對(duì)時(shí)間的直觀了解。 但是,通常我們需要從機(jī)器角度來看待時(shí)間。 為此,我們可以使用表示時(shí)間戳的Instant類。 即時(shí)計(jì)數(shù)是從1970年1月1日(1970-01-01 00:00:00)的第一秒開始的時(shí)間,也稱為EPOCH 。 如果即時(shí)值出現(xiàn)在紀(jì)元之前,則它們可以為負(fù)。 它們遵循ISO 8601表示日期和時(shí)間的標(biāo)準(zhǔn)。
//?current?time Instant?now?=?Instant.now();//?from?unix?timestamp,?2010-01-01?12:00:00 Instant?fromUnixTimestamp?=?Instant.ofEpochSecond(1262347200);//?same?time?in?millis Instant?fromEpochMilli?=?Instant.ofEpochMilli(1262347200000l);//?parsing?from?ISO?8601 Instant?fromIso8601?=?Instant.parse("2010-01-01T12:00:00Z");//?toString()?returns?ISO?8601?format, e.g. 2014-02-15T01:02:03Z String?toIso8601?=?now.toString();//?as?unix?timestamp long?toUnixTimestamp?=?now.getEpochSecond();//?in?millis long?toEpochMillis?=?now.toEpochMilli();// plus/minus methods are available too Instant?nowPlusTenSeconds?=?now.plusSeconds(10);期限和期限
期間和持續(xù)時(shí)間是另外兩個(gè)重要的類別。 就像名稱所暗示的那樣,它們代表時(shí)間或數(shù)量。 期間使用基于日期的值(年,月,日),而期間使用秒或納秒來定義時(shí)間量。 持續(xù)時(shí)間最適合使用Instants和機(jī)器時(shí)間。 如果終點(diǎn)發(fā)生在起點(diǎn)之前,則“期間”和“持續(xù)時(shí)間”可以包含負(fù)值。
//?periodsLocalDate?firstDate?=?LocalDate.of(2010,?5,?17);?//?2010-05-17 LocalDate?secondDate?=?LocalDate.of(2015,?3,?7);?//?2015-03-07 Period?period?=?Period.between(firstDate,?secondDate);int?days?=?period.getDays();?//?18 int?months?=?period.getMonths();?//?9 int?years?=?period.getYears();?//?4 boolean?isNegative?=?period.isNegative();?//?falsePeriod?twoMonthsAndFiveDays?=?Period.ofMonths(2).plusDays(5); LocalDate?sixthOfJanuary?=?LocalDate.of(2014,?1,?6);//?add?two?months?and?five?days?to?2014-01-06,?result?is?2014-03-11 LocalDate?eleventhOfMarch?=?sixthOfJanuary.plus(twoMonthsAndFiveDays);//?durationsInstant?firstInstant=?Instant.ofEpochSecond(?1294881180?);?//?2011-01-13?01:13 Instant?secondInstant?=?Instant.ofEpochSecond(1294708260);?//?2011-01-11?01:11Duration?between?=?Duration.between(firstInstant,?secondInstant);//?negative?because?firstInstant?is?after?secondInstant?(-172920) long?seconds?=?between.getSeconds();//?get?absolute?result?in?minutes?(2882) long?absoluteResult?=?between.abs().toMinutes();//?two?hours?in?seconds?(7200) long?twoHoursInSeconds?=?Duration.ofHours(2).getSeconds();格式化和解析
格式化和解析是處理日期和時(shí)間時(shí)的另一個(gè)大話題。 在Java 8中,這可以通過使用format()和parse()方法來實(shí)現(xiàn):
//?2014-04-01?10:45 LocalDateTime?dateTime?=?LocalDateTime.of(2014,?Month.APRIL,?1,?10,?45);//?format?as?basic?ISO?date?format?(20140220) String?asBasicIsoDate?=?dateTime.format(DateTimeFormatter.BASIC_ISO_DATE);//?format?as?ISO?week?date?(2014-W08-4) String?asIsoWeekDate?=?dateTime.format(DateTimeFormatter.ISO_WEEK_DATE);//?format?ISO?date?time?(2014-02-20T20:04:05.867) String?asIsoDateTime?=?dateTime.format(DateTimeFormatter.ISO_DATE_TIME);//?using?a?custom?pattern?(01/04/2014) String?asCustomPattern?=?dateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));//?french?date?formatting?(1.?avril?2014) String?frenchDate?=?dateTime.format(DateTimeFormatter.ofPattern("d.?MMMM?yyyy",?new?Locale("fr")));//?using?short?german?date/time?formatting?(01.04.14?10:45) DateTimeFormatter?formatter?=?DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(new?Locale("de")); String?germanDateTime?=?dateTime.format(formatter);//?parsing?date?strings LocalDate?fromIsoDate?=?LocalDate.parse("2014-01-20"); LocalDate?fromIsoWeekDate?=?LocalDate.parse("2014-W14-2",?DateTimeFormatter.ISO_WEEK_DATE); LocalDate?fromCustomPattern?=?LocalDate.parse("20.01.2014",?DateTimeFormatter.ofPattern("dd.MM.yyyy"));轉(zhuǎn)換次數(shù)
當(dāng)然,我們并不總是擁有所需類型的對(duì)象。 因此,我們需要一個(gè)選項(xiàng)來在彼此之間轉(zhuǎn)換不同的日期/時(shí)間相關(guān)對(duì)象。 以下示例顯示了一些可能的轉(zhuǎn)換選項(xiàng):
//?LocalDate/LocalTime?<->?LocalDateTime LocalDate?date?=?LocalDate.now(); LocalTime?time?=?LocalTime.now(); LocalDateTime?dateTimeFromDateAndTime?=?LocalDateTime.of(date,?time); LocalDate?dateFromDateTime?=?LocalDateTime.now().toLocalDate(); LocalTime?timeFromDateTime?=?LocalDateTime.now().toLocalTime();//?Instant?<->?LocalDateTime Instant?instant?=?Instant.now(); LocalDateTime?dateTimeFromInstant?=?LocalDateTime.ofInstant(instant,?ZoneId.of("America/Los_Angeles")); Instant?instantFromDateTime?=?LocalDateTime.now().toInstant(ZoneOffset.ofHours(-2));//?convert old?date/calendar/timezone?classes Instant?instantFromDate?=?new?Date().toInstant(); Instant?instantFromCalendar?=?Calendar.getInstance().toInstant(); ZoneId?zoneId?=?TimeZone.getDefault().toZoneId(); ZonedDateTime?zonedDateTimeFromGregorianCalendar?=?new?GregorianCalendar().toZonedDateTime();// convert to old classes Date?dateFromInstant?=?Date.from(Instant.now()); TimeZone?timeZone?=?TimeZone.getTimeZone(ZoneId.of("America/Los_Angeles")); GregorianCalendar?gregorianCalendar?=?GregorianCalendar.from(ZonedDateTime.now());結(jié)論
使用Java 8,我們可以在java.time包中獲得一個(gè)非常豐富的API,用于處理日期和時(shí)間。 該API可以用更新,更靈活的類完全替換舊的類,如java.util.Date或java.util.Calendar。 由于大多數(shù)類都是不可變的,因此新的API有助于構(gòu)建線程安全的系統(tǒng)。
- 示例的源代碼可以在GitHub上找到 。
翻譯自: https://www.javacodegeeks.com/2014/03/a-deeper-look-into-the-java-8-date-and-time-api.html
總結(jié)
以上是生活随笔為你收集整理的深入了解Java 8日期和时间API的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信上线“腾讯混元助手”小程序 目前仅对
- 下一篇: 消息称小米 14 系列手机双十一之前发布