BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

Date4j,一个简约的日期处理类库

| 作者 Kostis Kapelonis 关注 0 他的粉丝 ,译者 贾国清 关注 0 他的粉丝 发布于 2011年12月5日. 估计阅读时间: 7 分钟 | Google、Facebook、Pinterest、阿里、腾讯 等顶尖技术团队的上百个可供参考的架构实例!

Java本身的日期类在JDK1.0版本之后就再也没有更新过,同时还存在着一些众所周知的问题(例如1月从0开始,导致了很多月份差一的漏洞)。一份新的Java规范请求(JSR,Java Specification Request)已经被提交,目的就是要解决上述问题,此版本的类库仍处在Alpha版本。在其稳定之前,很多开发者还是会使用Joda Time类库,该类库与JSR-310的参考实现类似(但不完全相同)。

Date4j为在Java中处理日期提供了一套新的解决方案,但与Joda Time所关注的范围完全不同。对比如下:

Joda Time Date4j
拥有的类的数量: 140+ 拥有的类的数量< 10
包含可变和不可变类 仅包含不可变类
强调速度和功能 强调简单和有效
支持格里高里历(Gregorian)、 科普特语日历(Coptic)、 伊斯兰教历(Islamic)、佛历(Buddhist)等等 只提供对格里高里历的支持
可以完全取代JDK日期类 和JDK日期类配合使用
精确到毫秒级操作 支持到纳秒(十亿分之一秒)级操作
修复了天“溢出”的问题 天“溢出”的问题可配置
针对的是通常意义的日期维护 适用于通过数据库来维护的日期
采用Apache 2.0授权许可 采用BSD授权许可

虽然乍一看Date4j只具备了Joda中一部分的特性,但它有两个主要的特点是Joda所不具备的。

首先,Date4j的开发者宣称类库不应莫名其妙地将日期截断。Joda只支持毫秒级的精度而且在将来可能也不会改善。一些数据库也已经有了更好的解决方案。比如流行的PostgreSQL数据库对时间戳精度就已经支持到微秒级(百万分之一秒)。Date4j可在处理日期时对精度毫无损伤。

第二个特征是日期“溢出”的问题,例如向某个日期增加一段时间后,日期落在下月的情况。最简单的例子就是在3月31日增加一个月的计算:

DateTime dt = new DateTime("2011-03-31");
DateTime result = dt.plusMonths(1);
System.out.println(result.toString());

当使用Joda Time时,会输出4月30日,但这也许并不是你想要的结果。

鉴于这种不确定性,Date4j为您提供了4种选择

1. 第一天
2. 最后一天(与Joda Time相同)
3. 日期顺延
4. 抛出异常

以下通过举例的实例来说明,用Date4j替换Joda后的输出差异:

DateTime dt1 = new DateTime("2011-03-31");
DateTime result1 = dt1.plus(0,1,0,0,0,0,DayOverflow.FirstDay);
System.out.println(result1.toString());
//会输出 2011-05-01 (5月的第一天)
		
DateTime dt2 = new DateTime("2011-03-31");
DateTime result2 = dt2.plus(0,1,0,0,0,0,DayOverflow.LastDay);
System.out.println(result2.toString());
//会输出 2011-04-30(4月30日,与Joda输出结果相同)

DateTime dt3= new DateTime("2011-03-31");
DateTime result3 = dt3.plus(0,1,0,0,0,0,DayOverflow.Abort);
System.out.println(result3.toString()); 
//抛出运行时异常(Runtime Exception) 

下面的代码展示了DayOverflow.Spillover中的选项:

//Joda Time代码
DateTime dt = new DateTime("2010-12-31");
DateTime result = dt.plusMonths(2);
System.out.println(result.toString());
//输出2011-02-28(2月的最后一天)

//Date4j代码
DateTime dt1 = new DateTime("2010-12-31");
DateTime result1 = dt1.plus(0,2,0,0,0,0,DayOverflow.FirstDay);
System.out.println(result1.toString());
//输出 2011-03-01(3月的第一天)

//Date4j代码
DateTime dt2 = new DateTime("2010-12-31");
DateTime result2 = dt2.plus(0,2,0,0,0,0,DayOverflow.LastDay);
System.out.println(result2.toString());
//输出 2011-02-28 (2月28日,与Joda输出相同)

//Date4j代码
DateTime dt3= new DateTime("2010-12-31");
DateTime result3 = dt3.plus(0,2,0,0,0,0,DayOverflow.Spillover);
System.out.println(result3.toString()); 
//输出 2011-03-02(3月第二天)

如果应用对精度要求较高并且在处理数据库日期时不想对精度有所损失,或者在处理跨月份日期时想有更灵活的方案供选择,Date4j会是一个不错的选择。现在,源代码已可直接下载

查看英文原文:Date4j - A Minimalistic Library for Handling Dates

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

好东西 by 冯 光头

不知道使用方便不

什么情况下需要这么高精度? by liu leo

从业务逻辑上讲,java date类库的主要问题是:
1. 没有区分DateOnly & DateTime
2. 很多object都是mutable的

Calendar or util.Date? by Wang Yuxing

一般用Calendar的说

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

3 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT