在 java8 以前,时间和日期的类库很难用,而且有线程安全等诸多问题。
joda time 弥补了 java 在这方面的不足,但是在 java8 时,增加了 java.time 包,对 java 在日期 api 方面的进行了增强,这些代码实现了 jsr-310 的标准。joda 的官方推荐迁移到 java8 的时间类库上来。
下面来详细对比对比一下两个类库,看看 java8 的日期 api 是否能真正替代 joda time。
基础概念对比 joda date 的核心概念,这些概念在 java time 中基本也能找到对应:
instant 表示一个时刻,使用从 1970-01-01 00:00:00 至今的毫秒数表示
joda time:
datetime dt = new datetime();
instant instant = dt.toinstant();
java time:
clock clock = clock.systemdefaultzone();
instant instant = clock.instant();
interval 表示两个 instant 之间的间隔,左闭右开。
joda time:
datetime dt = new datetime();
datetime dt1 = new datetime();
interval interval = new interval(dt.toinstant(), dt1.toinstant());
java time 中没有提供类似的 api,因为 jsr-310 标准中没有这个概念。
duration 用毫秒表示的时间段,通常从 interval 获得 joda time:
java time:
localdatetime l1 = localdatetime.now();
localdatetime l2 = localdatetime.now();
period period = period.between(l1.tolocaldate(), l2.tolocaldate());
period 同样表示时间段,比如 3 年,5 个月,而 duration 使用毫秒表示
joda time:
datetime dt1 = new datetime();
datetime dt2 = new datetime();
period period = period.fielddifference(dt1.tolocaldatetime(), dt2.tolocaldatetime());
java time:
localdatetime l1 = localdatetime.now();
localdatetime l2 = localdatetime.now();
period period = period.between(l1.tolocaldate(), l2.tolocaldate());
chronology 年表,这是 joda-time 设计的基础
joda time:
datetime dt = new datetime();
chronology chronology = dt.getchronology();
java time:
localdatetime localdatetime = localdatetime.now();
chronology ch = localdatetime.getchronology();
timezones 表示时区。
joda time:
datetime dt = new datetime();
datetimezone datetimezone = dt.getzone();
set<string> zones = datetimezone.getavailableids();
java time:
clock clock = clock.systemdefaultzone();
zoneid zoneid = clock.getzone();
set<string> zones = zoneid.getavailablezoneids();
从上面可以看到,除了 jsr-310 中没有的 interval 的定义之外,这两个库在基础概念方面的实现相差不大。
因为 unix 系统从 1970-01-01 00:00:00 开始计时,这个时间也称之为 epoch time,后续使用 unix 的这种计时方式。
具体使用 joda time 依赖 jdk5 及后续版本,没有额外的依赖。
为了起到对比的效果,挑几个比较常用的场景进行对比:
获取 1970 至今的毫秒数 获取当前时间 获取年、月、日、星期几 日期的增减 日期的格式化 获取时间戳 在代码中,经常会使用这个功能来表示唯一性:
joda time:
datetime dt = new datetime();
long mills = dt.getmillis();
java time:
clock clock = clock.systemdefaultzone();
long mills = clock.millis();
获取当前时间 这块两个库没有太大的差异:
joda time:
datetime dt = new datetime();
localdatetime localdatetime = dt.tolocaldatetime();
java time:
localdatetime localdatetime = localdatetime.now();
获取年、月、日、星期几 joda time:
datetime dt = new datetime();
int dayofyear = dt.getdayofyear();
int dayofmonth = dt.getdayofmonth();
int dayofweek = dt.getdayofweek();
int hourofday = dt.gethourofday();
java time:
clock clock = clock.systemdefaultzone();
localdatetime localdatetime = localdatetime.now(clock);
int dayofyear = localdatetime.getdayofyear();
int dayofmonth = localdatetime.getdayofmonth();
int dayofweek = localdatetime.getdayofweek().getvalue();
int hourofday = localdatetime.gethour();
获取这些值两个库也没有太大的差异,但是对于一些场景,比如我想获得 "星期四" 这个字符串。 在 joda 库中,可以 dt.dayofweek().getasshorttext(); // 星期四 这样获得。在 java 中,localdatetime.getdayofweek().name(); //thursday 只能获取到英文。
joda time 在本地化方面比 java time 做的更好。
日期增减 joda time:
datetime dt = new datetime();
dt = dt.plusdays(2); //当前日期添加两天
dt = dt.plushours(5); // 当前时间加上两个小时
dt = dt.minusdays(1); // 当前日期减一天
dt = dt.minushours(2); // 当前日期减两个小时
java time:
localdatetime localdatetime = localdatetime.now();
localdatetime = localdatetime.plusdays(2); // 增加两天
localdatetime = localdatetime.plushours(2); // 增加两个小时
localdatetime = localdatetime.minusdays(1); //减少一天
localdatetime = localdatetime.minushours(1); // 减少一个小时
日期的格式化 日期格式化是日常使用最频繁的功能,下面来对比一下这两者的区别。
joda time:
// 方式一
datetimeformatter formatter = datetimeformat.forpattern("yyyy-mm-dd hh:mm:ss");
datetime dt = new datetime();
system.out.println(dt.tostring(formatter));
// 方式二
string dateformat = "yyyy-mm-dd hh:mm:ss";
system.out.println(dt.tostring(dateformat));
java time:
datetimeformatter formatter = datetimeformatter.ofpattern("yyyy-mm-dd hh:mm:ss");
localdatetime localdatetime = localdatetime.now(); system.out.println(formatter.format(localdatetime));
通过上面的对比,可以发现这两个类库都可以完成相同的功能。虽然在细节上是有一些细微的差别。
java.util.date 是 java 中最早的日期类,后来就不推荐使用这个类了,java.util.calendar 用来替代 date。calendar 有 date 的所有功能,并且提供了更加丰富的获取年月日的 api。
calendar 是一个虚拟类,gregoriancalendar 则是 calendar 的实现类。
java time 与 java.util 下的时间类相互转化,可以将 date 或者 calendar 转化成 java time 中的 localdatetime.
java.util.date 转 java.time.localdatetime:
date date = new date();
localdatetime localdatetime = localdatetime.ofinstant(date.toinstant(), zoneid.systemdefault());
java.util.carlendar 转 java.time.localdatetime:
calendar calendar = calendar.getinstance();
localdatetime localdatetime = localdatetime.ofinstant(calendar.toinstant(), zoneid.systemdefault());
joda time 也可以与 java.util.date 可以进行相互的转化:
// from joda to jdk
datetime dt = new datetime();
date jdkdate = dt.todate();
// from jdk to joda
dt = new datetime(jdkdate);
// from joda to jdk
datetime dt = new datetime();
calendar jdkcal = dt.tocalendar(locale.chinese);
// from jdk to joda
dt = new datetime(jdkcal);
// from joda to jdk
datetime dt = new datetime();
gregoriancalendar jdkgcal = dt.togregoriancalendar();
// from jdk to joda
dt = new datetime(jdkgcal);
设计思想 joda time 与 java time 在功能上已经相差不大,常用的功能这两个类库都可以完成,而且两个库都是线程安全的。
但我认为 joda time 的 api 更加简洁一些,joda time 的使用可以直接从 datetime 这个类开始。而 java time 的使用则更加繁琐。
从设计上来说 java time 都不再使用 new 来创建实例,而是使用工厂方法来创建实例。这点上比 joda time 的设计要更好,而且更加安全。
既然 joda time 都推荐迁移回 java time 了,那么最终肯定是要迁移的。但是目前来说,我觉得 joda time 用起来更加顺手一些,暂时还会继续使用这个。
转载自: