溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何使用Java時間操作類庫Joda-Time

發(fā)布時間:2021-10-18 10:52:38 來源:億速云 閱讀:113 作者:iii 欄目:web開發(fā)

本篇內(nèi)容主要講解“如何使用Java時間操作類庫Joda-Time”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“如何使用Java時間操作類庫Joda-Time”吧!

一、JDK8以前版本中的時間類庫

1.1 原始時間類庫存在的缺陷與不足

我們在使用Java8之前的類庫時,都會在處理日期-時間的時候總是不爽,這其中包括且不限于以下的槽點:

在Java 1.0版本中,對時間、日期的操作完全依賴于 java.util.Data 類,只能以毫秒的精度表示時間,無法表示日期。

  • 在易用性方面有著很大的缺陷,年份的起始時間選擇是1900年,月份是從0開始。

  • toString 方法返回值不直觀,帶有時區(qū)。

在Java1.1 版本中,廢棄了很多Date 類中的很多方法,并且新增了 java.util.Calendar。但是與Date相同,Calendar  類也有類似的問題和設(shè)計缺陷,導(dǎo)致在使用這些類寫出的代碼也很容易出錯。

  • 月份依然是從0開始計算。

  • 常用的日期、時間操作需要同時使用Date、Canendar、SimpleDateFormat,比較繁瑣。

  • 部分特性只存在于某一個類(解析和格式化日期或時間的DateFormat方法只存在于Date類中)。

  • DateFormat 不是線程安全的,如果兩個線程嘗試使用同一個formatter 解析日期,可能會得到無法預(yù)期的結(jié)果。

  • Date 和 Canendar 都是可變的。

1.2 關(guān)于SimpleDateFormat 線程不安全的原因

由于 parse 方法使用的貢獻(xiàn)變量 calendar 不是線程安全的。在 format (subFormat) 方法中進(jìn)行了 calendar  的賦值,在 parse 進(jìn)行了值得處理,因此在并發(fā)的情況下會造成 calendar 清理不及時,值被覆蓋的情況。

/**  * The {@link Calendar} instance used for calculating the date-time fields  * and the instant of time. This field is used for both formatting and  * parsing.  *    * <p>Subclasses should initialize this field to a {@link Calendar}  * appropriate for the {@link Locale} associated with this  * <code>DateFormat</code>.  * @serial  */ protected Calendar calendar;  @Override public StringBuffer format(Date date, StringBuffer toAppendTo,                            FieldPosition pos){     pos.beginIndex = pos.endIndex = 0;     return format(date, toAppendTo, pos.getFieldDelegate()); }  // Called from Format after creating a FieldDelegate private StringBuffer format(Date date, StringBuffer toAppendTo,                             FieldDelegate delegate) {     // Convert input date to time field list     calendar.setTime(date);   // At this point the fields of Calendar have been set.  Calendar  // will fill in default values for missing fields when the time  // is computed.   pos.index = start;   Date parsedDate;  try {         parsedDate = calb.establish(calendar).getTime();         // If the year value is ambiguous,         // then the two-digit year == the default start year         if (ambiguousYear[0]) {             if (parsedDate.before(defaultCenturyStart)) {                 parsedDate = calb.addYear(100).establish(calendar).getTime();             }         }  } }

1.3 如何解決上述線程不安全問題?

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 使用ThreadLocal 為每個線程都創(chuàng)建一個線程獨享 SimpleDateFormat 變量;

  3. 需要的時候創(chuàng)建局部變量;

  4. 使用 org.apacle.commons.lang3.time.DateFormatUtils

  5. 使用Joda-Time (后面介紹)

二、Joda-Time 日期時間類庫

2.1 簡介

Joda-Time 是Joda提供的一個遵循Apache2.0 開源協(xié)議的 JDK以外的優(yōu)質(zhì)日期和時間開發(fā)庫。

Joda除Joda-Time之外的項目有Joda-Money、Joda-Beans、Joda-Convert、Joda-Collect Joda官網(wǎng)

2.1.1 為什么使用Joda-Time

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 使用方便:Calendar 訪問“正常的”日期困難,并且缺乏簡單的防腐,Joda-Time 擁有簡單的字段訪問,比如獲得年的 getYear() 和  獲得星期 中的天 getDayOfWeek() 。

  3. 易于擴展:JDK支持通過使用子類實現(xiàn)多個日歷系統(tǒng),但是這是非常笨重的,并且在實現(xiàn)中很難選出另一個日歷系統(tǒng)。Joda-Time 支持基于  Chronology 類實現(xiàn)多個可插拔的日歷系統(tǒng)。

  4. 功能全面:Joda-Time 提供了所有的日期和時間計算的必須功能,它提供了即裝即用的特性。

  5. 最新的時區(qū)計算:時區(qū)的實現(xiàn)基于公共時區(qū)信息數(shù)據(jù)庫,每年更新數(shù)次。新版本的Joda-Time  包括了這個數(shù)據(jù)庫的所有更改,應(yīng)盡早進(jìn)行必要的更新,手動更新區(qū)域數(shù)據(jù)很容易。

  6. 日歷支持:提供了8種日歷系統(tǒng)。

  7. 互通性:內(nèi)部使用毫秒進(jìn)行標(biāo)識,這與JDK或者其他公共的時間表示相一致。

  8. 性能良好:支持針對所有訪問的域進(jìn)行最小的計算。

  9. 良好的測試覆蓋率:有全方位的測試人員保證庫的質(zhì)量、

  10. 具有完整文檔:有一個完整的用戶指南,該指南提供了一個概述,涵蓋常見的使用場景。javadoc 非常詳細(xì),涵蓋API的其余部分。

  11. 發(fā)展:自2002年以來積極發(fā)展,是一個成熟的可靠的代碼庫,一些相關(guān)的項目目前也是可用的。

  12. 開源:遵循Apache 2.0開源協(xié)議發(fā)布。

2.1.2 Joda-Time 的關(guān)鍵優(yōu)點

  1. LocalDate:只包含日期

  2. LocalTime:只包含時間

  3. Instant:時間軸上的時間點

  4. DateTime:時區(qū)中完整的日期和時間

  5. DateTimeZone:更好的時區(qū)

  6. Duration和Period:持續(xù)時間

  7. Interval:兩個時間點之間的時間

  8. 全面并且靈活的時間格式化與轉(zhuǎn)換

正因為Joda-Time 與 Java8 之前的時間類庫相比,具備了如此多的優(yōu)點,所以 Joda-Time  成為事實上的標(biāo)準(zhǔn)的Java日期和時間庫。

2.2 特性解讀

2.2.1 Joda-Time和JDK的互操作性

互操作性是指:Joda 類能夠生成 java.util.Date  的實例(以及Calendar),這可以讓我們保留現(xiàn)有對JDK的依賴,又能夠使用Joda處理復(fù)雜的日期/時間計算。

Date To Joda-Time

Date date = new Date(); DateTime dateTime = new DateTime(date);

Canendar To Joda-Time

Calendar calendar = Calendar.getInstance(); DateTime dateTime = new DateTime(calendar);

Joda-Time To Date

Date date = new Date();   DateTime dateTime = new DateTime(date);                        Date date2 = dateTime.toDate();

Joda-Time To Calendar

Calendar calendar = Calendar.getInstance();   dateTime = new DateTime(calendar);   Calendar calendar2 = dateTime.toCalendar(Locale.CHINA);

2.2.2 Joda的關(guān)鍵日期/時間概念理解

Joda 使用了以下概念,使得它們可以應(yīng)用到任何日期/時間庫:

不可變性(Immutability)

Joda-Time與java.lang.String類似,它們的實例均無法修改(因為任意對其值改變的操作都會生成新的對象),這也代表了它們是線程安全的。

瞬時性(Instant)

如接口 org.joda.time.ReadableInstant 中所表示的那樣,Instant 表示的是一個精確的時間點,是從  epoch:1970-01-01T00:00:00Z 開始計算的毫秒數(shù),這也的設(shè)計也使得其子類都可以與JDK Date 以及 Calendar 類兼容。

/**  * Defines an instant in the datetime continuum.  * This interface expresses the datetime as milliseconds from 1970-01-01T00:00:00Z.  * <p>  * The implementation of this interface may be mutable or immutable.  * This interface only gives access to retrieve data, never to change it.  * <p>  * Methods in your application should be defined using <code>ReadableInstant</code>  * as a parameter if the method only wants to read the instant without needing to know  * the specific datetime fields.  * <p>  * The {@code compareTo} method is no longer defined in this class in version 2.0.  * Instead, the definition is simply inherited from the {@code Comparable} interface.  * This approach is necessary to preserve binary compatibility.  * The definition of the comparison is ascending order by millisecond instant.  * Implementors are recommended to extend {@code AbstractInstant} instead of this interface.  *  * @author Stephen Colebourne  * @since 1.0  */ public interface ReadableInstant extends Comparable<ReadableInstant> {      /**      * Get the value as the number of milliseconds since      * the epoch, 1970-01-01T00:00:00Z.      *      * @return the value as milliseconds      */     long getMillis();                        &middot;&middot;&middot;&middot;&middot;&middot; }

局部性(Partial)

瞬時性表達(dá)的是與epoch相對的時間上的一個精確時刻,而一個局部時間指的是一個時間的一部分片段,其可以通過一些方法使得時間產(chǎn)生變動(本質(zhì)上還是生成了新的類),這樣可以把它當(dāng)做重復(fù)周期中的一點,用到多個地方。

年表(Chronology)

Joda-Time的設(shè)計核心就是年表(org.joda.time.Chronology),從根本上將,年表是一種日歷系統(tǒng),是一種計算時間的特殊方式,并且在其中執(zhí)行日歷算法的框架。Joda-Time支持的8種年表如下所示:

  • ISO(默認(rèn)) - org.joda.time.chrono.ISOChronology

  • GJ - org.joda.time.chrono.GJChronology

  • Gregorian - org.joda.time.chrono.GregorianChronology

  • Julian - org.joda.time.chrono.JulianChronology

  • Coptic - org.joda.time.chrono.CopticChronology

  • Buddhist - org.joda.time.chrono.BuddhistChronology

  • Ethiopic - org.joda.time.chrono.EthiopicChronology

  • Islamic - org.joda.time.chrono.IslamicChronology

以上的每一種年表都可以作為特定日歷系統(tǒng)的計算引擎,是可插拔的實現(xiàn)。

時區(qū)(Time zone)

具體定義詳見百科解釋,在實際編碼過程中任何嚴(yán)格的時間計算都必須涉及時區(qū)(或者相對于GMT),Joda-Time中對應(yīng)的核心類為org.joda.time.DateTimeZone,雖然日常的使用過程中,并未涉及到對時區(qū)的操作,但是DateTimeZone如何對DateTime產(chǎn)生影響是比較值得注意的,此處不進(jìn)行贅述。

2.3 具體使用方法

上面介紹我完了Joda-Time的一些概念,接下來具體使用我們來進(jìn)行說明:

2.3.1 創(chuàng)建 Joda-Time 對象

瞬時性-ReadableInstant

// 1.使用系統(tǒng)時間 DateTime dateTime1 = new DateTime(); // 2.使用jdk中的date Date jdkDate1 = new Date(); DateTime dateTime2 = new DateTime(jdkDate1); // 3.使用毫秒數(shù)指定 Date jdkDate2 = new Date(); long millis = jdkDate.getTime(); DateTime dateTime3 = new DateTime(millis); // 4.使用Calendar Calendar calendar = Calendar.getInstance(); DateTime dateTime4 = new DateTime(calendar); // 5.使用多個字段指定一個瞬間時刻(局部時間片段) // year month day hour(midnight is zero) minute second milliseconds DateTime dateTime5 = new DateTime(2000, 1, 1, 0, 0, 0, 0); // 6.由一個DateTime生成另一個DateTime DateTime dateTime6 = new DateTime(dateTime1); // 7.有時間字符串生成DateTime String timeString = "2019-01-01T00:00:00-06:00"; DateTime dateTime7 = DateTime.parse(timeString);

局部性-ReadablePartial

當(dāng)程序中處理的日期、時間并不需要是完整時刻的時候,可以創(chuàng)建一個局部時間,比如只希望專注于年/月/日,  或者一天中的時間,或者是一周中的某天。Joda-Time中有表示這些時間的是org.joda.time.ReadablePartial接口,實現(xiàn)它的兩個類LocalDate和LocalTime是分別用來表示年/月/日和一天中的某個時間的。

// 顯示地提供所含的每個字段 LocalDate localDate = new LocalDate(2019, 1, 1); // 6:30:06 PM LocalTime localTime = new LocalTime(18, 30, 6, 0);

LocalDate是替代了早期Joda-Time版本中使用的org.joda.time.YearMonthDay,LocalTime是替代早期版本的org.joda.time.TimeOfDay。(均已被標(biāo)注為過時狀態(tài))。

時間跨度

Joda-Time提供了三個類用于表示時間跨度(在某些業(yè)務(wù)需求中,它們可能會非常有用)。

Duration

這個類表示以毫秒為單位的絕對精度,提供標(biāo)準(zhǔn)數(shù)學(xué)轉(zhuǎn)換的方法,同時把時間跨度轉(zhuǎn)換為標(biāo)準(zhǔn)單位。

Period

這個類表示以年月日單位表示。

Interval

這個類表示一個特定的時間跨度,使用一個明確的時刻界定這段時間跨度的范圍。Interval 為半開  區(qū)間,所以由其封裝的時間跨度包括這段時間的起始時刻,但是不包含結(jié)束時刻。

2.3.2 使用Joda-Time的方法處理時間

DateTime today = new DateTime(); // 獲取777秒之前的時間 DateTime dateTime1 = today.minus(777 * 1000); // 獲取明天的時間 DateTime tomorrow = today.plusDays(1); // 獲取當(dāng)月第一天的日期 DateTime dateTime2 = today.withDayOfMonth(1);  // 獲取當(dāng)前時間三個月后的月份的最后一天 DateTime dateTime3 = today.plusMonths(3).dayOfMonth().withMaximumValue();

下面列出部分DateTime方法列表: plus/minus開頭的方法(比如:plusDay,  minusMonths):用來返回在DateTime實例上增加或減少一段時間后的實例

  • plus(long duration) 增加指定毫秒數(shù)并返回

  • plusYears(int years) 增加指定年份并返回

  • plusMonths(int months) 增加指定月份并返回

  • plusWeeks(int weeks) 增加指定星期并返回

  • plusDays(int days) 增加指定天數(shù)并返回

  • plusHours(int hours) 增加指定小時并返回

  • plusMinutes(int minutes) 增加指定分鐘并返回

  • plusSeconds(int seconds) 增加指定秒數(shù)并返回

  • plusMillis(int millis) 增加指定毫秒并返回

與之相反的是minus前綴的 plus是增加 minus是減少

with開頭的方法:用來返回在DateTime實例更新指定日期單位后的實例

  • withCenturyOfEra(int centuryOfEra) 更新時間世紀(jì)單位并返回

  • withYearOfCentury(int yearOfCentury)更新世紀(jì)年并返回

  • withYear(int year) 更新時間年并返回

  • withWeekyear(int weekyear) 更新時間周數(shù)并返回

  • withMonthOfYear(int monthOfYear)更新時間月份并返回

  • withDayOfYear(int dayOfYear) 更新時間天數(shù)并返回

  • withDayOfMonth(int dayOfMonth) 更新時間天數(shù)并返回

  • withDayOfWeek(int dayOfWeek) 更新時間天數(shù)并返回

  • withHourOfDay(int hour) 更新時間小時并返回

  • withMinuteOfHour(int minute) 更新時間分鐘并返回

  • withSecondOfMinute(int second) 更新時間秒數(shù)并返回

  • withMillisOfSecond(int millis) 更新時間毫秒并返回

  • withMillisOfDay(int millis) 更新時間毫秒并返回

  • withTimeAtStartOfDay() 獲取當(dāng)天最早時間

判斷DateTime對象大小狀態(tài)的一些操作方法

  • compareTo(DateTime d) 比較兩時間大小 時間大于指定時間返回 1 時間小于指定時間返回-1 相等返回0

  • equals(DateTime d) 比較兩時間是否相等

  • isAfter(long instant) 判斷時間是否大于指定時間

  • isAfterNow() 判斷時間是否大于當(dāng)前時間

  • isBefore(long instant) 判斷時間是否小于指定時間

  • isBeforeNow() 判斷時間是否小于當(dāng)前時間

  • isEqual(long instant) 判斷時間是否等于指定時間

  • isEqualNow() 判斷時間是否等于當(dāng)前時間

2.3.3 以Joda-Time的方式格式化時間

// 傳入的格式化模板只需與JDK SimpleDateFormat兼容的格式字符串即可 public static String convert(Date date,String dateFormat){     return new DateTime(date).toString(dateFormat); } // 將JDK中的Date轉(zhuǎn)化為UTC時區(qū)的DateTime DateTime dateTime = new DateTime(new Date(), DateTimeZone.UTC); // 將String轉(zhuǎn)換為DateTime public static Date convertUTC2Date(String utcDate){     DateTime dateTime =DateTime.parse(utcDate, DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));     return dateTime.toDate();  }

更多使用方法請參考官方文檔。

三、JAVA 8中新的時間類庫

3.1 簡介

由于JDK之前版本的類庫的缺陷和糟糕的使用體驗,再加上已經(jīng)成為事實標(biāo)準(zhǔn)Joda-Time的影響力,Oracle決定在JAVA  API中提供高質(zhì)量的日期和時間支持,這也就是整合了大部分Joda-Time特性的JDK  8新的時間類庫。(Joda-Time的作者實際參與開發(fā),并且實現(xiàn)了JSR310的全部內(nèi)容,新的API位于java.time下。常用的類有以下幾個:LocalDate、LocalTime、Instant、Duration和Period。)

由于JDK 8  新的時間類庫大量借鑒了Joda-Time的設(shè)計思想乃至命名,因此如果你是Joda-Time的使用者,那你可以無學(xué)習(xí)成本的使用新的API(當(dāng)然,它們之間也存在些許差別需要注意到)。

3.2 使用方法

3.2.1 使用LocalDate 和LocalTime

首先是LocalDate,該類的實例是一個不可變對象,它只提供了簡單的日期,并不含當(dāng)天的時間信息。另外,它也不附帶任何與時區(qū)相關(guān)的信息。

// 使用指定的日期創(chuàng)建LocalDate LocalDate date = LocalDate.of(2019, 1, 1); // 獲取當(dāng)前日期 LocalDate today = LocalDate.now(); // 獲取今日的屬性 int year = date.getYear(); Month month = date.getMonth(); int day = date.getDayOfMonth(); DayOfWeek dow = date.getDayOfWeek(); int len = date.lengthOfMonth(); boolean leap = date.isLeapYear(); // 通過ChronoField的枚舉值獲取需要的屬性字段 int year = date.get(ChronoField.YEAR);

接著是LocalTime,它表示了一天內(nèi)的某個時刻。

LocalTime time = LocalTime.of(18, 18, 18); int hour = time.getHour(); int minute = time.getMinute(); int second = time.getSecond();

LocalDate和LocalTime都可以通過使用靜態(tài)方法parse來解析字符串進(jìn)行創(chuàng)建。

LocalDate date = LocalDate.parse("2019-01-01");  LocalTime time = LocalTime.parse("18:18:18");

也可以向parse方法傳遞一個DateTimeFormatter,該類的實例定義了如何格式化一個日期或者時間對象。它其實是老版java.util.DateFormat的替代品。

3.2.2 LocalDateTime

// 直接創(chuàng)建LocalDateTime LocalDateTime dt1 = LocalDateTime.of(2019, Month.JANUARY, 1, 18, 18, 18); // 合并日期和時間 LocalDate date = LocalDate.parse("2019-01-01"); LocalTime time = LocalTime.parse("18:18:18"); LocalDateTime dt2 = LocalDateTime.of(date, time); LocalDateTime dt3 = date.atTime(18, 18, 18); LocalDateTime dt4 = date.atTime(time); LocalDateTime dt5 = time.atDate(date); // 從LocalDateTime中提取LocalDate或者LocalTime LocalDate date1 = dt1.toLocalDate(); LocalTime time1 = dt1.toLocalTime();

3.3.3 Instant

Instant類是為了方便計算機理解的而設(shè)計的,它表示一個持續(xù)時間段上某個點的單一大整型數(shù),實際上它是以Unix元年時間(傳統(tǒng)的設(shè)定為UTC時區(qū)1970年1月1日午夜時分)開始所經(jīng)歷的秒數(shù)進(jìn)行計算(最小計算單位為納秒)。

// 傳遞一個秒數(shù)已創(chuàng)建該類的實例 Instant.ofEpochSecond(3); // 傳遞一個秒數(shù)+納秒 2 秒之后再加上100萬納秒(1秒) Instant.ofEpochSecond(2, 1_000_000_000);

3.3.4 Duration與Period

Duration是用于比較兩個LocalTime對象或者兩個Instant之間的時間差值。

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

Period是用于對年月日的方式對多個時間進(jìn)行比較。

Period tenDays = Period.between(LocalDate.of(2019, 1, 1), lcalDate.of(2019, 2, 2));

當(dāng)然,Duration和Period類都提供了很多非常方便的工廠類,直接創(chuàng)建對應(yīng)的實例。

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);

3.3.5 操作、解析和格式化日期

// 直接使用withAttribute的方法修改 LocalDate date1 = LocalDate.of(2019, 1, 1); LocalDate date2 = date1.withYear(2019); LocalDate date3 = date2.withDayOfMonth(1); LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 1);

所有聲明了Temporal接口的類LocalDate、LocalTime、LocalDateTime以及Instant,它們都使用get和with方法,將對象值的讀取和修改區(qū)分開,如果使用了不支持的字段訪問字段,會拋出一個UnsupportedTemporalTypeException異常。類似的,plus方法和minus方法都聲明于Temporal接口。通過這些方法,對TemporalUnit對象加上或者減去一個數(shù)字,我們能非常方便地將Temporal對象前溯或者回滾至某個時間段,通過ChronoUnit枚舉我們可以非常方便地實現(xiàn)TemporalUnit接口。

3.3.6 更多定制化的處理時間

向重載的with方法傳遞一個定制化的TemporalAdjuster對象,可以更加靈活地處理日期。時間和日期的API已經(jīng)提供了大量預(yù)定義的TemporalAdjuster,可以通過TemporalAdjuster類的靜態(tài)工廠方法訪問它們。這些方法的名稱非常直觀,方法名就是問題描述。某些情況下,如果你需要定義自己的TemporalAdjuster,只需要聲明TemporalAdjuster接口并且自己實現(xiàn)對應(yīng)的方法即可。

LocalDate date1 = LocalDate.of(2014, 3, 18); LocalDate date2 = date1.with(TemporalAdjuster.nextOrSame(DayOfWeek.SUNDAY)); LocalDate date3 = date2.with(TemporalAdjuster.lastDayOfMonth());

3.3.7 解析日期-時間對象

日常工作中,格式化以及解析日期-時間對象是另一個非常重要的功能,而新的java.time.format包就是特別為我們達(dá)到這個目的而設(shè)計的。這其中,最重要的類是DateTimeFormatter。所有的DateTimeFormatter實例都能用于以一定的格式創(chuàng)建代表特定日期或時間的字符串。(與老的java.util.DateFormat相比較,所有的DateTimeFormatter實例都是線程安全的)

  1. // 使用不同的格式器生成字符串 

  2. LocalDate date = LocalDate.of(2019, 1, 1); 

  3. String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE); 

  4. String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE); 

  5. // 生成LocalDate對象 

  6. LocalDate date1 = LocalDate.parse("20190101", DateTimeFormatter.BASIC_ISO_DATE); 

  7. LocalDate date2 = LocalDate.parse("2019-01-01", DateTimeFormatter.ISO_LOCAL_DATE); 


// 使用特定的模式創(chuàng)建格式器 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); LocalDate date1 = LocalDate.of(2019, 1, 1); String formattedDate = date1.format(formatter); LocalDate date2 = LocalDate.parse(formattedDate, formatter);

3.3.8 處理不同的時區(qū)和日歷系統(tǒng)

在新的日期-時間類庫中,為了最大程度上的減少在處理時區(qū)帶來的繁瑣和復(fù)雜而使用了新的java.time.ZoneId類(與其他日期和時間類一樣,ZoneId類也是無法修改的)  來替代老版的java.util.TimeZone。時區(qū)是按照一定的規(guī)則將區(qū)域劃分成標(biāo)準(zhǔn)時間相同的區(qū)間。在ZoneRules這個類中包含了40個這樣的實例??梢院唵蔚赝ㄟ^調(diào)用ZoneId的getRules()得到指定時區(qū)的規(guī)則。每個特定的ZoneId對象都由一個地區(qū)ID標(biāo)識,地區(qū)ID都為“{區(qū)域}/{城市}”的格式。比如:

ZoneId romeZone = ZoneId.of("Asia/Shanghai");

Java 8中在原先的TimeZone中加入了新的方法toZoneId,其作用是將一個老的時區(qū)對象轉(zhuǎn)換為ZoneId:

ZoneId zoneId = TimeZone.getDefault().toZoneId();

得到的ZoneId對象后可以將它與LocalDate、LocalDateTime或者是Instant對象整合起來,構(gòu)造為一個ZonedDateTime實例,它代表了相對于指定時區(qū)的時間點:

LocalDate date = LocalDate.of(2019, Month.JANUARY, 1); ZonedDateTime zdt1 = date.atStartOfDay(romeZone); LocalDateTime dateTime = LocalDateTime.of(2019, Month.JANUARY, 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(2019, Month.JANUARY, 18, 13, 45); Instant instantFromDateTime = dateTime.toInstant(romeZone);

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

Instant instant = Instant.now(); LocalDateTime timeFromInstant = LocalDateTime.ofInstant(instant, romeZone);

與Joda-Time所不同的是,Java8中的日期-時間類庫提供了4種其他的日歷系統(tǒng),這些日歷系統(tǒng)中的每一個都有一個對應(yīng)的日志類,分別是ThaiBuddhistDate、MinguoDate  、JapaneseDate 以及HijrahDate 。所有這些類以及LocalDate  都實現(xiàn)了ChronoLocalDate接口,能夠?qū)珰v的日期進(jìn)行建模。利用LocalDate對象,你可以創(chuàng)建這些類的實例。同樣的,利用它們提供的靜態(tài)工廠方法,你可以創(chuàng)建任何一個Temporal對象的實例。

LocalDate date = LocalDate.of(2019, Month.JANUARY, 1); JapaneseDate japaneseDate = JapaneseDate.from(date);

參考資料

Joda-Time 簡介 Joda Time項目和java8時間api

動態(tài)計算時間段

需求:如現(xiàn)在是13:00,則時間段為15:10-17:10、17:10-19:10、19:10-21:10;即最早的出發(fā)時間為當(dāng)前時間+參數(shù)【2h20min】,最遲的時間段為開始時間在20點前結(jié)束時間在20點后的時間段),求解共有多少個時間段?

分析:

  1. 第一個時間段的開始時間:當(dāng)前時間+參數(shù)【2h20min】,中間的時間段是2h;

  2. 通過理解這句:最遲的時間段為開始時間在20點前結(jié)束時間在20點后的時間段,我們可以假設(shè)最大的時間變量為 max

  3. 假設(shè)當(dāng)前時間為now,總共有n個時間段,可以推導(dǎo)出公式:now + (2h * n) + 10min <= max;

注意:計算過程都轉(zhuǎn)換成毫秒

public class Test {     // 毫秒     static final long slot = 130 * 60 * 1000;      private static List<TimeSelectItem> buildStartEndTime(Long now, Long max) {         // now + (2h * n) + 10min  <= max;          Long n = (max - now - 60 * 1000) / (120 * 60 * 1000);         System.out.println("max:" + max);         System.out.println("now:" + now);         System.out.println(" max - now:" + (max - now));         System.out.println("n:" + n);          List<TimeSelectItem> timeSelectItems = new ArrayList<>();          Long startTimestamp = now + slot;         Long endTimestamp = startTimestamp + 120 * 60 * 1000;          for (int i = 1; i <= n; i++) {             // 起始時間             // startTimestamp = startTimestamp + i * (120 * 60 * 1000);             // 結(jié)束時間             endTimestamp = startTimestamp + (120 * 60 * 1000);              System.out.println(startTimestamp);             System.out.println(endTimestamp);              TimeSelectItem item = new TimeSelectItem();              DateTime dt = new DateTime(startTimestamp);             int hour = dt.hourOfDay().get();             int millis = dt.getMinuteOfHour();             String startTag = hour + ":" + millis;              DateTime dt1 = new DateTime(endTimestamp);             int hour1 = dt1.hourOfDay().get();             long millis1 = dt1.getMinuteOfHour();             String enTag = hour1 + ":" + millis1;              item.setDisplayName(startTag + " - " + enTag);              item.setStartTimestamp(startTimestamp);             item.setEndTimestamp(endTimestamp);             timeSelectItems.add(item);              startTimestamp = endTimestamp;         }         return timeSelectItems;     }      public static void main(String[] args) {         Long start = DateTime.now().getMillis();         Calendar c = Calendar.getInstance();         c.setTime(new Date());         c.set(Calendar.HOUR_OF_DAY, 20);         c.set(Calendar.MINUTE, 0);         c.set(Calendar.SECOND, 0);           DateTime dt = new DateTime();         dt.withHourOfDay(20);         Long end = c.getTimeInMillis();                 // List<TimeSelectItem> list = buildStartEndTime(1614747600000L, 1614772800000L);         List<TimeSelectItem> list = buildStartEndTime(1614834000000L, end);         for (TimeSelectItem item : list ) {             System.out.println(item);         }     } }

到此,相信大家對“如何使用Java時間操作類庫Joda-Time”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI