摘要:類似地,一天中的時(shí)間,比如,可以使用類表示。合并日期和時(shí)間這個(gè)復(fù)合類名叫,是和的合體。對(duì)于最常見的用例,日期和時(shí)間已經(jīng)提供了大量預(yù)定義的。你甚至還可以創(chuàng)建這樣的,它使用的歷法系統(tǒng),以相對(duì)于格林尼治時(shí)間的偏差方式表示日期時(shí)間。
一、LocalDate、LocalTime、Instant、Duration 以及 Period 1.使用 LocalDate 和 LocalTime
創(chuàng)建一個(gè)LocalDate對(duì)象并讀取其值
LocalDate date = LocalDate.of(2014, 3, 18); //2014-03-18 int year = date.getYear(); //2014 Month month = date.getMonth();//MARCH int day = date.getDayOfMonth();//18 DayOfWeek dow = date.getDayOfWeek();//TUESDAY int len = date.lengthOfMonth();//31 boolean leap = date.isLeapYear();//false
你還可以通過傳遞一個(gè)TemporalField參數(shù)給get方法拿到同樣的信息。TemporalField是一個(gè)接口,它定義了如何訪問temporal對(duì)象某個(gè)字段的值。ChronoField枚舉實(shí)現(xiàn)了這一接口,所以你可以很方便地使用get方法得到枚舉元素的值,如下所示。
使用TemporalField讀取LocalDate的值
int year = date.get(ChronoField.YEAR); int month = date.get(ChronoField.MONTH_OF_YEAR); int day = date.get(ChronoField.DAY_OF_MONTH);
類似地,一天中的時(shí)間,比如13:45:20,可以使用LocalTime類表示。類似地,一天中的時(shí)間,比如13:45:20,可以使用LocalTime類表示。
LocalTime time = LocalTime.of(13, 45, 20); int hour = time.getHour(); int minute = time.getMinute(); int second = time.getSecond();
LocalDate和LocalTime都可以通過解析代表它們的字符串創(chuàng)建。使用靜態(tài)方法parse,你可以實(shí)現(xiàn)這一目的:
LocalDate date = LocalDate.parse("2014-03-18"); LocalTime time = LocalTime.parse("13:45:20");
你可以向parse方法傳遞一個(gè)DateTimeFormatter。它是替換老版java.util.DateFormat的推薦替代品。2.合并日期和時(shí)間
這個(gè)復(fù)合類名叫LocalDateTime,是LocalDate和LocalTime的合體。它同時(shí)表示了日期和時(shí)間,但不帶有時(shí)區(qū)信息,你可以直接創(chuàng)建,也可以通過合并日期和時(shí)間對(duì)象構(gòu)造,如下所示。
直接創(chuàng)建LocalDateTime對(duì)象,或者通過合并日期和時(shí)間的方式創(chuàng)建
// 2014-03-18T13:45:20 LocalDateTime dt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20); LocalDateTime dt2 = LocalDateTime.of(date, time); LocalDateTime dt3 = date.atTime(13, 45, 20); LocalDateTime dt4 = date.atTime(time); LocalDateTime dt5 = time.atDate(date);
注意,通過它們各自的atTime或者atDate方法,向LocalDate傳遞一個(gè)時(shí)間對(duì)象,或者向LocalTime傳遞一個(gè)日期對(duì)象的方式,你可以創(chuàng)建一個(gè)LocalDateTime對(duì)象。你也可以使用toLocalDate或者toLocalTime方法,從LocalDateTime中提取LocalDate或者LocalTime組件:
LocalDate date1 = dt1.toLocalDate(); LocalTime time1 = dt1.toLocalTime();3.機(jī)器的日期和時(shí)間格式
新的java.time.Instant類對(duì)時(shí)間建模的方式,基本上它是以Unix元年時(shí)間(傳統(tǒng)的設(shè)定為UTC時(shí)區(qū)1970年1月1日午夜時(shí)分)開始所經(jīng)歷的
秒數(shù)進(jìn)行計(jì)算。你可以通過向靜態(tài)工廠方法ofEpochSecond傳遞一個(gè)代表秒數(shù)的值創(chuàng)建一個(gè)該類的實(shí)例。靜態(tài)工廠方法ofEpochSecond還有一個(gè)增強(qiáng)的重載版本,它接收第二個(gè)以納秒為單位的參數(shù)值,對(duì)傳入作為秒數(shù)的參數(shù)進(jìn)行調(diào)整。重載的版本會(huì)調(diào)整納秒?yún)?shù),確保保存的納秒分片在0到999 999 999之間。這意味著下面這些對(duì)ofEpochSecond工廠方法的調(diào)用會(huì)返回幾乎同樣的Instant對(duì)象:
Instant.ofEpochSecond(3); Instant.ofEpochSecond(3, 0); Instant.ofEpochSecond(2, 1_000_000_000); Instant.ofEpochSecond(4, -1_000_000_000);
從Java7開始,你就可以在你的Java代碼里把長(zhǎng)整型數(shù)字比如10000000000寫成一個(gè)更具可讀性10_000_000_000。
Instant類也支持靜態(tài)工廠方法now,它能夠幫你獲取當(dāng)前時(shí)刻的時(shí)間戳。它包含的是由秒及納秒所構(gòu)成的數(shù)字。所以,它無法處理那些我們非常容易理解的時(shí)間單位。比如下面這段語句:
int day = Instant.now().get(ChronoField.DAY_OF_MONTH);
它會(huì)拋出下面這樣的異常:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfMonth4.定義 Duration 或 Period
你可以創(chuàng)建兩個(gè)LocalTimes對(duì)象、兩個(gè)LocalDateTimes對(duì)象,或者兩個(gè)Instant對(duì)象之間的duration( 持續(xù)期間),如下所示:
Duration d1 = Duration.between(time1, time2); Duration d1 = Duration.between(dateTime1, dateTime2); Duration d2 = Duration.between(instant1, instant2);
如果你試圖在這兩類對(duì)象之間創(chuàng)建duration,會(huì)觸發(fā)一個(gè)DateTimeException異常。此外,由于Duration類主要用于以秒和納秒衡量時(shí)間的長(zhǎng)短,你不能僅向between方法傳遞一個(gè)LocalDate對(duì)象做參數(shù)。
如果你需要以年、月或者日的方式對(duì)多個(gè)時(shí)間單位建模,可以使用Period類。使用該類的工廠方法between,你可以使用得到兩個(gè)LocalDate之間的時(shí)長(zhǎng),如下所示:
Period tenDays = Period.between(LocalDate.of(2014, 3, 8), LocalDate.of(2014, 3, 18));
Duration和Period類都提供了很多非常方便的工廠類,直接創(chuàng)建對(duì)應(yīng)的實(shí)例;不再是只能以兩個(gè)temporal對(duì)象的差值的方式來定義它們的對(duì)象。
創(chuàng)建Duration和Period對(duì)象
Duration threeMinutes = Duration.ofMinutes(3); Duration threeMinutes = Duration.of(3, ChronoUnit.MINUTES); Period tenDays = Period.ofDays(10); Period threeWeeks = Period.ofWeeks(3); Period twoYearsSixMonthsOneDay = Period.of(2, 6, 1);
日期/時(shí)間類中表示時(shí)間間隔的通用方法
Temporal接口的實(shí)現(xiàn)類:二、操縱、解析和格式化日期
HijrahDate, Instant, JapaneseDate, LocalDate, LocalDateTime, LocalTime, MinguoDate, OffsetDateTime, OffsetTime, ThaiBuddhistDate, Year, YearMonth, ZonedDateTime
如果你已經(jīng)有一個(gè)LocalDate對(duì)象,想要?jiǎng)?chuàng)建它的一個(gè)修改版,最直接也最簡(jiǎn)單的方法是使用withAttribute方法。withAttribute方法會(huì)創(chuàng)建對(duì)象的一個(gè)副本,并按照需要修改它的屬性。注意,下面的這段代碼中所有的方法都返回一個(gè)修改了屬性的對(duì)象。它們都不會(huì)修改原來的對(duì)象!
LocalDate date1 = LocalDate.of(2014, 3, 18); LocalDate date2 = date1.withYear(2011); LocalDate date3 = date2.withDayOfMonth(25); LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 9);
采用更通用的with方法能達(dá)到同樣的目的,它接受的第一個(gè)參數(shù)是一個(gè)TemporalField對(duì)象,格式類似上面代碼最后一行。更確切地說,使用get和with方法,我們可以將Temporal對(duì)象值的讀取和修改區(qū)分開。如果Temporal對(duì)象不支持請(qǐng)求訪問的字段,它會(huì)拋出一個(gè)UnsupportedTemporalTypeException異常。
以相對(duì)方式修改LocalDate對(duì)象的屬性:
LocalDate date1 = LocalDate.of(2014, 3, 18); LocalDate date2 = date1.plusWeeks(1); LocalDate date3 = date2.minusYears(3); LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS);
像LocalDate、LocalTime、LocalDateTime以及Instant這樣表示時(shí)間點(diǎn)的日期?時(shí)間類提供了大量通用的方法
有的時(shí)候,你需要進(jìn)行一些更加復(fù)雜的操作,比如,將日期調(diào)整到下個(gè)周日、下個(gè)工作日,或者是本月的最后一天。這時(shí),你可以使用重載版本的with方法,向其傳遞一個(gè)提供了更多定制化選擇的TemporalAdjuster對(duì)象,更加靈活地處理日期。對(duì)于最常見的用例,日期和時(shí)間API已經(jīng)提供了大量預(yù)定義的TemporalAdjuster。你可以通過TemporalAdjuster類的靜態(tài)工廠方法訪問它們。
使用預(yù)定義的TemporalAdjuster
import static java.time.temporal.TemporalAdjusters.*; LocalDate date1 = LocalDate.of(2014, 3, 18); LocalDate date2 = date1.with(nextOrSame(DayOfWeek.SUNDAY)); //2014-03-23 LocalDate date3 = date2.with(lastDayOfMonth());//2014-03-31
TemporalAdjuster類中的工廠方法
TemporalAdjuster接口
@FunctionalInterface public interface TemporalAdjuster { Temporal adjustInto(Temporal temporal); }
如果你想要使用Lambda表達(dá)式定義TemporalAdjuster對(duì)象,推薦使用TemporalAdjusters類的靜態(tài)工廠方法ofDateAdjuster,它接受一個(gè)UnaryOperator
新的java.time.format包就是特別為這個(gè)目的而設(shè)計(jì)的。這個(gè)包中,最重要的類是DateTimeFormatter。創(chuàng)建格式器最簡(jiǎn)單的方法是通過它的靜態(tài)工廠方法以及常量。像BASIC_ISO_DATE和 ISO_LOCAL_DATE 這樣的常量是 DateTimeFormatter 類的預(yù)定義實(shí)例。
LocalDate date = LocalDate.of(2014, 3, 18); String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE); //20140318 String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE);//2014-03-18
你可以使用工廠方法parse達(dá)到重創(chuàng)該日期對(duì)象的目的:
LocalDate date1 = LocalDate.parse("20140318", DateTimeFormatter.BASIC_ISO_DATE); LocalDate date2 = LocalDate.parse("2014-03-18", DateTimeFormatter.ISO_LOCAL_DATE);
和老的java.util.DateFormat相比較,所有的DateTimeFormatter實(shí)例都是線程安全的。
按照某個(gè)模式創(chuàng)建DateTimeFormatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); LocalDate date1 = LocalDate.of(2014, 3, 18); String formattedDate = date1.format(formatter); LocalDate date2 = LocalDate.parse(formattedDate, formatter);
創(chuàng)建一個(gè)本地化的DateTimeFormatter
DateTimeFormatter italianFormatter = DateTimeFormatter.ofPattern("d. MMMM yyyy", Locale.ITALIAN); LocalDate date1 = LocalDate.of(2014, 3, 18); String formattedDate = date.format(italianFormatter); // 18. marzo 2014 LocalDate date2 = LocalDate.parse(formattedDate, italianFormatter);
DateTimeFormatterBuilder類還提供了更復(fù)雜的格式器,你可以通過DateTimeFormatterBuilder自己編程實(shí)現(xiàn)我們?cè)谏厦娲a使用的italianFormatter,代碼清單如下。
DateTimeFormatter italianFormatter = new DateTimeFormatterBuilder() .appendText(ChronoField.DAY_OF_MONTH) .appendLiteral(". ") .appendText(ChronoField.MONTH_OF_YEAR) .appendLiteral(" ") .appendText(ChronoField.YEAR) .parseCaseInsensitive() .toFormatter(Locale.ITALIAN);三、處理不同的時(shí)區(qū)和歷法
新的java.time.ZoneId類是老版java.util.TimeZone的替代品。跟其他日期和時(shí)間類一樣,ZoneId類也是無法修改的。時(shí)區(qū)是按照一定的規(guī)則將區(qū)域劃分成的標(biāo)準(zhǔn)時(shí)間相同的區(qū)間。在ZoneRules這個(gè)類中包含了40個(gè)這樣的實(shí)例。你可以簡(jiǎn)單地通過調(diào)用ZoneId的getRules()得到指定時(shí)區(qū)的規(guī)則。每個(gè)特定的ZoneId對(duì)象都由一個(gè)地區(qū)ID標(biāo)識(shí),比如:
ZoneId romeZone = ZoneId.of("Europe/Rome");
地區(qū)ID都為“{區(qū)域}/{城市}”的格式,你可以通過Java 8的新方法toZoneId將一個(gè)老的時(shí)區(qū)對(duì)象轉(zhuǎn)換為ZoneId:
ZoneId zoneId = TimeZone.getDefault().toZoneId();
為時(shí)間點(diǎn)添加時(shí)區(qū)信息
LocalDate date = LocalDate.of(2014, Month.MARCH, 18); ZonedDateTime zdt1 = date.atStartOfDay(romeZone); LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45); ZonedDateTime zdt2 = dateTime.atZone(romeZone); Instant instant = Instant.now(); ZonedDateTime zdt3 = instant.atZone(romeZone);
通過ZoneId,你還可以將LocalDateTime轉(zhuǎn)換為Instant:
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45); Instant instantFromDateTime = dateTime.toInstant(romeZone);
你也可以通過反向的方式得到LocalDateTime對(duì)象:
Instant instant = Instant.now(); LocalDateTime timeFromInstant = LocalDateTime.ofInstant(instant, romeZone);1.利用和 UTC/格林尼治時(shí)間的固定偏差計(jì)算時(shí)區(qū)
ZoneOffset類,它是ZoneId的一個(gè)子類,表示的是當(dāng)前時(shí)間和倫敦格林尼治子午線時(shí)間的差異:
ZoneOffset newYorkOffset = ZoneOffset.of("-05:00");
注意,使用這種方式定義的ZoneOffset并未考慮任何日光時(shí)的影響,所以在大多數(shù)情況下,不推薦使用。ZoneOffset也是ZoneId。
你甚至還可以創(chuàng)建這樣的OffsetDateTime,它使用ISO-8601的歷法系統(tǒng),以相對(duì)于UTC/格林尼治時(shí)間的偏差方式表示日期時(shí)間。
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45); OffsetDateTime dateTimeInNewYork = OffsetDateTime.of(date, newYorkOffset)2.使用別的日歷系統(tǒng)
Java 8中另外還提供了4種其他的日歷系統(tǒng)。這些日歷系統(tǒng)中的每一個(gè)都有一個(gè)對(duì)應(yīng)的日志類,分別是ThaiBuddhistDate、MinguoDate 、 JapaneseDate 以及HijrahDate 。所有這些類以及 LocalDate 都實(shí)現(xiàn)了ChronoLocalDate接口。
如下所示:
LocalDate date = LocalDate.of(2014, Month.MARCH, 18); JapaneseDate japaneseDate = JapaneseDate.from(date);
或者,你還可以為某個(gè)Locale顯式地創(chuàng)建日歷系統(tǒng),接著創(chuàng)建該Locale對(duì)應(yīng)的日期的實(shí)例。新的日期和時(shí)間API中,Chronology接口建模了一個(gè)日歷系統(tǒng),使用它的靜態(tài)工廠方法ofLocale,可以得到它的一個(gè)實(shí)例,代碼如下:
Chronology japaneseChronology = Chronology.ofLocale(Locale.JAPAN); ChronoLocalDate now = japaneseChronology.dateNow();
日期及時(shí)間API的設(shè)計(jì)者建議我們使用LocalDate,盡量避免使用ChronoLocalDate,原因是開發(fā)者在他們的代碼中可能會(huì)做一些假設(shè),而這些假設(shè)在不同的日歷系統(tǒng)中,有可能不成立。比如,有人可能會(huì)做這樣的假設(shè),即一個(gè)月天數(shù)不會(huì)超過31天,一年包括12個(gè)月,或者一年中包
含的月份數(shù)目是固定的。由于這些原因,我們建議你盡量在你的應(yīng)用中使用LocalDate,包括存儲(chǔ)、操作、業(yè)務(wù)規(guī)則的解讀;不過如果你需要將程序的輸入或者輸出本地化,這時(shí)你應(yīng)該使用ChronoLocalDate類。
伊斯蘭教日歷
在Java 8新添加的幾種日歷類型中,HijrahDate(伊斯蘭教日歷)是最復(fù)雜一個(gè),因?yàn)樗鼤?huì)發(fā)生各種變化。Hijrah日歷系統(tǒng)構(gòu)建于農(nóng)歷月份繼承之上。Java 8提供了多種方法判斷一個(gè)月份,比如新月,在世界的哪些地方可見,或者說它只能首先可見于沙特阿拉伯。withVariant方法可以用于選擇期望的變化。為了支持HijrahDate這一標(biāo)準(zhǔn),Java 8中還包括了烏姆庫拉(Umm Al-Qura)變量。
下面這段代碼作為一個(gè)例子說明了如何在ISO日歷中計(jì)算當(dāng)前伊斯蘭年中齋月的起始和終止日期:
HijrahDate ramadanDate = HijrahDate.now().with(ChronoField.DAY_OF_MONTH, 1) .with(ChronoField.MONTH_OF_YEAR, 9); System.out.println("Ramadan starts on " + IsoChronology.INSTANCE.date(ramadanDate) + " and ends on " + IsoChronology.INSTANCE.date( ramadanDate.with( TemporalAdjusters.lastDayOfMonth())));
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/74429.html
摘要:實(shí)戰(zhàn)讀書筆記第一章從方法傳遞到接著上次的,繼續(xù)來了解一下,如果繼續(xù)簡(jiǎn)化代碼。去掉并且生成的數(shù)字是萬,所消耗的時(shí)間循序流并行流至于為什么有時(shí)候并行流效率比循序流還低,這個(gè)以后的文章會(huì)解釋。 《Java8實(shí)戰(zhàn)》-讀書筆記第一章(02) 從方法傳遞到Lambda 接著上次的Predicate,繼續(xù)來了解一下,如果繼續(xù)簡(jiǎn)化代碼。 把方法作為值來傳遞雖然很有用,但是要是有很多類似與isHeavy...
摘要:類或父類中聲明的方法的優(yōu)先級(jí)高于任何聲明為默認(rèn)方法的優(yōu)先級(jí)。只有聲明了一個(gè)默認(rèn)方法。由于比更加具體,所以編譯器會(huì)選擇中聲明的默認(rèn)方法。 如果在現(xiàn)存的接口上引入了非常多的新方法,所有的實(shí)現(xiàn)類都必須進(jìn)行改造,實(shí)現(xiàn)新方法,為了解決這個(gè)問題,Java 8為了解決這一問題引入了一種新的機(jī)制。Java 8中的接口現(xiàn)在支持在聲明方法的同時(shí)提供實(shí)現(xiàn),這聽起來讓人驚訝!通過兩種方式可以完成這種操作。其一...
摘要:第四章引入流一什么是流流是的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合通過查詢語句來表達(dá),而不是臨時(shí)編寫一個(gè)實(shí)現(xiàn)。 第四章 引入流 一、什么是流 流是Java API的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合(通過查詢語句來表達(dá),而不是臨時(shí)編寫一個(gè)實(shí)現(xiàn))。就現(xiàn)在來說,你可以把它們看成遍歷數(shù)據(jù)集的高級(jí)迭代器。此外,流還可以透明地并行處理,你無需寫任何多線程代碼。 下面兩段代碼都是用來返回低...
摘要:前言前面一篇文章寫了如何安全的使用里面介紹了如何處理日期時(shí)間,以及如何保證線程安全,及其介紹了在中的處理時(shí)間日期默認(rèn)就線程安全的類。引入了全新的日期時(shí)間格式工具,線程安全而且使用方便。 前言 前面一篇文章寫了《SimpleDateFormat 如何安全的使用?》, 里面介紹了 SimpleDateFormat 如何處理日期/時(shí)間,以及如何保證線程安全,及其介紹了在 Java 8 中的處...
摘要:內(nèi)部迭代與使用迭代器顯式迭代的集合不同,流的迭代操作是在背后進(jìn)行的。流只能遍歷一次請(qǐng)注意,和迭代器類似,流只能遍歷一次。 流(Stream) 流是什么 流是Java API的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合(通過查詢語句來表達(dá),而不是臨時(shí)編寫一個(gè)實(shí)現(xiàn))。就現(xiàn)在來說,你可以把它們看成遍歷數(shù)據(jù)集的高級(jí)迭代器。此外,流還可以透明地并行處理,你無需寫任何多線程代碼了!我會(huì)在后面的筆記中...
摘要:但返回的是一個(gè)類型的對(duì)象,這意味著操作的結(jié)果是一個(gè)類型的對(duì)象。反之,如果對(duì)象存在,這次調(diào)用就會(huì)將其作為函數(shù)的輸入,并按照與方法的約定返回一個(gè)對(duì)象。 一、Optional 類入門 Java 8中引入了一個(gè)新的類java.util.Optional。變量存在時(shí),Optional類只是對(duì)類簡(jiǎn)單封裝。變量不存在時(shí),缺失的值會(huì)被建模成一個(gè)空的Optional對(duì)象,由方法Optional.empt...
閱讀 4116·2023-04-26 02:07
閱讀 3742·2021-10-27 14:14
閱讀 2965·2021-10-14 09:49
閱讀 1686·2019-08-30 15:43
閱讀 2696·2019-08-29 18:33
閱讀 2432·2019-08-29 17:01
閱讀 976·2019-08-29 15:11
閱讀 678·2019-08-29 11:06