文档章节

一个强大的Java时间处理库

拿客-三产
 拿客-三产
发布于 2016/07/14 11:34
字数 3463
阅读 313
收藏 11
点赞 0
评论 0

##转载请标明出处 http://coderknock.com JDateTime 是一个优雅的,对开发者友好的时间日期处理类,并且也一种非常精巧的跟踪日期和时间的一种方式。它使用一种非常清晰并且被广泛证明的算法去进行时间的操作。每个被JDK中Calendar深深虐过的人都将发现使用JDateTime是多么美妙的一种体验。

###Julian day

Julian day 或者 Julian day number(JDN)表示距离格林威治时间公元前 4713年 1月1日 星期一正午12点有多少个整数天。Julian Date(JD)则表示距离同样的时间过了多少天(有小数位的天)。JDs 是被推荐的方式当在天文学上表示时间时。

Julian Day number 可以被认为是一种简单的日历:日期是他的整数位,时间是它的小数位。这样它可以非常方便的被引用,计算或者转换。实际上JD 的设计之美正是它可以非常容易的去计算时间的范围进而去根据时间滚动日期,仅仅通过简单的数学加减法。JD允许通过简单的减法去计算两个历史日期之间的时间差。

Julian Day 系统被天文学家引进用来在两个不同的日历中去统一不同的历史年代表时提供统一的的日期系统。

除了零点的选取和名字的与众不同外,Julian Day 和Julian Date 不是直接的关联到Julian Calendar,尽管它可以从将一个日历的任何日期转换到另一个日历。 ###精度

JDateTime 内部使用JD去表示当前的日期和时间,它根据被证明并很好地测试过的天文学算法去做所有的计算。JDateTime 在所有的计算中提供精确到1毫秒的精度。

###日期和时间设置

JDateTime 可以通过多种方式创建:通过制定想要的日期和时间,或者通过传入一个JDK中日期时间相关类的实例,或者通过指定系统的毫秒数等等。

JDateTime 还支持通过指定日期和时间数据来创建,一旦被创建,日期和时间可以通过不同的方式来改变,可以通过完整的日期/时间信息来改变(等同于创建新的JDateInstance)或者仅仅改变一部分(天或者分钟等等)。

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中时间处理库性能的对比:

输入图片说明

© 著作权归作者所有

共有 人打赏支持
拿客-三产
粉丝 109
博文 75
码字总数 121734
作品 0
丰台
程序员
每个项目中,你必须知道的11个Java第三方类库。

Java第三方library ecosystem是一个很广阔的范畴。不久前有人撰文:每个项目中,你必须知道的11个Java第三方类库。 单元测试 1.DBUnit DBunit是一个基于junit扩展的数据库测试框架。它提供了...

thinkyoung ⋅ 2015/01/07 ⋅ 0

Xtend语言(1):独辟蹊径的JVM语言

我是2004年开始学习Java语言的,那时候的Java是1.4版本,说实在的,最新的Java10跟我一开始学习Java时候的语法变化并不大。我相信很多人都会跟我有相同的感受:Java写的越多就越觉得语法十分...

神思者l ⋅ 06/05 ⋅ 0

Java编程基础知识点和技术点归纳

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互...

Java小辰 ⋅ 05/23 ⋅ 0

Google的Guava类库简介(转)

说明:信息虽然有点旧,至少可以先了解个大概。 Guava是一个Google的基于Java的类库集合的扩展项目,包括collections, caching, primitives support, concurrency libraries, common annotat...

easonjim ⋅ 2017/11/01 ⋅ 0

Apache Groovy 2.5.0-rc-2 发布,包含 16 处修复和改进

Apache Groovy 2.5.0-rc-2 已发布。此版本包含 16 处错误修复/改进: Bug [GROOVY-6523] - Improve Documentation for in DefaultGroovyMethods.intersect(..) [GROOVY-7202] - Unable to re......

局长 ⋅ 05/07 ⋅ 0

Groovy 2.5.0 发布,JVM 动态脚本语言

Apache Groovy 2.5.0 已发布。此版本包含大量修复和依赖更新,并包含以下新特性: [GROOVY-6744] - Have the elvis operator (?:) support the Optional type in Java 8 [GROOVY-7089] - Bas......

淡漠悠然 ⋅ 05/31 ⋅ 1

Java程序员必读书单,家族又添新成员

点击关注异步图书,置顶公众号 每天与你分享IT好书 技术干货 职场知识 参与文末话题讨论,每日赠送异步图书。 ——异步小编 有些革命出其不意地吸引了全世界的眼球。Twitter、Linux操作系统和...

异步社区 ⋅ 05/09 ⋅ 0

Java 的 Ruby 解释器 - JRuby

JRuby是面向Ruby、基于Java虚拟机(JVM)的一种解释程序,它结合了Ruby语言的简易性和功能强大的JVM的执行机制,包括与Java库 全面集成。Rails彻底加快及简化了Web应用的开发,不过它让人觉得不...

匿名 ⋅ 2008/09/07 ⋅ 2

JRuby 9.1.17.0 发布,改进对 Java 9/10 的兼容性

JRuby 9.1.17.0 已发布,JRuby 是面向 Ruby、基于 Java 虚拟机(JVM)的一种解释程序,它结合了 Ruby 语言的简易性和功能强大的 JVM 的执行机制,包括与 Java 库全面集成。Rails 彻底加快及简化...

王练 ⋅ 04/24 ⋅ 0

用大白话告诉你啥是Java开发

Java,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台的总称。用Java实现的HotJava浏览器(支持Java applet)显示了Java的魅力:跨平台、动态的Web、Internet计算。从此...

远方Java ⋅ 06/14 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

20.zip压缩 tar打包 打包并压缩

6月25日任务 6.5 zip压缩工具 6.6 tar打包 6.7 打包并压缩 6.5 zip压缩工具: zip支持压缩目录 zip压缩完之后原来的文件不删除 不同的文件内容其实压缩的效果不一样 文件内有很多重复的用xz压...

王鑫linux ⋅ 12分钟前 ⋅ 0

double类型数据保留四位小数的另一种思路

来源:透析公式处理,有时候数据有很长的小数位,有的时候由在四位以内,如果用一般的处理方法,那么不足四位的小树会补充0到第四位,这样子有点画蛇添足的感觉,不太好看。所以要根据小数的...

young_chen ⋅ 19分钟前 ⋅ 0

Python 优化 回溯下降算法

使用sympy构造表达式,实现回溯下降算法 画出函数图像,先使用暴力搜索,找到最小值约为2.5左右 然后选定初始点,开始进行回溯搜索,下降方向为负梯度方向 下降的误差与步数大致呈现下面的状...

阿豪boy ⋅ 24分钟前 ⋅ 0

Django配置163邮箱出现 authentication failed(535)错误解决方法

最近用Django写某网站,当配置163邮箱设置完成后,出现535错误即:smtplib.SMTPAuthenticationError: (535, b'Error: authentication failed') Django初始配置邮箱设置 EMAIL_HOST = "smtp.1...

陈墨轩_CJX ⋅ 25分钟前 ⋅ 0

用接口模拟可伸缩枚举(34)

1、枚举的可伸缩性最后证明都不是什么好点子 扩展类型的元素是基本类型实例,基本类型的实例却不是扩展类型的元素,很混乱 目前还没有很好的方法来枚举基本类型的所有元素,及其扩展 可伸缩性...

职业搬砖20年 ⋅ 29分钟前 ⋅ 0

Ubuntu18.04 IDEA快捷键无法使用

IDEA默认的回退到上一视图的快捷键是Ctrl + Alt + Left,在ubuntu中这个快捷键被占用了,在16.04中可以在界面中取消这个快捷键,但是18.04就看不到了,可以使用以下命令解决 gsettings set ...

Iceberg_XTY ⋅ 33分钟前 ⋅ 0

如何解决s权限位引发postfix及crontab异常

一、问题现象 业务反馈某台应用服务器,普通用户使用mutt程序发送邮件时,提示“postdrop warning: mail_queue_enter: create file maildrop/713410.6065: Permission denied”,而且普通用法...

问题终结者 ⋅ 45分钟前 ⋅ 0

Unable to load database on disk

由于磁盘空间满了以后,导致zookeeper异常退出,清理磁盘空间后,zk启动报错,信息如下: 2018-06-25 17:18:46,904 INFO org.apache.zookeeper.server.quorum.QuorumPeerConfig: Reading co...

刀锋 ⋅ 今天 ⋅ 0

css3 box-sizing:border-box 实现div一行多列

<!DOCTYPE html><html><head><style> div.container{ background:green; padding:10px 10px;}div.box{box-sizing:border-box;-moz-box-sizing:border-box; /* Fir......

qimh ⋅ 今天 ⋅ 0

Homebrew简介和基本使用

一、Homebrew是什么 Homebrew是一款Mac OS平台下的软件包管理工具,拥有安装、卸载、更新、查看、搜索等很多实用的功能。简单的一条指令,就可以实现包管理,而不用你关心各种依赖和文件路径...

说回答 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部