Java8學(xué)習(xí)筆記之新日期和時間API

1育苟、LocalDate、LocalTime椎木、Instant违柏、Duration、Period
1)使用LocalDate和LocalTime

LocalDate類的實(shí)例是一個不可變對象香椎,它只提供了簡單的日期漱竖,并不含當(dāng)天的時間信息。另外畜伐,它也不附帶任何與時區(qū)相關(guān)的信息馍惹。
可以通過靜態(tài)工廠方法of創(chuàng)建一個LocalDate實(shí)例。LocalDate實(shí)例提供了多種方法來讀取常用的值,比如年份讼积、月份肥照、星期幾等,如下所示勤众。
創(chuàng)建一個LocalDate對象并讀取其值:

LocalDate date = LocalDate.of(2019, 8, 18);//2019-08-18
int year = date.getYear();//2019
Month month = date.getMonth();//AUGUST
int day = date.getDayOfMonth();//18
DayOfWeek dow = date.getDayOfWeek();//SUNDAY
int len = date.lengthOfMonth();//31
boolean leap = date.isLeapYear();//false
LocalDate today = LocalDate.now();//2019-08-13

還可以通過傳遞一個TemporalField參數(shù)給get方法拿到同樣的信息舆绎。TemporalField是一個接口,它定義了如何訪問temporal對象某個字段的值们颜。ChronoField枚舉實(shí)現(xiàn)了這一接口吕朵,所以你可以很方便地使用get方法得到枚舉元素的值,如下所示窥突。
使用TemporalField讀取LocalDate的值:

int year = date.get(ChronoField.YEAR);//2019
int month = date.get(ChronoField.MONTH_OF_YEAR);//08
int day = date.get(ChronoField.DAY_OF_MONTH);//18

一天中的時間努溃,比如10:05:10,可以使用LocalTime類表示阻问∥嗨埃可以使用of重載的兩個工廠方法創(chuàng)建LocalTime的實(shí)例。第一個重載函數(shù)接收小時和分鐘称近,第二個重載函數(shù)同時還 接收秒第队。同LocalDate一樣,LocalTime類也提供了一些getter方法訪問這些變量的值刨秆,如下所示凳谦。
創(chuàng)建LocalTime并讀取其值:

LocalTime time = LocalTime.of(10, 5, 10);//10:05:10
int hour = time.getHour();//10
int minute = time.getMinute();//5
int second = time.getSecond();//10

LocalDate和LocalTime都可以通過解析代表它們的字符串創(chuàng)建。使用靜態(tài)方法parse可以實(shí)現(xiàn):

LocalDate date = LocalDate.parse("2019-08-18");//2019-08-18
LocalTime time = LocalTime.parse("10:05:10");//10:05:10

可以向parse方法傳遞一個DateTimeFormatter衡未。該類的實(shí)例定義了如何格式化一個日期或者時間對象尸执,它是java.util.DateFormat的推薦替代品。
注意:一旦傳遞的字符串參數(shù)無法被解析為合法的LocalDate或LocalTime對象缓醋,這兩個parse方法都會拋出一個繼承自RuntimeException的DateTimeParseException異常如失。

2)合并日期和時間

LocalDateTime:是LocalDate和LocalTime的合體,它同時表示了日期和時間送粱,但不帶有時區(qū)信息褪贵,可以直接創(chuàng)建,也可以通過合并日期和時間對象構(gòu)造葫督,如下所示。

LocalDate date = LocalDate.parse("2019-08-18");//2019-08-18
LocalTime time = LocalTime.parse("10:05:10");//10:05:10
LocalDateTime dt1 = LocalDateTime.of(2019, Month.AUGUST, 18, 10, 05, 10);//2019-08-18T10:05:10
LocalDateTime dt2 = LocalDateTime.of(date, time);//2019-08-18T10:05:10
LocalDateTime dt3 = date.atTime(10, 05, 10);//2019-08-18T10:05:10
LocalDateTime dt4 = date.atTime(time);//2019-08-18T10:05:10
LocalDateTime dt5 = time.atDate(date);//2019-08-18T10:05:10

通過它們各自的atTime或者atDate方法板惑,向LocalDate傳遞一個時間對象橄镜,或者向
LocalTime傳遞一個日期對象的方式,可以創(chuàng)建一個LocalDateTime對象冯乘。也可以用toLocalDate或toLocalTime方法洽胶,從LocalDateTime中提取LocalDate或LocalTime組件:

LocalDate date1 = dt1.toLocalDate();//2019-08-18
LocalTime time1 = dt1.toLocalTime();//10:05:10
3)機(jī)器的日期和時間格式

我們習(xí)慣于以星期幾、幾號、幾點(diǎn)姊氓、幾分這樣的方式理解日期和時間丐怯。但這種方式對于計(jì)算機(jī)而言并不容易理解。從計(jì)算機(jī)的角度來看翔横,建模時間自然的格式是表示一個持續(xù)時間段上某個點(diǎn)的單一大整型數(shù)读跷。這也是新的java.time.Instant類對時間建模的方式,基本上它是以Unix元年時間(傳統(tǒng)的設(shè)定為UTC時區(qū)1970年1月1日午夜時分)開始所經(jīng)歷的秒數(shù)進(jìn)行計(jì)算禾唁。
可以通過向靜態(tài)工廠方法ofEpochSecond傳遞一個代表秒數(shù)的值效览,創(chuàng)建一個該類的實(shí)例。靜態(tài)工廠方法ofEpochSecond還有一個增強(qiáng)的重載版本荡短,它接收第二個以納秒為單位的參數(shù)值丐枉,對傳入作為秒數(shù)的參數(shù)進(jìn)行調(diào)整。重載的版本會調(diào)整納秒?yún)?shù)掘托,確保保存的納秒分片在0到999 999 999之間瘦锹。

Instant.ofEpochSecond(3);
Instant.ofEpochSecond(3, 0);
Instant.ofEpochSecond(2, 1_000_000_000);//2秒之后再加上100萬納秒(1秒) 
Instant.ofEpochSecond(4, -1_000_000_000);//4秒之前的100萬納秒(1秒)

Instant類也支持靜態(tài)工廠方法now,它能獲取當(dāng)前時刻的時間戳闪盔。Instant的設(shè)計(jì)初衷是為了便于機(jī)器使用弯院,它包含的是由秒及納秒所構(gòu)成的數(shù)字。所以锭沟,它無法處理那些我們非常容易理解的時間單位抽兆。

int day = Instant.now().get(ChronoField.DAY_OF_MONTH);

它會拋出下面這樣的異常:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfMonth
4)定義Duration或Period

Temporal接口定義了如何讀取和操縱為時間建模的對象的值∽寤矗可以創(chuàng)建兩個LocalTimes對象辫红、兩個LocalDateTimes對象,或者兩個Instant對象之間的duration祝辣,如下所示:

Duration d1 = Duration.between(time1, time2);
Duration d1 = Duration.between(dateTime1, dateTime2);
Duration d2 = Duration.between(instant1, instant2);

由于LocalDateTime和Instant是為不同的目的而設(shè)計(jì)的贴妻,一個是為了便于人閱讀使用, 另一個是為了便于機(jī)器處理蝙斜,所以不能將二者混用名惩。如果試圖在這兩類對象之間創(chuàng)建duration,會觸發(fā)一個DateTimeException異常孕荠。此外娩鹉,由于Duration類主要用于以秒和納秒衡量時間的長短,不能僅向between方法傳遞一個LocalDate對象做參數(shù)稚伍。
如果需要以年弯予、月或者日的方式對多個時間單位建模,可以使用Period類个曙。使用該類的工廠方法between锈嫩,可以使用得到兩個LocalDate之間的時長,如下所示:

Period tenDays1 = Period.between(LocalDate.of(2019, 8, 10), LocalDate.of(2019, 8, 18));//P8D
Period tenDays2 = Period.between(LocalDate.of(2019, 8, 10), LocalDate.of(2019, 8, 8));//P-2D

Duration和Period類都提供了很多非常方便的工廠類,直接創(chuàng)建對應(yīng)的實(shí)例呼寸;就像下面這段代碼那樣艳汽,不再是只能以兩個temporal對象的差值的方式來定義它們的對象。

Duration threeMinutes1 = Duration.ofMinutes(3);//PT3M
Duration threeMinutes2 = Duration.of(3, ChronoUnit.MINUTES);//PT3M
Period tenDays = Period.ofDays(10);//P10D
Period threeWeeks = Period.ofWeeks(3);//P21D
Period twoYearsSixMonthsOneDay = Period.of(2, 6, 1);//P2Y6M1D
日期-時間類中表示時間間隔的通用方法

日期-時間類中表示時間間隔的通用方法

以上這些日期-時間對象都是不可修改的对雪,這是為了更好地支持函數(shù)式編程河狐,確保線程安全,保持領(lǐng)域模式一致性而做出的重大設(shè)計(jì)決定慌植。當(dāng)然甚牲,新的日期和時間API也提供了一些便利的方法來創(chuàng)建這些對象的可變版本。

2蝶柿、操縱丈钙、解析和格式化日期

如果已經(jīng)有一個LocalDate對象,想要創(chuàng)建它的一個修改版交汤,最直接也最簡單的方法是使用withAttribute方法雏赦。withAttribute方法會創(chuàng)建對象的一個副本,并按照需要修改它的屬性芙扎。

LocalDate date1 = LocalDate.of(2019, 8, 18);//2019-08-18
LocalDate date2 = date1.withYear(2019);//2019-08-18
LocalDate date3 = date2.withDayOfMonth(25);//2019-08-25
LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 9);//2019-09-25

采用更通用的with方法能達(dá)到同樣的目的星岗,它接受的第一個參數(shù)是一個TemporalField對象。 date.with()與date.get()有些類似戒洼,它們都聲明于Temporal接口俏橘,所有的日期和時間API類都實(shí)現(xiàn)這兩個方法,它們定義了單點(diǎn)的時間圈浇,比如LocalDate寥掐、LocalTime、LocalDateTime以及Instant磷蜀。使用get和with方法召耘,我們可以將Temporal對象值的讀取和修改區(qū)分開。如果Temporal對象不支持請求訪問的字段褐隆,它會拋出一個UnsupportedTemporalTypeException異常污它,比如試圖訪問Instant對象的ChronoField.MONTH_OF_YEAR字段,或LocalDate對象的ChronoField.NANO_OF_SECOND字段時都會拋出這樣的異常庶弃。

LocalDate date1 = LocalDate.of(2019, 8, 18);//2019-08-18
LocalDate date2 = date1.plusWeeks(1);//2019-08-25
LocalDate date3 = date2.minusYears(3);//2016-08-25
LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS);//2017-02-25

與get和with方法類似衫贬,plus方法也是通用方法,它和minus方法都聲明于Temporal接口中歇攻。通過這些方法固惯,對TemporalUnit對象加上或者減去一個數(shù)字,我們能非常方便地將Temporal對象前溯或者回滾至某個時間段掉伏,通過ChronoUnit枚舉我們可以非常方便地實(shí)現(xiàn)TemporalUnit接口缝呕。


表示時間點(diǎn)的日期-時間類的通用方法
1)使用TemporalAdjuster

有時需要進(jìn)行一些更加復(fù)雜的操作,比如斧散,將日期調(diào)整到下個周日供常、下個工作日,或是本月的最后一天鸡捐。這時栈暇,可以使用重載版本的with方法,向其傳遞一個提供了更多定制化選擇的TemporalAdjuster對象箍镜,更加靈活地處理日期源祈。對于最常見的用例,日期和時間API已經(jīng)提供了大量預(yù)定義的TemporalAdjuster色迂∠闳保可以通過TemporalAdjuster類的靜態(tài)工廠方法訪問它們,如下所示歇僧。

import static java.time.temporal.TemporalAdjusters.*;
LocalDate date1 = LocalDate.of(2019, 8, 18);//2019-08-18
LocalDate date2 = date1.with(nextOrSame(DayOfWeek.SUNDAY));//2019-08-18
LocalDate date3 = date2.with(lastDayOfMonth());//2019-08-31
TemporalAdjuster類中的工廠方法

使用TemporalAdjuster我們可以進(jìn)行更加復(fù)雜的日期操作图张,方法名基本就是問題陳述。即使沒有找到符合你要求的預(yù)定義的TemporalAdjuster诈悍,創(chuàng)建自己的TemporalAdjuster也并非難事祸轮。實(shí)際上,TemporalAdjuster接口只聲明了單一的一個方法(這使得它成為了一個函數(shù)式接口)侥钳,定義如下适袜。

@FunctionalInterface
public interface TemporalAdjuster {
    Temporal adjustInto(Temporal var1);
}

TemporalAdjuster接口的實(shí)現(xiàn)需要定義如何將一個Temporal對象轉(zhuǎn)換為另一個Temporal對象,可以把它看成一個UnaryOperator<Temporal>舷夺。
示例:設(shè)計(jì)一個NextWorkingDay類苦酱,該類實(shí)現(xiàn)了TemporalAdjuster接口,能夠計(jì)算明天的日期冕房,同時過濾掉周六和周日這些節(jié)假日躏啰。如果當(dāng)天的星期介于周一至周五之間,日期向后移動一天耙册;如果當(dāng)天是周六或者周日给僵,則返回下一個周一。

public class NextWorkingDay implements TemporalAdjuster {
  @Override
  public Temporal adjustInto(Temporal temporal) {
    DayOfWeek dow = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));//讀取當(dāng)前日期 
    int dayToAdd = 1;//正常情況详拙,增加1天 
    if (dow == DayOfWeek.FRIDAY) dayToAdd = 3;//如果當(dāng)天是周五帝际,增加3天 
    else if (dow == DayOfWeek.SATURDAY) dayToAdd = 2;//如果當(dāng)天是周六,增加2天
    return temporal.plus(dayToAdd, ChronoUnit.DAYS);//增加恰當(dāng)?shù)奶鞌?shù)后饶辙,返回修改的日期
  }
}

該TemporalAdjuster通常情況下將日期往后順延一天蹲诀,如果當(dāng)天是周六或者周日,則依據(jù)情況分別將日期順延3天或者2天弃揽。由于TemporalAdjuster是一個函數(shù)式接口脯爪,只能以Lambda表達(dá)式的方式向該adjuster接口傳遞行為:

date = date.with(temporal -> {
   DayOfWeek dow = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
   int dayToAdd = 1;
   if (dow == DayOfWeek.FRIDAY) dayToAdd = 3;
   else if (dow == DayOfWeek.SATURDAY) dayToAdd = 2;
   return temporal.plus(dayToAdd, ChronoUnit.DAYS);
});

如果想使用Lambda表達(dá)式定義TemporalAdjuster對象则北,推薦使用TemporalAdjusters類的靜態(tài)工廠方法ofDateAdjuster,它接受一個UnaryOperator<LocalDate>類型的參數(shù)痕慢,代碼如下:

TemporalAdjuster nextWorkingDay = TemporalAdjusters.ofDateAdjuster(
  temporal -> {
    DayOfWeek dow =DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
    int dayToAdd = 1;
    if (dow == DayOfWeek.FRIDAY) dayToAdd = 3;
    if (dow == DayOfWeek.SATURDAY) dayToAdd = 2;
    return temporal.plus(dayToAdd, ChronoUnit.DAYS);
});
date = date.with(nextWorkingDay);
2)打印輸出及解析日期-時間對象

處理日期和時間對象時尚揣,格式化以及解析日期-時間對象是一個非常重要的功能。新 java.time.format包就是特別為這個目的而設(shè)計(jì)的掖举。這個包中快骗,重要的類是DateTimeFormatter。創(chuàng)建格式器簡單的方法是通過它的靜態(tài)工廠方法以及常量塔次。像BASIC_ISO_DATE和ISO_LOCAL_DATE這樣的常量是DateTimeFormatter類的預(yù)定義實(shí)例方篮。所有的DateTimeFormatter實(shí)例都能用于以一定的格式創(chuàng)建代表特定日期或時間的字符串。

LocalDate date = LocalDate.of(2019, 8, 18);//2019-08-18
String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE);//20190818
String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE);//2019-08-18

也可以通過解析代表日期或時間的字符串重新創(chuàng)建該日期對象励负。所有的日期和時間API都提供了表示時間點(diǎn)或者時間段的工廠方法藕溅,可以使用工廠方法parse實(shí)現(xiàn):

LocalDate date1 = LocalDate.parse("20190818", DateTimeFormatter.BASIC_ISO_DATE);//2019-08-18
LocalDate date2 = LocalDate.parse("2019-08-18", DateTimeFormatter.ISO_LOCAL_DATE);//2019-08-18

和java.util.DateFormat相比,所有的DateTimeFormatter實(shí)例都是線程安全的继榆。你能夠以單例模式創(chuàng)建格式器實(shí)例蜈垮,就像DateTimeFormatter所定義的那些常量,并在多個線程間共享這些實(shí)例裕照。DateTimeFormatter類還支持一個靜態(tài)工廠方法攒发,它可以按照某個特定的模式創(chuàng)建格式器。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date1 = LocalDate.of(2019, 8, 18);//2019-08-18
String formattedDate = date1.format(formatter);//18/08/2019
LocalDate date2 = LocalDate.parse(formattedDate, formatter);//2019-08-18

如果還需要更細(xì)粒度的控制晋南,DateTimeFormatterBuilder類還提供了更復(fù)雜的格式器惠猿。另外,它還提供了非常強(qiáng)大的解析功能负间,比如區(qū)分大小寫的解析偶妖、柔性解析(允許解析器使用啟發(fā)式的機(jī)制去解析輸入,不精確地匹配指定的模式)政溃、填充趾访,以及在格式器中指定可選節(jié)。
構(gòu)造一個DateTimeFormatter:

DateTimeFormatter italianFormatter = new DateTimeFormatterBuilder()
  .appendText(ChronoField.DAY_OF_MONTH)
  .appendLiteral(". ")
  .appendText(ChronoField.MONTH_OF_YEAR)
  .appendLiteral(" ")
  .appendText(ChronoField.YEAR)
  .parseCaseInsensitive()
  .toFormatter(Locale.ITALIAN);
3董虱、處理不同的時區(qū)和歷法

時區(qū)的處理是新版日期和時間API新增加的重要功能扼鞋,使用新版日期和時間API時區(qū)的處理被極大地簡化了。新的java.time.ZoneId類是老版java.util.TimeZone的替代品愤诱。它的設(shè)計(jì)目標(biāo)就是要讓你無需為時區(qū)處理的復(fù)雜和繁瑣而操心云头,比如處理日光時(Daylight Saving Time,DST)這種問題淫半。跟其他日期和時間類一樣溃槐,ZoneId類也是無法修改的。
時區(qū)是按照一定規(guī)則將區(qū)域劃分成的標(biāo)準(zhǔn)時間相同的區(qū)間科吭。在ZoneRules這個類中包含了40個這樣的實(shí)例昏滴。你可以簡單地通過調(diào)用ZoneId的getRules()得到指定時區(qū)的規(guī)則猴鲫。每個特定的ZoneId對象都由一個地區(qū)ID標(biāo)識,比如:
ZoneId romeZone = ZoneId.of("Europe/Rome");
地區(qū)ID都為“{區(qū)域}/{城市}”的格式谣殊,這些地區(qū)集合的設(shè)定都由英特網(wǎng)編號分配機(jī)構(gòu)(IANA)的時區(qū)數(shù)據(jù)庫提供变隔。可以通過Java 8的新方法toZoneId將一個老的時區(qū)對象轉(zhuǎn)換為ZoneId:ZoneId zoneId = TimeZone.getDefault().toZoneId();
一旦得到一個ZoneId對象蟹倾,就可以將它與LocalDate、LocalDateTime或Instant對象整合起來猖闪,構(gòu)造一個ZonedDateTime實(shí)例鲜棠,它代表了相對于指定時區(qū)的時間點(diǎn)。

LocalDate date = LocalDate.of(2019, Month.AUGUST, 13);//2019-08-13
ZoneId zone = ZoneId.of("Asia/Shanghai");//Asia/Shanghai
ZonedDateTime zdt1 = date.atStartOfDay(zone);//2019-08-13T00:00+08:00[Asia/Shanghai]
LocalDateTime dateTime = LocalDateTime.of(2019, Month.AUGUST, 13, 10, 15);//2019-08-13T10:15
ZonedDateTime zdt2 = dateTime.atZone(zone);//2019-08-13T10:15+08:00[Asia/Shanghai]
Instant instant = Instant.now();//2019-08-13T03:20:05.177Z
ZonedDateTime zdt3 = instant.atZone(zone);//2019-08-13T11:20:05.177+08:00[Asia/Shanghai]

通過ZoneId培慌,還可以將LocalDateTime轉(zhuǎn)換為Instant:

LocalDateTime dateTime = LocalDateTime.of(2019, Month.AUGUST, 13, 10, 45);//2019-08-13T10:45
Instant instantFromDateTime = dateTime.atZone(zone).toInstant();//2019-08-13T02:45:00Z

也可以通過反向的方式得到LocalDateTime對象:

Instant instant = Instant.now();//2019-08-13T06:33:38.711Z
LocalDateTime timeFromInstant = LocalDateTime.ofInstant(instant, zone);//22019-08-13T14:33:38.711
1)利用和UTC/格林尼治時間的固定偏差計(jì)算時區(qū)

一種比較通用的表達(dá)時區(qū)的方式是利用當(dāng)前時區(qū)和UTC/格林尼治的固定偏差豁陆。這種情況下,可以使用ZoneOffset類吵护,它是ZoneId的一個子類盒音,表示當(dāng)前時間和倫敦格林尼治子午線時間的差異:
ZoneOffset newYorkOffset = ZoneOffset.of("-05:00");
“-05:00”的偏差實(shí)際上對應(yīng)的是美國東部標(biāo)準(zhǔn)時間。注意:使用這種方式定義的ZoneOffset并未考慮任何日光時的影響馅而,所以在大多數(shù)情況下祥诽,不推薦使用∥凸В可以創(chuàng)建這樣的OffsetDateTime雄坪,它使用ISO-8601的歷法系統(tǒng),以相對于UTC/格林尼治時間的偏差方式表示日期時間屯蹦。

ZoneOffset newYorkOffset = ZoneOffset.of("-05:00");//-05:00
LocalDateTime dateTime = LocalDateTime.of(2019, Month.AUGUST, 18, 10, 15);//2019-08-18T10:15
OffsetDateTime dateTimeInNewYork = OffsetDateTime.of(dateTime, newYorkOffset);//2019-08-18T10:15-05:00
2)使用別的日歷系統(tǒng)

ISO-8601日歷系統(tǒng)是世界文明日歷系統(tǒng)的事實(shí)標(biāo)準(zhǔn)维哈。但Java 8中另外還提供了4種其他的日歷系統(tǒng)。這些日歷系統(tǒng)中的每個都有一個對應(yīng)的日志類登澜,分別是ThaiBuddhistDate阔挠、 MinguoDate、JapaneseDate以及HijrahDate脑蠕。這些類及LocalDate都實(shí)現(xiàn)了ChronoLocalDate接口购撼,能夠?qū)珰v的日期進(jìn)行建模。利用LocalDate對象谴仙,可以創(chuàng)建這些類的實(shí)例份招。使用它們提供的靜態(tài)工廠方法,可以創(chuàng)建任何一個Temporal對象的實(shí)例狞甚,如下所示:

LocalDate date = LocalDate.of(2019, Month.AUGUST, 18);//2019-08-18
JapaneseDate japaneseDate = JapaneseDate.from(date);//Japanese Heisei 31-08-18

還可以為某個Locale顯式地創(chuàng)建日歷系統(tǒng)锁摔,接著創(chuàng)建該Locale對應(yīng)的日期實(shí)例。新的日期和時間API中哼审,Chronology接口建模了一個日歷系統(tǒng)谐腰,使用它的靜態(tài)工廠方法ofLocale孕豹,可以得到它的一個實(shí)例,代碼如下:

Chronology japaneseChronology = Chronology.ofLocale(Locale.JAPAN);//ISO
ChronoLocalDate now = japaneseChronology.dateNow();//2019-08-13

日期及時間API的設(shè)計(jì)者建議我們使用LocalDate十气,盡量避免使用ChronoLocalDate励背,原因是開發(fā)者在他們的代碼中可能會做一些假設(shè),而這些假設(shè)在不同的日歷系統(tǒng)中砸西,有可能不成立叶眉。盡量在應(yīng)用中使用LocalDate,包括存儲芹枷、操作衅疙、業(yè)務(wù)規(guī)則的解讀;如果需要將程序的輸入或者輸出本地化鸳慈,這時應(yīng)該使用 ChronoLocalDate類饱溢。
伊斯蘭教日歷
在Java 8新添加的幾種日歷類型中,HijrahDate(伊斯蘭教日歷)是復(fù)雜一個走芋,因?yàn)樗鼤l(fā)生各種變化绩郎。Hijrah日歷系統(tǒng)構(gòu)建于農(nóng)歷月份繼承之上。Java 8提供了多種方法判斷一個月份翁逞,比如新月肋杖,在世界的哪些地方可見,或者說它只能首先可見于沙特阿拉伯挖函。withVariant方法可以用于選擇期望的變化兽愤。為了支持HijrahDate這一標(biāo)準(zhǔn),Java 8中還包括了烏姆庫拉(Umm Al-Qura)變量挪圾。
示例:在ISO日歷中計(jì)算當(dāng)前伊斯蘭年中齋月的起始和終止日期

HijrahDate ramadanDate = HijrahDate.now()
    .with(ChronoField.DAY_OF_MONTH, 1)
    .with(ChronoField.MONTH_OF_YEAR, 9);//取得當(dāng)前的Hijrah日期浅萧,接著對其進(jìn) 行修正,得到齋月的第一天哲思,即第9個月洼畅。輸出:Hijrah-umalqura AH 1440-09-01
System.out.println("Ramadan starts on "+IsoChronology.INSTANCE.date(ramadanDate)+" and ends on "
+IsoChronology.INSTANCE.date(ramadanDate.with(TemporalAdjusters.lastDayOfMonth())));//Ramadan starts on 2019-05-06 and ends on 2019-06-03

--參考文獻(xiàn)《Java8實(shí)戰(zhàn)》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市棚赔,隨后出現(xiàn)的幾起案子帝簇,更是在濱河造成了極大的恐慌,老刑警劉巖靠益,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丧肴,死亡現(xiàn)場離奇詭異,居然都是意外死亡胧后,警方通過查閱死者的電腦和手機(jī)芋浮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來壳快,“玉大人纸巷,你說我怎么就攤上這事镇草。” “怎么了瘤旨?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵梯啤,是天一觀的道長。 經(jīng)常有香客問我存哲,道長因宇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任祟偷,我火速辦了婚禮察滑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘肩袍。我一直安慰自己,他們只是感情好婚惫,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布氛赐。 她就那樣靜靜地躺著,像睡著了一般先舷。 火紅的嫁衣襯著肌膚如雪艰管。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天蒋川,我揣著相機(jī)與錄音牲芋,去河邊找鬼。 笑死捺球,一個胖子當(dāng)著我的面吹牛缸浦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播氮兵,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼裂逐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了泣栈?” 一聲冷哼從身側(cè)響起卜高,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎南片,沒想到半個月后掺涛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疼进,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年薪缆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伞广。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡矮燎,死狀恐怖定血,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情诞外,我是刑警寧澤澜沟,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站峡谊,受9級特大地震影響茫虽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜既们,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一濒析、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧啥纸,春花似錦号杏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至荣暮,卻和暖如春庭惜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背穗酥。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工护赊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人砾跃。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓骏啰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親抽高。 傳聞我的和親對象是個殘疾皇子器一,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容