##轉載請標明出處 http://coderknock.com JDateTime 是一個優雅的,對開發者友好的時間日期處理類,而且也一種很是精巧的跟蹤日期和時間的一種方式。它使用一種很是清晰而且被普遍證實的算法去進行時間的操做。每一個被JDK中Calendar深深虐過的人都將發現使用JDateTime是多麼美妙的一種體驗。java
###Julian day算法
Julian day 或者 Julian day number(JDN)表示距離格林威治時間公元前 4713年 1月1日 星期一正午12點有多少個整數天。Julian Date(JD)則表示距離一樣的時間過了多少天(有小數位的天)。JDs 是被推薦的方式當在天文學上表示時間時。sql
Julian Day number 能夠被認爲是一種簡單的日曆:日期是他的整數位,時間是它的小數位。這樣它能夠很是方便的被引用,計算或者轉換。實際上JD 的設計之美正是它能夠很是容易的去計算時間的範圍進而去根據時間滾動日期,僅僅經過簡單的數學加減法。JD容許經過簡單的減法去計算兩個歷史日期之間的時間差。函數
Julian Day 系統被天文學家引進用來在兩個不一樣的日曆中去統一不一樣的歷史年表明時提供統一的的日期系統。性能
除了零點的選取和名字的不同凡響外,Julian Day 和Julian Date 不是直接的關聯到Julian Calendar,儘管它能夠從將一個日曆的任何日期轉換到另外一個日曆。 ###精度學習
JDateTime 內部使用JD去表示當前的日期和時間,它根據被證實並很好地測試過的天文學算法去作全部的計算。JDateTime 在全部的計算中提供精確到1毫秒的精度。測試
###日期和時間設置設計
JDateTime 能夠經過多種方式建立:經過制定想要的日期和時間,或者經過傳入一個JDK中日期時間相關類的實例,或者經過指定系統的毫秒數等等。code
JDateTime 還支持經過指定日期和時間數據來建立,一旦被建立,日期和時間能夠經過不一樣的方式來改變,能夠經過完整的日期/時間信息來改變(等同於建立新的JDateInstance)或者僅僅改變一部分(天或者分鐘等等)。orm
JDateTime有較好的容錯性,好比JDateTime jdt = new JDateTime("2016-1-32");會生成2016-02-01並不會報錯。 ####先簡單看一下如何建立一個Date: ######使用構造函數進行JDateTime的初始化
import jodd.datetime.JDateTime; import jodd.datetime.format.JdtFormat; /** * 拿客 * www.coderknock.com * QQ羣:213732117 * 建立時間:2016年07月14日 * 描述:JDateTime */ public class JoddDate { public static void main(String[] args) { JDateTime jdt = new JDateTime(); // 當前的日期以及時間 jdt.getFormat();//獲取格式化字符串,默認是 YYYY-MM-DD hh:mm:ss.mss jdt.setFormat("YYYY年MM月DD日 hh時mm分ss秒 mss毫秒");//設置格式化字符串 System.out.println(jdt); //JDateTime重寫了toString方法,使用了JdtFormatter來格式化輸出字符串 jdt = new JDateTime(2012, 12, 21); // 2012年12月21日 System.out.println(jdt.toString()); jdt = new JDateTime(System.currentTimeMillis()); // 根據當前系統毫秒說來獲取時間 System.out.println(jdt.toString("MM/DD/YYYY hh:mm:ss mss"));//toString還有一個JdtFormat作完參數的方法,可是不太方便 jdt = new JDateTime(2012, 12, 21, 11, 54, 22, 124); // 設置日期以及時、分、秒、毫秒 System.out.println(jdt); jdt = new JDateTime("2012-12-21 11:54:22.124"); // 使用格式化字符串設置時間 System.out.println(jdt); jdt = new JDateTime("12/21/2012", "MM/DD/YYYY"); // 使用本身定義的時間字符串設置時間 System.out.println(jdt); } }
輸出:
2016年07月14日 09時49分56秒 204毫秒 2012-12-21 00:00:00.000 2016-07-14 09:49:56.240 2012-12-21 11:54:22.124 2012-12-21 11:54:22.124 2012-12-21 00:00:00.000
######使用方法進行JDateTime的時間設置
import jodd.datetime.JDateTime; import jodd.datetime.format.JdtFormat; /** * 拿客 * www.coderknock.com * QQ羣:213732117 * 建立時間:2016年07月14日 * 描述:JDateTime */ public class JoddDate { public static void main(String[] args) { JDateTime jdt = new JDateTime(); System.out.println(jdt); jdt.set(2012, 12, 21, 11, 54, 22, 124); // 設置日期和時間 System.out.println(jdt); jdt.set(2012, 12, 21); // 設置日期 這種方法會默認時間爲零點 System.out.println(jdt); jdt.setDate(2012, 12, 21); // 另外一種設置日期的方法 這種方法會默認時間爲零點 System.out.println(jdt); jdt.setCurrentTime(); // 設置爲當前日期和時間 System.out.println(jdt); jdt.setYear(1973); // 改變年(也有單獨改變月、日的方法,你們本身嘗試) System.out.println(jdt); jdt.setHour(22); // 改變小時(也有單獨改變分、毫秒的方法,你們本身嘗試) System.out.println(jdt); jdt.setTime(18, 00, 12, 853); // 設置時間 System.out.println(jdt); } }
輸出結果:
2016-07-14 10:31:31.380 2012-12-21 11:54:22.124 2012-12-21 00:00:00.000 2012-12-21 00:00:00.000 2016-07-14 10:31:31.412 1973-07-14 10:31:31.412 1973-07-14 22:31:31.412 1973-07-14 18:00:12.853
JDateTime提供了儘量多的方法來知足開發的需求,而且提供了不一樣參數的重載方法,基本上你想要的方法均可以找到。 JDateTime提供了日期時間中各個部分的get方法,能夠很方便的獲取到想要的內容。在JDateTime中天和月是從1開始計數的,因此,JDateTime.JNUARY 是1。 JDateTime還提供幾個方法來獲取Java中經常使用的時間格式:
convertToDate java.util.Date convertToCalendar java.util.Calendar convertToSqlDate java.sql.Date convertToSqlTime java.sql.Time convertToSqlTimestamp java.sql.Timestamp
一樣能夠從java中的時間直接轉成JDateTime
JDateTime(java.util.Date) JDateTime(java.util.calendar) setDateTime(java.util.Date) setDateTime(java.util.calendar)
官方文檔中提出的如下方法我在3.7.1版本中測試時已經找不到了
jdt.convertToGregorianCalendar(); jdt.convertTo(GregorianCalendar.class); // generic way of conversion jdt.loadFrom(gregCalInstance); // load time data from GregorianCalendar jdt.storeTo(gregCalInstance); // store time data to GregorianCalendar
###時間計算
JDateTime 提供了儘量多的方法來知足開發的需求,而且提供了不一樣參數的重載方法在當前的日期/時間上加減指定的時間。它能夠僅僅改變單個部分的日期/時間信息也能夠一次改變多個部分。
JDateTime中加操做使用add方法開頭(有不少很細的操做的方法你們能夠仔細看看API)減使用sub(有不少很細的操做的方法你們能夠仔細看看API)。
import jodd.datetime.JDateTime; /** * 拿客 * www.coderknock.com * QQ羣:213732117 * 建立時間:2016年07月14日 * 描述:JDateTime */ public class JoddDate { public static void main(String[] args) { JDateTime jdt = new JDateTime("2016-7-14 11:54:22.124"); System.out.println(jdt); jdt.add(1, 2, 3, 4, 5, 6, 7); // 增長一年兩個月三個小時...... System.out.println(jdt); jdt.add(4, 2, 0); // 增長四年兩個月 System.out.println(jdt); jdt.addMonth(-120); // 減小120個月 System.out.println(jdt); jdt.subYear(1); // 減小一年 System.out.println(jdt); jdt.addHour(1234); // 增長1234小時 System.out.println(jdt); } }
輸出結果:
2016-07-14 11:54:22.124 2017-09-17 15:59:28.131 2021-11-17 15:59:28.131 2011-11-17 15:59:28.131 2010-11-17 15:59:28.131 2011-01-08 01:59:28.131
因爲性能的緣由,最好是經過一個方法調用按照順序一次性改變多個時間部分,好比,若是同時要在當前時間上加必定數量的months,minutes和秒,經過add(0, months, 0, 0, minutes, seconds, 0); 一次性改變而不是調用三個單獨的方法去改變,這樣速度更快。 因爲每個月天數的不一樣,對於月的增減須要格外注意:
import jodd.datetime.JDateTime; /** * 拿客 * www.coderknock.com * QQ羣:213732117 * 建立時間:2016年07月14日 * 描述:JDateTime */ public class JoddDate { public static void main(String[] args) { JDateTime jdt = new JDateTime("2016-1-31"); System.out.println(jdt); jdt.addMonth(1); System.out.println(jdt); jdt = new JDateTime("2016-1-31"); //設置MonthFix爲flase以後增長一個月就至關因而增長31天(忽略月份天數的不一樣) jdt.setMonthFix(false);//MonthFix默認是true JDateTimeDefault.monthFix jdt.addMonth(1); System.out.println(jdt); } }
輸出結果:
2016-01-31 00:00:00.000 2016-02-29 00:00:00.000 2016-03-02 00:00:00.000
###時間對比 JDateTime中提供了多種方法來進行時間的對比(有不少重載,這塊比較簡單,不作演示) compareTo compareDateTo isAfter isBefore isAfterDate isBeforeDate daysBetween daysBetween equalsDate equalsTime ###週期
經過JDateTime 能夠很是容易的去計算時間週期。經過兩個時間相減接口獲得的結果去計算週期時間十分的方便。可是若是要包括小時,分鐘,秒和毫秒,更簡單而且快速的方式是使用Period類。
import jodd.datetime.JDateTime; import jodd.datetime.Period; /** * 拿客 * www.coderknock.com * QQ羣:213732117 * 建立時間:2016年07月14日 * 描述:JDateTime */ public class JoddDate { public static void main(String[] args) { JDateTime jdt=new JDateTime("2015-7-14"); JDateTime jdtTow=new JDateTime("2016-7-14"); Period period=new Period(jdt,jdtTow); System.out.println(period.getDays()); //獲取兩個時間中天數部分的差 System.out.println(period.getHours()); //獲取兩個時間中小時部分的差(只包括顯示部分而並非總差的小時數) System.out.println(period.getMilliseconds());//獲取兩個時間中毫秒部分的差(只包括顯示部分而並非總差的小時數) System.out.println(period.getMinutes());//獲取兩個時間中分鐘部分的差(只包括顯示部分而並非總差的小時數) System.out.println(period.getSeconds());//獲取兩個時間中秒部分的差(只包括顯示部分而並非總差的小時數) JDateTime newjdt=new JDateTime("2015-7-14 14:23:53.123"); JDateTime newjdtTow=new JDateTime("2016-7-14 16:10:22.23"); Period newperiod=new Period(newjdt,newjdtTow); System.out.println(newperiod.getDays()); //獲取兩個時間中天數部分的差 System.out.println(newperiod.getHours()); //獲取兩個時間中小時部分的差(只包括顯示部分而並非總差的小時數) System.out.println(newperiod.getMilliseconds());//獲取兩個時間中毫秒部分的差(只包括顯示部分而並非總差的小時數) System.out.println(newperiod.getMinutes());//獲取兩個時間中分鐘部分的差(只包括顯示部分而並非總差的小時數) System.out.println(newperiod.getSeconds());//獲取兩個時間中秒部分的差(只包括顯示部分而並非總差的小時數) } }
請認真分析一下輸出的結果:
366 0 0 0 0 366 1 900 46 28
若是newjdtTow=new JDateTime("2016-7-14 15:10:22.23");那麼小時差爲0,由於15:10和14:23分直接差的小時數不夠一個小時,同理若是newjdtTow=new JDateTime("2016-7-14 14:10:22.23");那麼天數差會爲365。 ###字符串轉換 #####JDateTime支持的解析模式(支持的較少,可是已經我的以爲夠用): |模式|是否能夠解析?|值| |:----:|:----:|:----:| |YYYY|yes|year| |MM|yes|month| |DD|yes|day of month| |D| |day of week| |MML| |month name long| |MMS| |month name short| |DL| |day of week name long| |DS| |day of week name short| |hh|yes|hour| |mm|yes|minute| |ss|yes|seconds| |mss|yes|milliseconds| |DDD| |day of year| |WW| |week of year| |WWW| |week of year with 'W' prefix| |W| |week of month| |E| |era (AD or BC)| |TZL| |time zone name long| |TZS| |time zone name short| 在上面的示例中,實際對字符串的轉換已經有一些講解,下面咱們就列出官方的示例,供你們擴展學習:
import jodd.datetime.JDateTime; import java.text.DateFormat; import java.text.SimpleDateFormat; /** * 拿客 * www.coderknock.com * QQ羣:213732117 * 建立時間:2016年07月14日 * 描述:JDateTime */ public class JoddDate { public static void main(String[] args) { JDateTime jdt = new JDateTime(1975, 1, 1); System.out.println(jdt.toString()); // "1975-01-01 00:00:00.000" System.out.println(jdt.toString("YYYY.MM.DD")); // "1975.01.01" System.out.println(jdt.toString("MM: MML (MMS)")); // "01: January (Jan)" System.out.println(jdt.toString("DD is D: DL (DS)")); // "01 is 3: Wednesday (Wed)" System.out.println(jdt.toString("'''' is a sign, W is a week number and 'W' is a letter")); // "' is a sign, 5 is a week number and W is a letter" jdt.parse("2003-11-24 23:18:38.173"); System.out.println(jdt); jdt.parse("2003-11-23"); System.out.println(jdt); // 2003-11-23 00:00:00.000 jdt.parse("01.01.1975", "DD.MM.YYYY"); System.out.println(jdt); // 1975-01-01 jdt.parse("2001-01-31", "YYYY-MM-***"); System.out.println(jdt); // 2001-01-01, since day is not parsed DateFormat df = new SimpleDateFormat(); System.out.println(df.format(jdt.convertToDate())); // date formatter } }
上面示例中對官網給出的部分已經不可用的示例進行了刪減 輸出結果
1975-01-01 00:00:00.000 1975.01.01 01: 一月 (一月) 01 is 3: 星期三 (星期三) ' is a sign, 1 is a week number and W is a letter 2003-11-24 23:18:38.173 2003-11-23 00:00:00.000 1975-01-01 00:00:00.000 2001-01-01 00:00:00.000 01-1-1 上午12:00
###本地化
經過在JDateTime中設置locale,能夠在結果字符串中返回本地化的名稱,好比月份和長短日期的名稱,當沒有指定locale時,JDateTime使用系統默認的locale。 ###星期定義
JdateTime提供了兩種方式去定義星期,即定義星期的第一天和定義一年的第一個星期(用來周的計數)。 setWeekDefinition(start,must)定義一個星期的起始天和一週的那一天必須在一年中來計算該周屬於那一年。 setWeekDefinitionAlt(start, min) 是另外一個定義方式來定義一週的起始天和該周屬於該年時必須有的最小的天數。 ###JD供選方案
因爲JD的起始時間是如此的久遠,JD的數值很是的大和笨重,一個距離如今更近的起始點一般會被用到,好比丟棄掉一些數字位來在保證足夠的精度的同時適應有限的計算機內存。 JDateTime 能夠將JD在下面的類之間進行轉換:
簡化的 Julian Day (RJD), 改良的 Julian Day (MJD), and 截短的 Julian Day (TJD), NASA提出的定義
###時區和DST(夏時制)
Julian Date,根據定義,是與時區和夏時制無關的。可是,JDateTime支持時區,當時區改變時(而且改變到不一樣的時區)時間將進行必定的偏移。當JDateTime建立時,系統默認的時區就被使用,當設置新的時區是,當前時間將根據時區的不一樣而改變,下面的例子表示當前的日本時間:
JDateTime jdt = new JDateTime(); //官方給的示例就是小日本,因此沒作更改 jdt.setTimeZone(TimeZone.getTimeZone("Japan";)); System.out.println(jdt);
此外,能夠僅僅去設置時區,而不改變當前的時間。有時在改變時區時會很用,經過changeTimeZone()方法便可。 DST僅僅被部分支持,如今默認狀況下DST跟蹤是關閉的(標誌:trackDST)。當DST跟蹤打開時,JDateTime將跟蹤DST僅僅當加減時間時,最後一點,它能夠設置一個無效的時間(好比說不存在的時間)。 ###與Java中時間處理庫性能的對比: