##转载请标明出处 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中时间处理库性能的对比: