java如何獲取當前的時間 java 獲取時間



文章插圖
java如何獲取當前的時間 java 獲取時間

文章插圖
前言
上一周在做一個產品的需求的時候有個動態計算時間段(如現在是13:00 , 則時間段為15:10-17:10、17:10-19:10、19:10-21:10;即最早的出發時間為當前時間+參數【2h10min】 , 最遲的時間段為開始時間在20點前結束時間在20點后的時間段) , 期間大量使用到了日期時間類庫 , 本著熟悉日期時間類庫才有了這篇文章 , 文章最后我會把我如何實現的這個需求的一個算法貼出來 。
一、JDK8以前版本中的時間類庫1.1 原始時間類庫存在的缺陷與不足
我們在使用Java8之前的類庫時 , 都會在處理日期-時間的時候總是不爽 , 這其中包括且不限于以下的槽點:
在Java 1.0版本中 , 對時間、日期的操作完全依賴于 java.util.Data 類 , 只能以毫秒的精度表示時間 , 無法表示日期 。
在易用性方面有著很大的缺陷 , 年份的起始時間選擇是1900年 , 月份是從0開始 。toString 方法返回值不直觀 , 帶有時區 。
在Java1.1 版本中 , 廢棄了很多Date 類中的很多方法 , 并且新增了 java.util.Calendar 。但是與Date相同 , Calendar 類也有類似的問題和設計缺陷 , 導致在使用這些類寫出的代碼也很容易出錯 。
月份依然是從0開始計算 。常用的日期、時間操作需要同時使用Date、Canendar、SimpleDateFormat , 比較繁瑣 。部分特性只存在于某一個類(解析和格式化日期或時間的DateFormat方法只存在于Date類中) 。DateFormat 不是線程安全的 , 如果兩個線程嘗試使用同一個formatter 解析日期 , 可能會得到無法預期的結果 。Date 和 Canendar 都是可變的 。1.2 關于SimpleDateFormat 線程不安全的原因
由于 parse 方法使用的貢獻變量 calendar 不是線程安全的 。在 format (subFormat) 方法中進行了 calendar 的賦值 , 在 parse 進行了值得處理 , 因此在并發的情況下會造成 calendar 清理不及時 , 值被覆蓋的情況 。
[email protected][email protected].Thisfieldisusedforbothformattingand*parsing.**<p>[email protected][email protected]}associatedwiththis*<code>DateFormat</code>.[email protected]*/protectedCalendarcalendar;@OverridepublicStringBufferformat(Datedate,StringBuffertoAppendTo,FieldPositionpos){pos.beginIndex=pos.endIndex=0;returnformat(date,toAppendTo,pos.getFieldDelegate());}//CalledfromFormataftercreatingaFieldDelegateprivateStringBufferformat(Datedate,StringBuffertoAppendTo,FieldDelegatedelegate){//Convertinputdatetotimefieldlistcalendar.setTime(date);//AtthispointthefieldsofCalendarhavebeenset.Calendar//willfillindefaultvaluesformissingfieldswhenthetime//iscomputed.pos.index=start;DateparsedDate;try{parsedDate=calb.establish(calendar).getTime();//Iftheyearvalueisambiguous,//thenthetwo-digityear==thedefaultstartyearif(ambiguousYear[0]){if(parsedDate.before(defaultCenturyStart)){parsedDate=calb.addYear(100).establish(calendar).getTime();}}}}1.3 如何解決上述線程不安全問題?使用ThreadLocal 為每個線程都創建一個線程獨享 SimpleDateFormat 變量;需要的時候創建局部變量;使用 org.apacle.commons.lang3.time.DateFormatUtils使用Joda-Time (后面介紹)二、Joda-Time 日期時間類庫2.1 簡介
Joda-Time 是Joda提供的一個遵循Apache2.0 開源協議的 JDK以外的優質日期和時間開發庫 。
Joda除Joda-Time之外的項目有Joda-Money、Joda-Beans、Joda-Convert、Joda-Collect Joda官網
2.1.1 為什么使用Joda-Time使用方便:Calendar 訪問“正常的”日期困難 , 并且缺乏簡單的防腐 , Joda-Time 擁有簡單的字段訪問 , 比如獲得年的 getYear() 和 獲得星期 中的天 getDayOfWeek()。易于擴展:JDK支持通過使用子類實現多個日歷系統 , 但是這是非常笨重的 , 并且在實現中很難選出另一個日歷系統 。Joda-Time 支持基于 Chronology 類實現多個可插拔的日歷系統 。功能全面:Joda-Time 提供了所有的日期和時間計算的必須功能 , 它提供了即裝即用的特性 。最新的時區計算:時區的實現基于公共時區信息數據庫 , 每年更新數次 。新版本的Joda-Time 包括了這個數據庫的所有更改 , 應盡早進行必要的更新 , 手動更新區域數據很容易 。日歷支持:提供了8種日歷系統 ?;ネㄐ裕簝炔渴褂煤撩脒M行標識 , 這與JDK或者其他公共的時間表示相一致 。性能良好:支持針對所有訪問的域進行最小的計算 。良好的測試覆蓋率:有全方位的測試人員保證庫的質量、具有完整文檔:有一個完整的用戶指南 , 該指南提供了一個概述 , 涵蓋常見的使用場景 。javadoc 非常詳細 , 涵蓋API的其余部分 。發展:自2002年以來積極發展,是一個成熟的可靠的代碼庫 , 一些相關的項目目前也是可用的 。開源:遵循Apache 2.0開源協議發布 。2.1.2 Joda-Time 的關鍵優點LocalDate:只包含日期LocalTime:只包含時間Instant:時間軸上的時間點DateTime:時區中完整的日期和時間DateTimeZone:更好的時區Duration和Period:持續時間Interval:兩個時間點之間的時間全面并且靈活的時間格式化與轉換
正因為Joda-Time 與 Java8 之前的時間類庫相比 , 具備了如此多的優點 , 所以 Joda-Time 成為事實上的標準的Java日期和時間庫 。
2.2 特性解讀2.2.1 Joda-Time和JDK的互操作性
互操作性是指:Joda 類能夠生成 java.util.Date 的實例(以及Calendar) , 這可以讓我們保留現有對JDK的依賴 , 又能夠使用Joda處理復雜的日期/時間計算 。
Date To Joda-Time
Datedate=newDate();DateTimedateTime=newDateTime(date);Canendar To Joda-Time
Calendarcalendar=Calendar.getInstance();DateTimedateTime=newDateTime(calendar);Joda-Time To Date
Datedate=newDate();DateTimedateTime=newDateTime(date);Datedate2=dateTime.toDate();Joda-Time To Calendar
Calendarcalendar=Calendar.getInstance();dateTime=newDateTime(calendar);Calendarcalendar2=dateTime.toCalendar(Locale.CHINA);2.2.2 Joda的關鍵日期/時間概念理解
Joda 使用了以下概念 , 使得它們可以應用到任何日期/時間庫:
不可變性(Immutability)
Joda-Time與java.lang.String類似 , 它們的實例均無法修改(因為任意對其值改變的操作都會生成新的對象) , 這也代表了它們是線程安全的 。
瞬時性(Instant)
如接口 org.joda.time.ReadableInstant 中所表示的那樣 , Instant 表示的是一個精確的時間點 , 是從 epoch:1970-01-01T00:00:00Z 開始計算的毫秒數 , 這也的設計也使得其子類都可以與JDK Date 以及 Calendar 類兼容 。
/***Definesaninstantinthedatetimecontinuum.*Thisinterfaceexpressesthedatetimeasmillisecondsfrom1970-01-01T00:00:00Z.*<p>*Theimplementationofthisinterfacemaybemutableorimmutable.*Thisinterfaceonlygivesaccesstoretrievedata,nevertochangeit.*<p>*Methodsinyourapplicationshouldbedefinedusing<code>ReadableInstant</code>*asaparameterifthemethodonlywantstoreadtheinstantwithoutneedingtoknow*thespecificdatetimefields.*<p>[email protected]}methodisnolongerdefinedinthisclassinversion2.0.*Instead,[email protected][email protected][email protected].[email protected][email protected][email protected]*/publicinterfaceReadableInstantextendsComparable<ReadableInstant>{/***Getthevalueasthenumberofmillisecondssince*theepoch,1970-01-01T00:00:[email protected]*/longgetMillis();······}DateTime 類繼承圖如下:
局部性(Partial)
瞬時性表達的是與epoch相對的時間上的一個精確時刻 , 而一個局部時間指的是一個時間的一部分片段 , 其可以通過一些方法使得時間產生變動(本質上還是生成了新的類) , 這樣可以把它當做重復周期中的一點 , 用到多個地方 。
年表(Chronology)
Joda-Time的設計核心就是年表(org.joda.time.Chronology) , 從根本上將 , 年表是一種日歷系統 , 是一種計算時間的特殊方式 , 并且在其中執行日歷算法的框架 。Joda-Time支持的8種年表如下所示:
ISO(默認) – org.joda.time.chrono.ISOChronologyGJ – org.joda.time.chrono.GJChronologyGregorian – org.joda.time.chrono.GregorianChronologyJulian – org.joda.time.chrono.JulianChronologyCoptic – org.joda.time.chrono.CopticChronologyBuddhist – org.joda.time.chrono.BuddhistChronologyEthiopic – org.joda.time.chrono.EthiopicChronologyIslamic – org.joda.time.chrono.IslamicChronology
以上的每一種年表都可以作為特定日歷系統的計算引擎 , 是可插拔的實現 。
時區(Time zone)
具體定義詳見百科解釋 , 在實際編碼過程中任何嚴格的時間計算都必須涉及時區(或者相對于GMT) , Joda-Time中對應的核心類為org.joda.time.DateTimeZone , 雖然日常的使用過程中 , 并未涉及到對時區的操作 , 但是DateTimeZone如何對DateTime產生影響是比較值得注意的 , 此處不進行贅述 。
2.3 具體使用方法
上面介紹我完了Joda-Time的一些概念 , 接下來具體使用我們來進行說明:
2.3.1 創建 Joda-Time 對象瞬時性-ReadableInstant
//1.使用系統時間DateTimedateTime1=newDateTime();//2.使用jdk中的dateDatejdkDate1=newDate();DateTimedateTime2=newDateTime(jdkDate1);//3.使用毫秒數指定DatejdkDate2=newDate();longmillis=jdkDate.getTime();DateTimedateTime3=newDateTime(millis);//4.使用CalendarCalendarcalendar=Calendar.getInstance();DateTimedateTime4=newDateTime(calendar);//5.使用多個字段指定一個瞬間時刻(局部時間片段)//yearmonthdayhour(midnightiszero)minutesecondmillisecondsDateTimedateTime5=newDateTime(2000,1,1,0,0,0,0);//6.由一個DateTime生成另一個DateTimeDateTimedateTime6=newDateTime(dateTime1);//7.有時間字符串生成DateTimeStringtimeString="2019-01-01T00:00:00-06:00";DateTimedateTime7=DateTime.parse(timeString);局部性-ReadablePartial
當程序中處理的日期、時間并不需要是完整時刻的時候 , 可以創建一個局部時間 , 比如只希望專注于年/月/日, 或者一天中的時間 , 或者是一周中的某天 。Joda-Time中有表示這些時間的是org.joda.time.ReadablePartial接口 , 實現它的兩個類LocalDate和LocalTime是分別用來表示年/月/日和一天中的某個時間的 。
//顯示地提供所含的每個字段LocalDatelocalDate=newLocalDate(2019,1,1);//6:30:06PMLocalTimelocalTime=newLocalTime(18,30,6,0);LocalDate是替代了早期Joda-Time版本中使用的org.joda.time.YearMonthDay , LocalTime是替代早期版本的org.joda.time.TimeOfDay 。(均已被標注為過時狀態) 。
時間跨度
Joda-Time提供了三個類用于表示時間跨度(在某些業務需求中 , 它們可能會非常有用) 。
Duration
這個類表示以毫秒為單位的絕對精度 , 提供標準數學轉換的方法 , 同時把時間跨度轉換為標準單位 。
Period
這個類表示以年月日單位表示 。
Interval
這個類表示一個特定的時間跨度 , 使用一個明確的時刻界定這段時間跨度的范圍 。Interval 為半開 區間 , 所以由其封裝的時間跨度包括這段時間的起始時刻 , 但是不包含結束時刻 。
2.3.2 使用Joda-Time的方法處理時間
DateTimetoday=newDateTime();//獲取777秒之前的時間DateTimedateTime1=today.minus(777*1000);//獲取明天的時間DateTimetomorrow=today.plusDays(1);//獲取當月第一天的日期DateTimedateTime2=today.withDayOfMonth(1);//獲取當前時間三個月后的月份的最后一天DateTimedateTime3=today.plusMonths(3).dayOfMonth().withMaximumValue();下面列出部分DateTime方法列表: plus/minus開頭的方法(比如:plusDay, minusMonths):用來返回在DateTime實例上增加或減少一段時間后的實例
plus(long duration) 增加指定毫秒數并返回plusYears(int years) 增加指定年份并返回plusMonths(int months) 增加指定月份并返回plusWeeks(int weeks) 增加指定星期并返回plusDays(int days) 增加指定天數并返回plusHours(int hours) 增加指定小時并返回plusMinutes(int minutes) 增加指定分鐘并返回plusSeconds(int seconds) 增加指定秒數并返回plusMillis(int millis) 增加指定毫秒并返回
與之相反的是minus前綴的 plus是增加 minus是減少
with開頭的方法:用來返回在DateTime實例更新指定日期單位后的實例
withCenturyOfEra(int centuryOfEra) 更新時間世紀單位并返回withYearOfCentury(int yearOfCentury)更新世紀年并返回withYear(int year) 更新時間年并返回withWeekyear(int weekyear) 更新時間周數并返回withMonthOfYear(int monthOfYear)更新時間月份并返回withDayOfYear(int dayOfYear) 更新時間天數并返回withDayOfMonth(int dayOfMonth) 更新時間天數并返回withDayOfWeek(int dayOfWeek) 更新時間天數并返回withHourOfDay(int hour) 更新時間小時并返回withMinuteOfHour(int minute) 更新時間分鐘并返回withSecondOfMinute(int second) 更新時間秒數并返回withMillisOfSecond(int millis) 更新時間毫秒并返回withMillisOfDay(int millis) 更新時間毫秒并返回withTimeAtStartOfDay() 獲取當天最早時間
判斷DateTime對象大小狀態的一些操作方法
compareTo(DateTime d) 比較兩時間大小 時間大于指定時間返回 1 時間小于指定時間返回-1 相等返回0equals(DateTime d) 比較兩時間是否相等isAfter(long instant) 判斷時間是否大于指定時間isAfterNow() 判斷時間是否大于當前時間isBefore(long instant) 判斷時間是否小于指定時間isBeforeNow() 判斷時間是否小于當前時間isEqual(long instant) 判斷時間是否等于指定時間isEqualNow() 判斷時間是否等于當前時間2.3.3 以Joda-Time的方式格式化時間
//傳入的格式化模板只需與JDKSimpleDateFormat兼容的格式字符串即可publicstaticStringconvert(Datedate,StringdateFormat){returnnewDateTime(date).toString(dateFormat);}//將JDK中的Date轉化為UTC時區的DateTimeDateTimedateTime=newDateTime(newDate(),DateTimeZone.UTC);//將String轉換為DateTimepublicstaticDateconvertUTC2Date(StringutcDate){DateTimedateTime=DateTime.parse(utcDate,DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));returndateTime.toDate();}
更多使用方法請參考官方文檔 。
三、JAVA 8中新的時間類庫3.1 簡介
由于JDK之前版本的類庫的缺陷和糟糕的使用體驗 , 再加上已經成為事實標準Joda-Time的影響力 , Oracle決定在JAVA API中提供高質量的日期和時間支持 , 這也就是整合了大部分Joda-Time特性的JDK 8新的時間類庫 。(Joda-Time的作者實際參與開發 , 并且實現了JSR310的全部內容 , 新的API位于java.time下 。常用的類有以下幾個:LocalDate、LocalTime、Instant、Duration和Period 。)
由于JDK 8 新的時間類庫大量借鑒了Joda-Time的設計思想乃至命名 , 因此如果你是Joda-Time的使用者 , 那你可以無學習成本的使用新的API(當然 , 它們之間也存在些許差別需要注意到) 。
3.2 使用方法3.2.1 使用LocalDate 和LocalTime
首先是LocalDate , 該類的實例是一個不可變對象 , 它只提供了簡單的日期 , 并不含當天的時間信息 。另外 , 它也不附帶任何與時區相關的信息 。
//使用指定的日期創建LocalDateLocalDatedate=LocalDate.of(2019,1,1);//獲取當前日期LocalDatetoday=LocalDate.now();//獲取今日的屬性intyear=date.getYear();Monthmonth=date.getMonth();intday=date.getDayOfMonth();DayOfWeekdow=date.getDayOfWeek();intlen=date.lengthOfMonth();booleanleap=date.isLeapYear();//通過ChronoField的枚舉值獲取需要的屬性字段intyear=date.get(ChronoField.YEAR);接著是LocalTime , 它表示了一天內的某個時刻 。
LocalTimetime=LocalTime.of(18,18,18);inthour=time.getHour();intminute=time.getMinute();intsecond=time.getSecond();LocalDate和LocalTime都可以通過使用靜態方法parse來解析字符串進行創建 。
LocalDatedate=LocalDate.parse("2019-01-01");LocalTimetime=LocalTime.parse("18:18:18");也可以向parse方法傳遞一個DateTimeFormatter , 該類的實例定義了如何格式化一個日期或者時間對象 。它其實是老版java.util.DateFormat的替代品 。
3.2.2 LocalDateTime
//直接創建LocalDateTimeLocalDateTimedt1=LocalDateTime.of(2019,Month.JANUARY,1,18,18,18);//合并日期和時間LocalDatedate=LocalDate.parse("2019-01-01");LocalTimetime=LocalTime.parse("18:18:18");LocalDateTimedt2=LocalDateTime.of(date,time);LocalDateTimedt3=date.atTime(18,18,18);LocalDateTimedt4=date.atTime(time);LocalDateTimedt5=time.atDate(date);//從LocalDateTime中提取LocalDate或者LocalTimeLocalDatedate1=dt1.toLocalDate();LocalTimetime1=dt1.toLocalTime();3.3.3 Instant
Instant類是為了方便計算機理解的而設計的 , 它表示一個持續時間段上某個點的單一大整型數 , 實際上它是以Unix元年時間(傳統的設定為UTC時區1970年1月1日午夜時分)開始所經歷的秒數進行計算(最小計算單位為納秒) 。
//傳遞一個秒數已創建該類的實例Instant.ofEpochSecond(3);//傳遞一個秒數+納秒2秒之后再加上100萬納秒(1秒)Instant.ofEpochSecond(2,1_000_000_000);3.3.4 Duration與Period
Duration是用于比較兩個LocalTime對象或者兩個Instant之間的時間差值 。
Durationd1=Duration.between(time1,time2);Durationd1=Duration.between(dateTime1,dateTime2);Durationd2=Duration.between(instant1,instant2);Period是用于對年月日的方式對多個時間進行比較 。
PeriodtenDays=Period.between(LocalDate.of(2019,1,1),lcalDate.of(2019,2,2));當然 , Duration和Period類都提供了很多非常方便的工廠類 , 直接創建對應的實例 。
DurationthreeMinutes=Duration.ofMinutes(3);DurationthreeMinutes=Duration.of(3,ChronoUnit.MINUTES);PeriodtenDays=Period.ofDays(10);PeriodthreeWeeks=Period.ofWeeks(3);PeriodtwoYearsSixMonthsOneDay=Period.of(2,6,1);3.3.5 操作、解析和格式化日期
//直接使用withAttribute的方法修改LocalDatedate1=LocalDate.of(2019,1,1);LocalDatedate2=date1.withYear(2019);LocalDatedate3=date2.withDayOfMonth(1);LocalDatedate4=date3.with(ChronoField.MONTH_OF_YEAR,1);所有聲明了Temporal接口的類LocalDate、LocalTime、LocalDateTime以及Instant , 它們都使用get和with方法 , 將對象值的讀取和修改區分開 , 如果使用了不支持的字段訪問字段 , 會拋出一個UnsupportedTemporalTypeException異常 。類似的 , plus方法和minus方法都聲明于Temporal接口 。通過這些方法 , 對TemporalUnit對象加上或者減去一個數字 , 我們能非常方便地將Temporal對象前溯或者回滾至某個時間段 , 通過ChronoUnit枚舉我們可以非常方便地實現TemporalUnit接口 。
3.3.6 更多定制化的處理時間
向重載的with方法傳遞一個定制化的TemporalAdjuster對象 , 可以更加靈活地處理日期 。時間和日期的API已經提供了大量預定義的TemporalAdjuster , 可以通過TemporalAdjuster類的靜態工廠方法訪問它們 。這些方法的名稱非常直觀 , 方法名就是問題描述 。某些情況下 , 如果你需要定義自己的TemporalAdjuster , 只需要聲明TemporalAdjuster接口并且自己實現對應的方法即可 。
LocalDatedate1=LocalDate.of(2014,3,18);LocalDatedate2=date1.with(TemporalAdjuster.nextOrSame(DayOfWeek.SUNDAY));LocalDatedate3=date2.with(TemporalAdjuster.lastDayOfMonth());3.3.7 解析日期-時間對象
日常工作中 , 格式化以及解析日期-時間對象是另一個非常重要的功能 , 而新的java.time.format包就是特別為我們達到這個目的而設計的 。這其中 , 最重要的類是DateTimeFormatter 。所有的DateTimeFormatter實例都能用于以一定的格式創建代表特定日期或時間的字符串 。(與老的java.util.DateFormat相比較 , 所有的DateTimeFormatter實例都是線程安全的)
//使用不同的格式器生成字符串LocalDatedate=LocalDate.of(2019,1,1);Strings1=date.format(DateTimeFormatter.BASIC_ISO_DATE);Strings2=date.format(DateTimeFormatter.ISO_LOCAL_DATE);//生成LocalDate對象LocalDatedate1=LocalDate.parse("20190101",DateTimeFormatter.BASIC_ISO_DATE);LocalDatedate2=LocalDate.parse("2019-01-01",DateTimeFormatter.ISO_LOCAL_DATE);//使用特定的模式創建格式器DateTimeFormatterformatter=DateTimeFormatter.ofPattern("dd/MM/yyyy");LocalDatedate1=LocalDate.of(2019,1,1);StringformattedDate=date1.format(formatter);LocalDatedate2=LocalDate.parse(formattedDate,formatter);3.3.8 處理不同的時區和日歷系統
在新的日期-時間類庫中 , 為了最大程度上的減少在處理時區帶來的繁瑣和復雜而使用了新的java.time.ZoneId類(與其他日期和時間類一樣 , ZoneId類也是無法修改的) 來替代老版的java.util.TimeZone 。時區是按照一定的規則將區域劃分成標準時間相同的區間 。在ZoneRules這個類中包含了40個這樣的實例 。可以簡單地通過調用ZoneId的getRules()得到指定時區的規則 。每個特定的ZoneId對象都由一個地區ID標識 , 地區ID都為“{區域}/{城市}”的格式 。比如:
ZoneIdromeZone=ZoneId.of("Asia/Shanghai");Java 8中在原先的TimeZone中加入了新的方法toZoneId , 其作用是將一個老的時區對象轉換為ZoneId:
ZoneIdzoneId=TimeZone.getDefault().toZoneId();得到的ZoneId對象后可以將它與LocalDate、LocalDateTime或者是Instant對象整合起來 , 構造為一個ZonedDateTime實例 , 它代表了相對于指定時區的時間點:
LocalDatedate=LocalDate.of(2019,Month.JANUARY,1);ZonedDateTimezdt1=date.atStartOfDay(romeZone);LocalDateTimedateTime=LocalDateTime.of(2019,Month.JANUARY,18,13,45);ZonedDateTimezdt2=dateTime.atZone(romeZone);Instantinstant=Instant.now();ZonedDateTimezdt3=instant.atZone(romeZone);通過ZoneId , 還可以將LocalDateTime轉換為Instant:
LocalDateTimedateTime=LocalDateTime.of(2019,Month.JANUARY,18,13,45);InstantinstantFromDateTime=dateTime.toInstant(romeZone);同樣可以通過反向的方式得到LocalDateTime對象:
Instantinstant=Instant.now();LocalDateTimetimeFromInstant=LocalDateTime.ofInstant(instant,romeZone);與Joda-Time所不同的是 , Java8中的日期-時間類庫提供了4種其他的日歷系統 , 這些日歷系統中的每一個都有一個對應的日志類 , 分別是ThaiBuddhistDate、MinguoDate 、JapaneseDate 以及HijrahDate。所有這些類以及LocalDate 都實現了ChronoLocalDate接口 , 能夠對公歷的日期進行建模 。利用LocalDate對象 , 你可以創建這些類的實例 。同樣的 , 利用它們提供的靜態工廠方法 , 你可以創建任何一個Temporal對象的實例 。
LocalDatedate=LocalDate.of(2019,Month.JANUARY,1);JapaneseDatejapaneseDate=JapaneseDate.from(date);參考資料
Joda-Time 簡介 Joda Time項目和java8時間api
動態計算時間段
需求:如現在是13:00 , 則時間段為15:10-17:10、17:10-19:10、19:10-21:10;即最早的出發時間為當前時間+參數【2h10min】 , 最遲的時間段為開始時間在20點前結束時間在20點后的時間段) , 求解共有多少個時間段?
分析:
第一個時間段的開始時間:當前時間+參數【2h10min】 , 中間的時間段是2h;通過理解這句:最遲的時間段為開始時間在20點前結束時間在20點后的時間段 , 我們可以假設最大的時間變量為 max假設當前時間為now , 總共有n個時間段 , 可以推導出公式:now + (2h * n) + 10min <= max;
注意:計算過程都轉換成毫秒
【java如何獲取當前的時間 java 獲取時間】publicclassTest{//毫秒staticfinallongslot=130*60*1000;privatestaticList<TimeSelectItem>buildStartEndTime(Longnow,Longmax){//now+(2h*n)+10min<=max;Longn=(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=newArrayList<>();LongstartTimestamp=now+slot;LongendTimestamp=startTimestamp+120*60*1000;for(inti=1;i<=n;i++){//起始時間//startTimestamp=startTimestamp+i*(120*60*1000);//結束時間endTimestamp=startTimestamp+(120*60*1000);System.out.println(startTimestamp);System.out.println(endTimestamp);TimeSelectItemitem=newTimeSelectItem();DateTimedt=newDateTime(startTimestamp);inthour=dt.hourOfDay().get();intmillis=dt.getMinuteOfHour();StringstartTag=hour+":"+millis;DateTimedt1=newDateTime(endTimestamp);inthour1=dt1.hourOfDay().get();longmillis1=dt1.getMinuteOfHour();StringenTag=hour1+":"+millis1;item.setDisplayName(startTag+"-"+enTag);item.setStartTimestamp(startTimestamp);item.setEndTimestamp(endTimestamp);timeSelectItems.add(item);startTimestamp=endTimestamp;}returntimeSelectItems;}publicstaticvoidmain(String[]args){Longstart=DateTime.now().getMillis();Calendarc=Calendar.getInstance();c.setTime(newDate());c.set(Calendar.HOUR_OF_DAY,20);c.set(Calendar.MINUTE,0);c.set(Calendar.SECOND,0);DateTimedt=newDateTime();dt.withHourOfDay(20);Longend=c.getTimeInMillis();//List<TimeSelectItem>list=buildStartEndTime(1614747600000L,1614772800000L);List<TimeSelectItem>list=buildStartEndTime(1614834000000L,end);for(TimeSelectItemitem:list){System.out.println(item);}}}