Java日期及时间库插件 -- Joda Time.
轉(zhuǎn)載自? ?Java日期及時(shí)間庫(kù)插件 -- Joda Time.
來(lái)到新公司工作也有一個(gè)多月了, 陸陸續(xù)續(xù)做了一些簡(jiǎn)單的項(xiàng)目. 今天做一個(gè)新東西的時(shí)候發(fā)現(xiàn)了 Joda Time的這個(gè)東西, 因?yàn)橐郧坝玫亩际荍DK原生的時(shí)間處理API, 大家都知道Java原生的時(shí)間處理的API一直都是不太好用, 所以這個(gè)有必要去學(xué)習(xí)下, 去總結(jié)下.
來(lái)到新公司學(xué)到的東西挺多的, 比如我們用了Guava, ElasticSearch, kafka/mns/ons, GuavaCache/Ehcache/Memcahe .... 等很多東西都是我以前沒有接觸過(guò)的. 所以待我學(xué)習(xí)的東西還有很多. 每天都是懷著激動(dòng)的心情, 去汲取更多的知識(shí). 說(shuō)了這么多屁話, 開始總結(jié)了.
一: 使用示例?
因?yàn)殡p十一就快到了, 所以接觸了一個(gè)秒殺的活動(dòng), 其中有這么一塊代碼:?
/*** 檢查抽獎(jiǎng)時(shí)間** @return true 可以抽獎(jiǎng) false 不能抽獎(jiǎng)*/private boolean checkDrawTime() {return DateTime.parse("2016-11-11 11:11:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).isBeforeNow();}這個(gè)方法很簡(jiǎn)單, 就是檢查現(xiàn)在的時(shí)間是不是2016/11/11 11:11:00 之前. 當(dāng)然這里的DateTime是Jode Time里的類.
查看源碼可以知道, DateTime.parse就是將輸入的時(shí)間轉(zhuǎn)換為后面的格式, 轉(zhuǎn)換的結(jié)果為:
然后再用isBeforeNow方法來(lái)比較, 下面看下這個(gè)方法具體的做法:
public boolean isBeforeNow() {return this.isBefore(DateTimeUtils.currentTimeMillis()); }public boolean isBefore(long var1) {return this.getMillis() < var1; }這樣看過(guò)來(lái)是不是很清楚了, 當(dāng)然Java 自帶的JDK也是可以完成的, 但是Joda Time都給我封裝好了, 用起來(lái)就更加簡(jiǎn)單了.
接下來(lái)看看更多的例子:
1、創(chuàng)建任意時(shí)間對(duì)象
//jdk Calendar calendar=Calendar.getInstance(); calendar.set(2012, Calendar.NOVEMBER, 15, 18, 23,55);//Joda-time DateTime dateTime=new DateTime(2012, 12, 15, 18, 23,55);2、計(jì)算兩日期相差的天數(shù)
//jdkCalendar start = Calendar.getInstance(); start.set(2012, Calendar.NOVEMBER, 14);Calendar end = Calendar.getInstance();end.set(2012, Calendar.NOVEMBER, 15);long startTim = start.getTimeInMillis();long endTim = end.getTimeInMillis();long diff = endTim-startTim;int days=(int) (diff/1000 / 3600 / 24);//joda-timeLocalDate start=new LocalDate(2012, 12,14);LocalDate end=new LocalDate(2012, 12, 15);int days = Days.daysBetween(start, end).getDays();3、獲取18天之后的某天在下個(gè)月的當(dāng)前周的第一天日期
//jdk Calendar current = Calendar.getInstance(); current.add(Calendar.DAY_OF_MONTH, 18); current.add(Calendar.MONTH, 1);...... DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = current.getTime(); String dateStr = dateFormat.format(date); System.out.println(dateStr);//joda-time String dateStr = new DateTime().plusDays(18).plusMonths(1).dayOfWeek().withMinimumValue().toString("yyyy-MM-dd HH:mm:ss"); System.out.println(dateStr);4、時(shí)間格式化
DateTimeFormatter format = DateTimeFormat .forPattern("yyyy-MM-dd HH:mm:ss");//時(shí)間解析 DateTime dateTime = DateTime.parse("2012-12-21 23:22:45", format);//時(shí)間格式化,輸出==> 2012/12/21 23:22:45 Fri String string_u = dateTime.toString("yyyy/MM/dd HH:mm:ss EE"); System.out.println(string_u);//格式化帶Locale,輸出==> 2012年12月21日 23:22:45 星期五 String string_c = dateTime.toString("yyyy年MM月dd日 HH:mm:ss EE",Locale.CHINESE); System.out.println(string_c);5、與JDK互操作
//通過(guò)jdk時(shí)間對(duì)象構(gòu)造 Date date = new Date(); DateTime dateTime = new DateTime(date);Calendar calendar = Calendar.getInstance(); dateTime = new DateTime(calendar);// Joda-time 各種操作..... dateTime = dateTime.plusDays(1) // 增加天.plusYears(1)// 增加年.plusMonths(1)// 增加月.plusWeeks(1)// 增加星期.minusMillis(1)// 減分鐘.minusHours(1)// 減小時(shí).minusSeconds(1);// 減秒數(shù)// 計(jì)算完轉(zhuǎn)換成jdk 對(duì)象 Date date2 = dateTime.toDate(); Calendar calendar2 = dateTime.toCalendar(Locale.CHINA)
二: api簡(jiǎn)介
Maven項(xiàng)目組中引入Joda Time坐標(biāo)地址:
<!-- joda --> <dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>2.3</version> </dependency>1, 日期和時(shí)間:
Joda-time里面的時(shí)間全都是不可變的,也就是不可變性。
DateTime :類似于JDK中的Calendar,提供了更多的方法。
DateMidnight :這個(gè)概念稍微復(fù)雜,封裝某個(gè)時(shí)區(qū)(通常為默認(rèn)時(shí)區(qū))在特定年/月/日的午夜時(shí)分的時(shí)刻。它基本上類似于?
DateTime,不同之處在于時(shí)間部分總是為與該對(duì)象關(guān)聯(lián)的特定?
DateTimeZone 時(shí)區(qū)的午夜時(shí)分。
LocalDate :無(wú)時(shí)間的類,只包含年月日。(不包含時(shí)區(qū))
LocalTime :無(wú)日期的類,只包含時(shí)間。(不包含時(shí)區(qū))
LocalDateTime :包含日期和時(shí)間。(不包含時(shí)區(qū))
下面舉一些簡(jiǎn)單的例子說(shuō)明Joda-time的強(qiáng)大之處:
//獲取當(dāng)前月份: DateTime dt = new DateTime(); int month = dt.getMonthOfYear(); //設(shè)定2000年/獲取當(dāng)前小時(shí)+2的小時(shí): DateTime dt = new DateTime(); DateTime year2000 = dt.withYear(2000); DateTime twoHoursLater = dt.plusHours(2); System.out.println(year2000.getYear()); System.out.println(twoHoursLater.getHourOfDay()); //以及下面的一些操作: String monthName = dt.monthOfYear().getAsText(); String frenchShortName = dt.monthOfYear().getAsShortText(Locale.FRENCH); boolean isLeapYear = dt.year().isLeap(); DateTime rounded = dt.dayOfMonth().roundFloorCopy(); System.out.println(monthName); // 本地月份名稱 System.out.println(frenchShortName); // 法語(yǔ)月份簡(jiǎn)稱 System.out.println(isLeapYear); // 是否閏年 System.out.println(rounded); // 獲取當(dāng)天0:0:0的DateTime對(duì)象2, 日歷系統(tǒng)及時(shí)區(qū)
Joda-time支持多種年表(即日歷系統(tǒng))及所有時(shí)區(qū)。主要的兩個(gè)類如下:
Chronology :年表,Joda-time支持很多年表。就像JDK有Calendar,也有GregorianCalendar。
DateTimeZone :時(shí)區(qū)。
示例如下,一般系統(tǒng)都沒有這個(gè)需求。
Chronology coptic = CopticChronology.getInstance(); System.out.println(coptic); // CopticChronology[Asia/Shanghai]DateTimeZone zone = DateTimeZone.forID("Asia/Tokyo"); Chronology gregorianJuian = GJChronology.getInstance(zone); System.out.println(gregorianJuian); // GJChronology[Asia/Tokyo]3, 時(shí)間跨度
Joda-time支持的時(shí)間跨度有三個(gè),分別如下:
Interval :根據(jù)開始、結(jié)束時(shí)間表示一個(gè)特定的時(shí)間跨度。其為半開區(qū)間,即包括起始時(shí)刻,不包含結(jié)束時(shí)刻。
Period :Period設(shè)定了一些特定的時(shí)間跨度,比如小時(shí)、天、月。
Duration :表示絕對(duì)的精準(zhǔn)跨度,以毫秒為單位。
使用示例如下:
DateTime beginDateTime = new DateTime(2010, 1, 1, 0, 0, 0); DateTime endDateTime = new DateTime(2015, 1, 1, 0, 0, 0); Interval interval = new Interval(beginDateTime, endDateTime); System.out.println(interval.containsNow()); // 是否包含當(dāng)前時(shí)間 System.out.println(interval.toDurationMillis()); // 時(shí)間間隔毫秒數(shù)DateTime dt = new DateTime(2005, 3, 26, 12, 0, 0, 0); DateTime plusPeriod = dt.plus(Period.days(1)); System.out.println(plusPeriod); // Period的方式+1天 DateTime plusDuration = dt.plus(new Duration(24L * 60L * 60L * 1000L)); System.out.println(plusDuration); // Duration的方式+1天三:?Joda-time使用的理念
不可變性(Immutability)
瞬間性(Instant)
局部性(Partial)
年表(Chronology)
時(shí)區(qū)(Time zone)
不可變
Joda-time的類具有不可變性,因此它們的實(shí)例無(wú)法被修改。(不可變類的一個(gè)優(yōu)點(diǎn)就是它們是線程 安全 的)。用于處理日期計(jì)算的 API 方法全部返回一個(gè)對(duì)應(yīng) Joda-time 類的新實(shí)例,同時(shí)保持原始實(shí)例不變。當(dāng)我們通過(guò)一個(gè) API 方法操作 Joda 類時(shí),我們必須捕捉該方法的返回值,因?yàn)槲覀冋谔幚淼膶?shí)例不能被修改。你可能對(duì)這種模式很熟悉,這正是 java.lang.String 的各種操作方法的工作 方式。
瞬間性
Instant 表示時(shí)間上的某個(gè)精確的時(shí)刻,使用從 epoch 開始計(jì)算的毫秒表示。這一定義與 JDK 相同,這就是為什么任何 Joda Instant 子類都可以與 JDK Date 和 Calendar 類兼容的原因。
更通用一點(diǎn)的定義是:一個(gè)瞬間 就是指時(shí)間線上只出現(xiàn)一次且唯一的一個(gè)時(shí)間點(diǎn),并且這種日期結(jié)構(gòu)只能以一種有意義的方式出現(xiàn)一次。
局部性
一個(gè)局部時(shí)間,正如我將在本文中將其稱為局部時(shí)間片段一樣,它指的是時(shí)間的一部分片段。瞬間性指定了與 epoch 相對(duì)的時(shí)間上的一個(gè)精確時(shí)刻,與此相反,局部時(shí)間片段指的是在時(shí)間上可以來(lái)回 “移動(dòng)” 的一個(gè)時(shí)刻,這樣它便可以應(yīng)用于多個(gè)實(shí)例。比如,6 月 2 日 可以應(yīng)用于任意一年的 6 月份(使用 Gregorian 日歷)的第二天的任意瞬間。同樣,11:06 p.m. 可以應(yīng)用于任意一年的任意一天,并且每天只能使用一次。即使它們沒有指定一個(gè)時(shí)間上的精確時(shí)刻,局部時(shí)間片段仍然是有用的。
我喜歡將局部時(shí)間片段看作一個(gè)重復(fù)周期中的一點(diǎn),這樣的話,如果我正在考慮的日期構(gòu)建可以以一種有意義的方式出現(xiàn)多次(即重復(fù)的),那么它就是一個(gè)局部時(shí)間。
年表
Joda 本質(zhì)——以及其設(shè)計(jì)核心——的關(guān)鍵就是年表(它的含義由一個(gè)同名抽象類捕捉)。從根本上講,年表是一種日歷系統(tǒng)——種計(jì)算時(shí)間的特殊方式——并且是一種在其中執(zhí)行日歷 算法 的框架。受 Joda 支持的年表的例子包括:ISO(默認(rèn))、Coptic、Julian、Islamic等。
時(shí)區(qū)
時(shí)區(qū)是值一個(gè)相對(duì)于英國(guó)格林威治的地理位置,用于計(jì)算時(shí)間。要了解事件發(fā)生的精確時(shí)間,還必須知道發(fā)生此事件的位置。任何嚴(yán)格的時(shí)間計(jì)算都必須涉及時(shí)區(qū)(或相對(duì)于 GMT),除非在同一個(gè)時(shí)區(qū)內(nèi)發(fā)生了相對(duì)時(shí)間計(jì)算(即時(shí)這樣時(shí)區(qū)也很重要,如果事件對(duì)于位于另一個(gè)時(shí)區(qū)的各方存在利益關(guān)系的話)。
DateTimeZone 是 Joda 庫(kù)用于封裝位置概念的類。許多日期和時(shí)間計(jì)算都可以在不涉及時(shí)區(qū)的情況下完成,但是仍然需要了解 DateTimeZone 如何影響 Joda 的操作。默認(rèn)時(shí)間,即從運(yùn)行代碼的機(jī)器的系統(tǒng)時(shí)鐘檢索到的時(shí)間,在大部分情況下被使用。
好了, 我所了解的就是這么多, 我主要還是從如何使用的角度去學(xué)習(xí)這個(gè)東西, 最后總結(jié)了它的幾個(gè)特性, 當(dāng)然Joda-Time的強(qiáng)大之處遠(yuǎn)不止這些, 大家在以后的工作中可以嘗試著去使用它.?
總結(jié)
以上是生活随笔為你收集整理的Java日期及时间库插件 -- Joda Time.的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用开源 Godot 引擎,《杀戮尖塔》
- 下一篇: 总结Java常见面试题和答案