在Java中处理日期和时间是很常见的需求,基础的工具类就是我们熟悉的Date和Calendar,然而这些工具类的api使用并不是很方便和强大,于是就诞生了Joda-Time这个专门处理日期时间的库。
由于Joda-Time很优秀,在Java 8出现前的很长时间内成为Java中日期时间处理的事实标准,用来弥补JDK的不足。在Java 8中引入的java.time
包是一组新的处理日期时间的API,遵守JSR 310
。值得一提的是,Joda-Time的作者Stephen Colebourne
和Oracle一起共同参与了这些API的设计和实现。
值得注意的是,Java 8中的java.time
包中提供的API和Joda-Time并不完全相同。比如,在Joda-Time中常用的Interval
(用来表示一对DateTime),在JSR 310
中并不支持。因此,另一个名叫Threeten的第三方库用来弥补Java 8的不足。Threeten翻译成中文就是310的意思,表示这个库与JSR 310
有关。它的作者同样是Joda-Time的作者Stephen Colebourne
。
Threeten主要提供两种发行包:ThreeTen-Backport和ThreeTen-Extra。前者的目的在于对Java 6和Java 7的项目提供Java 8的date-time类的支持;后者的目的在于为Java 8的date-time类提供额外的增强功能(比如:Interval
等)。
由于刚接触Joda-Time,并且目前的工作环境还未涉及到Java 8。因此,关于Java 8的date-time和Threeten的API,将在以后合适的时候介绍。这篇文章关注Joda-Time的使用。
总之,作为一种解决某一问题领域的工具库,我认为有以下几个方面值得关注:
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.2</version>
</dependency>
下面介绍5个最常用的date-time类:
注意:不可变的类,表明了正如Java的String类型一样,其对象是不可变的。即,不论对它进行怎样的改变操作,返回的对象都是新对象。
Instant比较适合用来表示一个事件发生的时间戳。不用去关心它使用的日历系统或者是所在的时区。 DateTime的主要目的是替换JDK中的Calendar类,用来处理那些时区信息比较重要的场景。 LocalDate比较适合表示出生日期这样的类型,因为不关心这一天中的时间部分。 LocalTime适合表示一个商店的每天开门/关门时间,因为不用关心日期部分。
作为Joda-Time很重要的一个类,详细地看一下它的用法。
如果查看Java Doc,会发现DateTime有很多构造方法。这是为了使用者能够很方便的由各种表示日期时间的对象构造出DateTime实例。下面介绍一些常用的构造方法:
1970-01-01T00:00:00Z
的毫秒数。使用默认的时区。ISO8601
格式,详见:ISODateTimeFormat.dateTimeParser()下面举几个例子:
当你有一个DateTime实例的时候,就可以调用它的各种方法,获取需要的信息。
注意,在增减时间的时候,想象成自己在翻日历,所有的计算都将符合历法,由Joda-Time自动完成,不会出现非法的日期(比如:3月31日加一个月后,并不会出现4月31日)。
有时我们需要对一个DateTime的某些属性进行置0操作。比如,我想得到当天的0点时刻。那么就需要用到Property中round开头的方法(roundFloorCopy)。如下面的例子所示:
其它:还有许多其它方法(比如dateTime.year().isLeap()来判断是不是闰年)。它们的详细含义,请参照Java Doc,现查现用,用需求驱动学习。
Joda-Time默认使用的是ISO的日历系统,而ISO的日历系统是世界上公历的事实标准。然而,值得注意的是,ISO日历系统在表示1583年之前的历史时间是不精确的。 Joda-Time默认使用的是JDK的时区设置。如果需要的话,这个默认值是可以被覆盖的。 Joda-Time使用可插拔的机制来设计日历系统,而JDK则是使用子类的设计,比如GregorianCalendar。下面的代码,通过调用一个工厂方法获得Chronology的实现:
时区是作为chronology的一部分来被实现的。下面的代码获得一个Joda-Time chronology在东京的时区:
Joda-Time为时间段的表示提供了支持。
虽然,这三个类都用来表示时间段,但是在用途上来说还是有一些差别。请看下面的例子:
因为当时那个地区执行夏令时的原因,在添加一个Period的时候会添加23个小时。而添加一个Duration,则会精确地添加24个小时,而不考虑历法。所以,Period和Duration的差别不但体现在精度上,也同样体现在语义上。因为,有时候按照有些地区的历法 1天 不等于 24小时。
这篇文章参考了Joda-Time的官方文档:Quick Start,并加上了自己的理解。 涉及到更多的需求和用法(比如“日期时间的格式化”等),可以参考官方文档:User Guide。