java 基础之如何取舍 joda 与 java8 日期库 · 物联网平台-威尼斯人最新

so_cool · 2020年03月08日 · 最后由 回复于 2022年09月03日 · 307 次阅读

在 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 用起来更加顺手一些,暂时还会继续使用这个。

转载自:

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册
网站地图