InfoQ

InfoQ

新闻

我的书签

登录注册 以永久保存书签。

该内容已经被标记书签!

标记书签错误,请重试!

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

作者 Kostis Kapelonis 译者 贾国清 发布于 2011年12月4日

领域
语言 & 开发
主题
JSR 310 ,
JCP标准 ,
JCP ,
Java ,
语言 ,
编程

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中文站高级策划编辑,热爱生活,喜欢旅游和体育运动。

好东西 发表人 冯 光头 发表于
什么情况下需要这么高精度? 发表人 liu leo 发表于
Calendar or util.Date? 发表人 Wang Yuxing 发表于
  1. 返回顶部

    好东西

    发表人 冯 光头

    不知道使用方便不

  2. 返回顶部

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

    发表人 liu leo

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

  3. 返回顶部

    Calendar or util.Date?

    发表人 Wang Yuxing

    一般用Calendar的说