<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    LetsCoding.cn

    天地之間有桿秤,拿秤砣砸老百姓。

    Java 8:健壯、易用的時(shí)間/日期API終于來臨

    對(duì)很多應(yīng)用來說,時(shí)間和日期的概念都是必須的。像生日,租賃期,事件的時(shí)間戳和商店?duì)I業(yè)時(shí)長(zhǎng),等等,都是基于時(shí)間和日期的;然而,Java卻沒有好的API來處理它們。在Java SE 8中,添加了一個(gè)新包:java.time,它提供了結(jié)構(gòu)良好的API來處理時(shí)間和日期。

    歷史

    在Java剛剛發(fā)布,也就是版本1.0的時(shí)候,對(duì)時(shí)間和日期僅有的支持就是java.util.Date類。大多數(shù)開發(fā)者對(duì)它的第一印象就是,它根本不代表一個(gè)“日期”。實(shí)際上,它只是簡(jiǎn)單的表示一個(gè),從1970-01-01Z開始計(jì)時(shí)的,精確到毫秒的瞬時(shí)點(diǎn)。由于標(biāo)準(zhǔn)的toString()方法,按照J(rèn)VM的默認(rèn)時(shí)區(qū)輸出時(shí)間和日期,有些開發(fā)人員把它誤認(rèn)為是時(shí)區(qū)敏感的。

    在升級(jí)Java到1.1期間,Date類被認(rèn)為是無法修復(fù)的。由于這個(gè)原因,java.util.Calendar類被添加了進(jìn)來。悲劇的是,Calendar類并不比java.util.Date好多少。它們面臨的部分問題是:

    • 可變性。像時(shí)間和日期這樣的類應(yīng)該是不可變的。
    • 偏移性。Date中的年份是從1900開始的,而月份都是從0開始的。
    • 命名。Date不是“日期”,而Calendar也不真實(shí)“日歷”。
    • 格式化。格式化只對(duì)Date有用,Calendar則不行。另外,它也不是線程安全的。

    大約在2001年,Joda-Time項(xiàng)目開始了。它的目的很簡(jiǎn)單,就是給Java提供一個(gè)高質(zhì)量的時(shí)間和日期類庫。盡管被耽擱了一段時(shí)間,它的1.0版還是被發(fā)布。很快,它就成為了廣泛使用和流行的類庫。隨著時(shí)間的推移,有越來越多的需求,要在JDK中擁有一個(gè)像Joda-Time的這樣類庫。在來自巴西的Michael Nascimento Santos的幫助下,官方為JDK開發(fā)新的時(shí)間/日期API的進(jìn)程:JSR-310,啟動(dòng)了。

    綜述

    新的API:java.time,由5個(gè)包組成:

    大多數(shù)開發(fā)者只會(huì)用到基礎(chǔ)和format包,也可能會(huì)用到temporal包。因此,盡管有68個(gè)新的公開類型,大多數(shù)開發(fā)者,大概,將只會(huì)用到其中的三分之一。

    日期

    在新的API中,LocalDate是其中最重要的類之一。它是表示日期的不可變類型,不包含時(shí)間和時(shí)區(qū)。

    “本地”,這個(gè)術(shù)語,我們對(duì)它的熟悉來自于Joda-Time。它原本出自ISO-8061的時(shí)間和日期標(biāo)準(zhǔn),它和時(shí)區(qū)無關(guān)。實(shí)際上,本地日期只是日期的描述,例如“2014年4月5日”。特定的本地時(shí)間,因你在地球上的不同位置,開始于不同的時(shí)間線。所以,澳大利亞的本地時(shí)間開始的比倫敦早10小時(shí),比舊金山早18小時(shí)。

    LocalDate被設(shè)計(jì)成,它的所有方法,都是常用方法:

    1. LocalDate date = LocalDate.of(2014, Month.JUNE10);
    2. int year = date.getYear(); // 2014
    3. Month month = date.getMonth(); // 6月
    4. int dom = date.getDayOfMonth(); // 10
    5. DayOfWeek dow = date.getDayOfWeek(); // 星期二
    6. int len = date.lengthOfMonth(); // 30 (6月份的天數(shù))
    7. boolean leap = date.isLeapYear(); // false (不是閏年)

    在上面的例子中,我們看到日期使用工廠方法(所有的構(gòu)造方法都是私有的)創(chuàng)建。然后用它查詢了部分基本信息。注意:枚舉類型,MonthDayOfWeek,被設(shè)計(jì)用來增強(qiáng)代碼的可讀性和可靠性。

    在下面的例子中,我們來看看如何操作LocalDate的實(shí)例。由于它是不可變類型,每次操作都會(huì)產(chǎn)生一個(gè)新的實(shí)例,而原有實(shí)例不收任何影響。

    1. LocalDate date = LocalDate.of(2014, Month.JUNE10);
    2. date = date.withYear(2015); // 2015-06-10
    3. date = date.plusMonths(2); // 2015-08-10
    4. date = date.minusDays(1); // 2015-08-09

    上面這些都很簡(jiǎn)單,但有時(shí)我們需要對(duì)日期進(jìn)行更復(fù)雜的修改。java.time包含了對(duì)此的處理機(jī)制:TemporalAdjuster類。時(shí)間修改器背后的設(shè)計(jì)思想是,提供一個(gè)預(yù)裝包的、能操縱日期的功能,比如,根據(jù)月份的最后一天獲取日期的對(duì)象。API提供了一些通用的功能,你可以新增你自己的。修改器的使用很簡(jiǎn)單,但使用靜態(tài)導(dǎo)入的方式,會(huì)讓你更方便:

    1. import static java.time.DayOfWeek.*
    2. import static java.time.temporal.TemporalAdjusters.*
    3.  
    4. LocalDate date = LocalDate.of(2014, Month.JUNE10);
    5. date = date.with(lastDayOfMonth());
    6. date = date.with(nextOrSame(WEDNESDAY));

    java.time包中,像所有主要的時(shí)間/日期類一樣,LocalDate類是固定于單個(gè)歷法系統(tǒng)的:ISO-8601標(biāo)準(zhǔn)定義的歷法。
    看見修改器的瞬間反應(yīng)就是,這代碼跟業(yè)務(wù)邏輯長(zhǎng)的差不多啊!這對(duì)時(shí)間/日期類業(yè)務(wù)邏輯是很重的。我們最后想看的是多次手動(dòng)修改日期。如果你的代碼庫里,有一個(gè)將會(huì)使用很多次的,對(duì)日期的通用操作,考慮把它做成修改器,然后告訴你的小組成員,把它當(dāng)做一個(gè)寫好的,測(cè)試過的組件,直接拿來用吧。

    時(shí)間/日期值對(duì)象

    值得花點(diǎn)時(shí)間弄清楚,是什么導(dǎo)致了LocalDate類成為值類型。值類型是這樣一種簡(jiǎn)單的數(shù)據(jù)類型:2個(gè)實(shí)例,只要內(nèi)容相同,就該是可以相互替換的,是不是同一個(gè)實(shí)例,并不重要。String類就是一個(gè)標(biāo)準(zhǔn)的值類型的例子,只要字面值一樣,我們就認(rèn)為它們相等,而不關(guān)心它們是不是同一個(gè)String對(duì)象的不同引用。

    大部分時(shí)間/日期類都應(yīng)該是值類型的,java.time開發(fā)包印證了這一點(diǎn)。因此,我們沒有理由去用==來判斷2個(gè)LocalDate是不是相等,實(shí)際上,Javadoc也反對(duì)這樣做。

    對(duì)于值類型,想要更多了解的同學(xué),可以參考我最近的文章,VALJOs:在Java中,它對(duì)值類型,定義了嚴(yán)格的規(guī)則集合,包括不可變性、工廠方法和良好定義的equals()hashCode()toString()compareTo()方法。

    不同的歷法系統(tǒng)

    java.time包中,像所有主要的時(shí)間/日期類一樣,LocalDate是固定于單個(gè)歷法系統(tǒng)的:由ISO-8601標(biāo)準(zhǔn)定義。

    ISO-8601歷法系統(tǒng)是事實(shí)上的世界民用歷法系統(tǒng),也就是公歷。平年有365天,閏年是366天。閏年的定義是:非世紀(jì)年,能被4整除;世紀(jì)年能被400整除。為了計(jì)算的一致性,公元1年的前一年被當(dāng)做公元0年,以此類推。

    采用這套歷法,第一個(gè)影響就是,ISO-8601的日期不必跟GregorianCalendar一致。在GregorianCalendar中,凱撒歷格里高利歷之間有一個(gè)轉(zhuǎn)換日,一般默認(rèn)在1582年10月15日。那天之前,用凱撒歷:每4年一個(gè)閏年,沒有例外。那天之后,用格里高利歷,也就是公歷,擁有稍微復(fù)雜點(diǎn)的閏年計(jì)算方式。

    既然凱撒歷和格里高利歷之間的轉(zhuǎn)換是個(gè)歷史事實(shí),那為什么新的java.time開發(fā)包不參照它呢?原因就是,現(xiàn)在使用歷史日期的大部分Java應(yīng)用程序,都是不正確的,繼續(xù)下去,是個(gè)錯(cuò)誤。這是為什么呢?當(dāng)年,羅馬的梵蒂岡,把歷法從凱撒歷改換成格里高利歷的時(shí)候,世界上大部分其他地區(qū)并沒有更換歷法。比如大英帝國,包括早期的美國,直到大約200后的1752年9月14日才換歷法,沙俄直到1918年2月14日,而瑞典的歷法轉(zhuǎn)換更是一團(tuán)糟。因此,實(shí)際上,對(duì)1918之前的日期,解釋是相當(dāng)多的;僅相信擁有單一轉(zhuǎn)換日的GregorianCalendar,是不靠譜的。LocalDate中沒有這種轉(zhuǎn)換,就是一個(gè)合理的選擇了。應(yīng)用程序需要額外的上下文信息,在凱撒歷和格里高利歷間,精確的解釋特定的歷史日期。

    第二個(gè)影響是,我們需要額外的一組類來幫助處理其他歷法系統(tǒng)。Chronology接口,是其他歷法的主要入口點(diǎn),它允許通過所屬的語言環(huán)境查找對(duì)應(yīng)的歷法系統(tǒng)。Java 8支持額外的4個(gè)歷法系統(tǒng):泰國佛教歷,中華民國歷,日本歷(沿襲中國古代帝位紀(jì)年),伊斯蘭歷。如有需要,應(yīng)用程序也可以實(shí)現(xiàn)自己的歷法系統(tǒng)。

    每個(gè)歷法系統(tǒng)都有自己的日期類,有ThaiBuddhistDateMinguoDateJapaneseDateHijrahDate。它們應(yīng)在對(duì)本地化有嚴(yán)重需求的應(yīng)用中使用,比如為日本政府開發(fā)的系統(tǒng)。它們4個(gè)都繼承了另外一個(gè)接口,ChronoLocalDate,可以讓代碼在不知道歷法系統(tǒng)的情況下,去操作它們。雖然如此,但還是希望少用這個(gè)接口。

    理解為什么少用ChronoLocalDate,對(duì)正確的使用整個(gè)java.time開發(fā)包很關(guān)鍵。真實(shí)情況是,當(dāng)我們檢視當(dāng)前的應(yīng)用,盡量以歷法無關(guān)的方式來操作日期的大部分代碼,都有問題。例如,你不能假定一年有12個(gè)月,而開發(fā)者都是這樣認(rèn)為的,并且增加12個(gè)月,他們就認(rèn)為是增加了一年。你不能認(rèn)為所有的月份都有相同的天數(shù),比如,科普特人的歷法,包括12個(gè)30天的月份,還有一個(gè)月僅有5天,或者6天。你也不能認(rèn)為,下一年的年份就比現(xiàn)在的年份大了1年,比如日本歷,在天皇換代時(shí),會(huì)重新紀(jì)年,此時(shí),還在那一年的年中(你甚至不能認(rèn)為在同一個(gè)月的兩天,是屬于同一年的)。

    在一個(gè)大型的系統(tǒng)中,唯一的以歷法無關(guān)的方式開發(fā)的方法是:形成嚴(yán)格的代碼審查制度,對(duì)日期和時(shí)間相關(guān)的每行代碼都要做雙重檢查,以防偏向ISO歷法系統(tǒng)。因此,推薦的做法是,在系統(tǒng)中,全部使用LocalDate,包括存儲(chǔ),操作和解釋業(yè)務(wù)規(guī)則。僅有的,使用ChronoLocalDate的時(shí)候是,本地化的輸入/輸出,典型的做法是使用用戶配置中首選的歷法;即使如此,大多數(shù)應(yīng)用并不需要那樣的本地化級(jí)別。

    如需更全面的了解,查看ChronoLocalDate的Javadoc

    時(shí)間

    日期之后,下一個(gè)考慮的概念就是本地時(shí)間,LocalTime。典型的例子就是便利店的營業(yè)時(shí)間,例如從07:00到23:00(早上7點(diǎn)到晚上11點(diǎn))。可能,在這個(gè)時(shí)間段營業(yè)的便利店,遍布整個(gè)美利堅(jiān),但是這個(gè)時(shí)間是本地化的,跟時(shí)區(qū)無關(guān)。

    LocalTime是值類型,且跟日期和時(shí)區(qū)沒有關(guān)聯(lián)。當(dāng)我們對(duì)時(shí)間進(jìn)行加減操作時(shí),以午夜基準(zhǔn),24小時(shí)一個(gè)周期。因此,20:00加上6小時(shí),結(jié)果就是02:00。

    LocalTime的用法跟LocalDate相似:

    1. LocalTime time = LocalTime.of(2030);
    2. int hour = date.getHour(); // 20
    3. int minute = date.getMinute(); // 30
    4. time = time.withSecond(6); // 20:30:06
    5. time = time.plusMinutes(3); // 20:33:06

    修改器機(jī)制同樣適用于LocalTime,只是對(duì)它的復(fù)雜操作比較少。

    時(shí)間和日期組合

    下一個(gè)要考察的是LocalDateTime類。這個(gè)值類型只是LocalDateLocalTime的簡(jiǎn)單組合。它表示一個(gè)跟時(shí)區(qū)無關(guān)的日期和時(shí)間。

    LocalDateTime可以直接創(chuàng)建,或者組合時(shí)間和日期:

    1. LocalDateTime dt1 = LocalDateTime.of(2014, Month.JUNE102030);
    2. LocalDateTime dt2 = LocalDateTime.of(date, time);
    3. LocalDateTime dt3 = date.atTime(2030);
    4. LocalDateTime dt4 = date.atTime(time);

    第三和第四行使用atTime()方法,平滑地構(gòu)造一個(gè)LocalDateTime實(shí)例。大部分的時(shí)間和日期類都有“at“方法:以這樣的方式,把當(dāng)前對(duì)象和其他對(duì)象組合,生成更復(fù)雜的對(duì)象。

    LocalDateTime的其他方法跟LocalDateLocalTime相似。這種相似的方法模式非常有利于API的學(xué)習(xí)。下面總結(jié)了用到的方法前綴:

    • of: 靜態(tài)工廠方法,從組成部分中創(chuàng)建實(shí)例
    • from: 靜態(tài)工廠方法,嘗試從相似對(duì)象中提取實(shí)例。from()方法沒有of()方法類型安全
    • now: 靜態(tài)工廠方法,用當(dāng)前時(shí)間創(chuàng)建實(shí)例
    • parse: 靜態(tài)工廠方法,總字符串解析得到對(duì)象實(shí)例
    • get: 獲取時(shí)間日期對(duì)象的部分狀態(tài)
    • is: 檢查關(guān)于時(shí)間日期對(duì)象的描述是否正確
    • with: 返回一個(gè)部分狀態(tài)改變了的時(shí)間日期對(duì)象拷貝
    • plus: 返回一個(gè)時(shí)間增加了的、時(shí)間日期對(duì)象拷貝
    • minus: 返回一個(gè)時(shí)間減少了的、時(shí)間日期對(duì)象拷貝
    • to: 把當(dāng)前時(shí)間日期對(duì)象轉(zhuǎn)換成另外一個(gè),可能會(huì)損失部分狀態(tài)
    • at: 用當(dāng)前時(shí)間日期對(duì)象組合另外一個(gè),創(chuàng)建一個(gè)更大或更復(fù)雜的時(shí)間日期對(duì)象
    • format: 提供格式化時(shí)間日期對(duì)象的能力

    時(shí)間點(diǎn)

    在處理時(shí)間和日期的時(shí)候,我們通常會(huì)想到年,月,日,時(shí),分,秒。然而,這只是時(shí)間的一個(gè)模型,是面向人類的。第二種通用模型是面向機(jī)器的,或者說是連續(xù)的。在此模型中,時(shí)間線中的一個(gè)點(diǎn)表示為一個(gè)很大的數(shù)。這有利于計(jì)算機(jī)處理。在UNIX中,這個(gè)數(shù)從1970年開始,以秒為的單位;同樣的,在Java中,也是從1970年開始,但以毫秒為單位。

    java.time包通過值類型Instant提供機(jī)器視圖。Instant表示時(shí)間線上的一點(diǎn),而不需要任何上下文信息,例如,時(shí)區(qū)。概念上講,它只是簡(jiǎn)單的表示自1970年1月1日0時(shí)0分0秒(UTC)開始的秒數(shù)。因?yàn)?strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">java.time包是基于納秒計(jì)算的,所以Instant的精度可以達(dá)到納秒級(jí)。

    1. Instant start = Instant.now();
    2. // perform some calculation
    3. Instant end = Instant.now();
    4. assert end.isAfter(start);

    Instant典型的用法是,當(dāng)你需要記錄事件的發(fā)生時(shí)間,而不需要記錄任何有關(guān)時(shí)區(qū)信息時(shí),存儲(chǔ)和比較時(shí)間戳。它額很多有趣的地方在于,你不能對(duì)它做什么,而不是你能做什么。例如,下面的幾行代碼會(huì)拋出異常:

    1. instant.get(ChronoField.MONTH_OF_YEAR);
    2. instant.plus(6, ChronoUnit.YEARS);

    拋出這些異常是因?yàn)椋?strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Instant只包含秒數(shù)和納秒數(shù),不提供處理人類意義上的時(shí)間單位。如果確實(shí)有需要,你需要額外提供時(shí)區(qū)信息。

    時(shí)區(qū)

    時(shí)區(qū)的概念由大英帝國開始采用。鐵路的發(fā)明和通訊工具的改進(jìn),突然意味著人們的活動(dòng)范圍,大到跟太陽時(shí)的改變有很大的關(guān)系。在此之前,每個(gè)城鎮(zhèn)和村莊,都通過太陽和日晷規(guī)定自己的時(shí)間。

    下面的英國布魯斯托交易所的時(shí)鐘照片,顯示了時(shí)區(qū)導(dǎo)致的最初混亂的一個(gè)例子。紅色的指針顯示格林威治時(shí)間,而黑色指針顯示布魯斯托時(shí)間,它們相差10分鐘。

    在技術(shù)的推動(dòng)下,標(biāo)準(zhǔn)的時(shí)區(qū)系統(tǒng)慢慢演進(jìn),最終替代了老舊的本地太陽法計(jì)時(shí)。然而,關(guān)鍵的事實(shí)是,時(shí)區(qū)也是政治的產(chǎn)物。它們被用來顯示對(duì)一個(gè)地區(qū)的政治控制,例如,最近的克里米亞時(shí)改為莫斯科時(shí)。一旦和政治掛鉤,相關(guān)的規(guī)則常常不合邏輯。

    時(shí)區(qū)規(guī)則,由一個(gè)發(fā)布IANA時(shí)區(qū)數(shù)據(jù)庫的國際組織搜集和匯總。這些數(shù)據(jù),包含地球上每個(gè)地區(qū)的標(biāo)識(shí)和時(shí)區(qū)的歷史變化。標(biāo)識(shí)的格式類似”歐洲/倫敦“,或者”美洲/紐約“。

    java.time之前,我們用TimeZone表示時(shí)區(qū),而現(xiàn)在,用ZoneId。它們有2個(gè)主要的不同。第一,ZoneId是不可變的,它里面保存時(shí)區(qū)縮寫的靜態(tài)變量也是不可變的;第二,實(shí)際的規(guī)則集在ZoneRules里,不在ZoneId中,通過getRules()方法可以獲得。

    時(shí)區(qū)的常見情況,是從UTC/格林威治開始的一個(gè)固定偏移。我們通常在說時(shí)差的時(shí)候,會(huì)遇到它,例如,我們說紐約比倫敦晚5個(gè)小時(shí)。ZoneId的子類,ZoneOffset,代表了這種從倫敦格林威治零度子午線開始的時(shí)間偏移。

    作為一個(gè)開發(fā)者,如果不用去處理時(shí)區(qū)和它帶來的復(fù)雜性,將會(huì)是非常棒的。java.time開發(fā)包盡最大努力的幫助你那樣做。只要有可能,盡量使用LocalDateLocalTimeLocalDateInstant。當(dāng)你不能回避時(shí)區(qū)時(shí),ZonedDateTime可以滿足你的需求。

    ZoneDateTime負(fù)責(zé)處理面向人類的(臺(tái)歷和掛鐘上看到的)時(shí)間和面向機(jī)器的時(shí)間(始終連續(xù)增長(zhǎng)的秒數(shù))之間的轉(zhuǎn)換。因此,你可以通過本地時(shí)間或時(shí)間點(diǎn)來創(chuàng)建ZoneDateTime實(shí)例:

    1. ZoneId zone = ZoneId.of("Europe/Paris");
    2.  
    3. LocalDate date = LocalDate.of(2014, Month.JUNE10);
    4. ZonedDateTime zdt1 = date.atStartOfDay(zone);
    5.  
    6. Instant instant = Instant.now();
    7. ZonedDateTime zdt2 = instant.atZone(zone);

    最惱人的時(shí)區(qū)問題之一就是夏令時(shí)。在夏令時(shí)中,從格林威治的偏移每年要調(diào)整兩次(也許更多);典型的做法是,春天調(diào)快時(shí)間,秋天再調(diào)回來。夏令時(shí)開始時(shí),我們都需要手動(dòng)調(diào)整家里的掛鐘時(shí)間。這些調(diào)整,在java.time包中,叫偏移過渡。春天時(shí),跟本地時(shí)間相比,缺了一段時(shí)間;相反,秋天時(shí),有的時(shí)間會(huì)出現(xiàn)兩次。

    ZonedDateTime在它的工廠方法和控制方法中處理了這些。例如,在夏令時(shí)切換的那天,增加一天會(huì)增加邏輯上的一天:可能多于24小時(shí),也可能少于24小時(shí)。同樣的,方法atStartOfDay()之所以這樣命名,是因?yàn)槟悴荒芗俣ㄋ奶幚斫Y(jié)果就一定是午夜零點(diǎn),夏令時(shí)開始的那天,一天是從午夜1點(diǎn)開始的。

    下面是關(guān)于夏令時(shí)的最后一個(gè)小提示。如果你想證明,在夏令時(shí)結(jié)束那天的重疊時(shí)段,你有考慮過什么情況會(huì)發(fā)生,你可以用這兩個(gè)專門處理重疊時(shí)段的方法之一:

    1. zdt = zdt.withEarlierOffsetAtOverlap();
    2. zdt = zdt.withLaterOffsetAtOverlap();

    處于時(shí)間重疊時(shí)段時(shí),使用這兩個(gè)方法之一,你可以得到調(diào)整之前或調(diào)整之后的時(shí)間。在其他情況下,這兩個(gè)方法是無效的。

    時(shí)間長(zhǎng)度

    到目前為止,我們討論的時(shí)間/日期類以多種不同的方式表示時(shí)間線上的一個(gè)點(diǎn)。java.time還為時(shí)間長(zhǎng)度額外提供了兩個(gè)值類型。

    Duration表示以秒和納秒為基準(zhǔn)的時(shí)長(zhǎng)。例如,“23.6秒”。

    Period表示以年、月、日衡量的時(shí)長(zhǎng)。例如,“3年2個(gè)月零6天”。

    它們可以作為參數(shù),傳給主要的時(shí)間/日期類的增加或減少時(shí)間的方法:

    1. Period sixMonths = Period.ofMonths(6);
    2. LocalDate date = LocalDate.now();
    3. LocalDate future = date.plus(sixMonths);

    解析和格式化

    java.time.format包是專門用來格式化輸出時(shí)間/日期的。這個(gè)包圍繞DateTimeFormatter類和它的輔助創(chuàng)建類DateTimeFormatterBuilder展開。

    靜態(tài)方法加上DateTimeFormatter中的常量,是最通用的創(chuàng)建格式化器的方式。包括:

    • 常用ISO格式常量,如ISO_LOCAL_DATE
    • 字母模式,如ofPattern(“dd/MM/uuuu”)
    • 本地化樣式,如ofLocalizedDate(FormatStyle.MEDIUM)

    很典型的,一旦有了格式化器,你可以把它傳遞給主要的時(shí)間/日期類的相關(guān)方法:

    1. DateTimeFormatter f = DateTimeFormatter.ofPattern("dd/MM/uuuu");
    2. LocalDate date = LocalDate.parse("24/06/2014", f);
    3. String str = date.format(f);

    這把你從格式化器自己的格式化和解析方法中隔離開來。

    如果你想控制格式化的語言環(huán)境,調(diào)用格式化器的withLocale(Locale)方法。相似的方式可以允許你控制格式化的歷法系統(tǒng)、時(shí)區(qū)、十進(jìn)制數(shù)和解析度。

    如果你需要更多的控制權(quán),查看DateTimeFormatterBuilder類吧,它允許你一步一步的構(gòu)造更復(fù)雜的格式化器。它還提供大小寫不敏感的解析,松散的解析,字符填充和可選的格式。

    總結(jié)

    Java 8中的java.time是一個(gè)新的、復(fù)雜的時(shí)間/日期API。它把Joda-Time中的設(shè)計(jì)思想和實(shí)現(xiàn)推向了更高的層次,讓開發(fā)人員把java.util.DateCalendar拋在了身后。是時(shí)候重新享受時(shí)間/日期編程的樂趣了。

    本文譯自:Intuitive, Robust Date and Time Handling, Finally Comes to Java

    原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明: 轉(zhuǎn)載自Let’sCoding.cn
    本文鏈接地址: Java 8:健壯、易用的時(shí)間/日期API終于來臨

    posted on 2014-04-29 11:30 Rolandz 閱讀(11699) 評(píng)論(2)  編輯  收藏

    評(píng)論

    # re: Java 8:健壯、易用的時(shí)間/日期API終于來臨 2014-11-21 16:48 劉敏

    hello world   回復(fù)  更多評(píng)論   

    # re: Java 8:健壯、易用的時(shí)間/日期API終于來臨[未登錄] 2015-02-25 10:15 Michael

    很給力!  回復(fù)  更多評(píng)論   


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     

    導(dǎo)航

    統(tǒng)計(jì)

    留言簿(1)

    隨筆分類(12)

    隨筆檔案(19)

    積分與排名

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲日本久久一区二区va| 久久久久亚洲AV成人无码| 亚洲乱码国产一区网址| 亚洲日韩小电影在线观看| 亚洲色av性色在线观无码| 亚洲性色精品一区二区在线| 免费看内射乌克兰女| 全黄大全大色全免费大片| 91九色视频无限观看免费| 国产免费观看青青草原网站| 三上悠亚亚洲一区高清| 亚洲高清资源在线观看| 亚洲风情亚Aⅴ在线发布| 91福利免费网站在线观看| 国产免费不卡视频| 免费一级毛片清高播放| 亚洲韩国—中文字幕| 亚洲国产精品无码第一区二区三区| 亚洲国产免费综合| 亚洲免费福利在线视频| 亚洲美女在线国产| 亚洲综合久久成人69| 国产成人综合亚洲绿色| 久久久久久一品道精品免费看 | 国产精品极品美女自在线观看免费 | 国产免费久久精品99久久| 57pao国产成视频免费播放| 美女黄网站人色视频免费国产| 亚洲自偷自偷图片| 天天爽亚洲中文字幕| 成人片黄网站色大片免费观看cn| 中字幕视频在线永久在线观看免费| 亚洲高清视频一视频二视频三| 久久精品国产亚洲AV香蕉| 色老头综合免费视频| 亚洲视频免费在线看| 国产亚洲精品成人a v小说| 狠狠色伊人亚洲综合网站色| 国产自国产自愉自愉免费24区| 免费高清在线影片一区| 久久久久亚洲AV成人无码|