Java基础之如何取舍Joda与 Java8 日期库

2020/3/1 17:14:58

本文主要是介绍Java基础之如何取舍Joda与 Java8 日期库,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

在 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:

DateTime dt = new DateTime();
DateTime dt1 = new DateTime();
Interval interval = new Interval(dt.toInstant(), dt1.toInstant());
Duration duration = interval.toInstant();
复制代码

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

原文

关注微信公众号,聊点其他的



这篇关于Java基础之如何取舍Joda与 Java8 日期库的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程