前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >吐槽java时间那点事儿 Joda Time

吐槽java时间那点事儿 Joda Time

作者头像
pollyduan
发布于 2019-11-04 05:38:21
发布于 2019-11-04 05:38:21
93900
代码可运行
举报
运行总次数:0
代码可运行

官网:http://www.joda.org/joda-time/

pom

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
  <groupId>joda-time</groupId>
  <artifactId>joda-time</artifactId>
  <version>2.9.7</version>
</dependency>

为什么要用joda?

创建对象

构建指定日期的时间(2017-02-21):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Calendar
Calendar calendar = Calendar.getInstance();
calendar.set(2017, 1, 21, 0, 0, 0);/*
槽点:明明是2月,第二个参数却要写1,蛋疼不蛋疼。当然也可用常量`Calendar.FEBRURY`替换`1`。

为什么不用Date(2017,1,21)? jdk本身在1.1就不推荐使用了,推荐用Calendar代替。
*/

//////////
//Joda-time
DateTime dateTime = new DateTime(2017, 2, 21, 0, 0);

时间跨度

joda提供了三种时间跨度类;

Duration :提供了日、时、分、秒、毫秒几个单位的工厂方法来创建。

Period:在Duration基础上增加了年、月、周作为单位。

Interval:这个类表示一个特定的时间跨度,将使用一个明确的时刻界定这段时间跨度的范围。Interval 为半开 区间,这表示由 Interval 封装的时间跨度包括这段时间的起始时刻,但是不包含结束时刻。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Duration duration=Duration.standardDays(3);
System.out.println(DateTime.now().minus(duration).toString());

Period period=Period.years(1);
System.out.println(DateTime.now().plus(period));

//Interval可以获得两个时间每个单位的时间差
DateTime dt1 = new DateTime(2008, 12, 8, 8, 31);
DateTime dt2 = new DateTime(2017, 2, 21, 17, 21);
Interval interval = new Interval(dt1.getMillis(), dt2.getMillis());
Period p = interval.toPeriod();
System.out.println(p.toString());
System.out.println("years:" + p.getYears()+";months:"+p.getMonths()
		+";days:"+p.getDays()+";hours:"+p.getHours()
		+";minutes:"+p.getMinutes()+";seconds:"+p.getSeconds()
		+";mills:"+p.getMillis());

时间计算

如果计算一下这个日期18天以后的时间呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Calendar
Calendar calendar = Calendar.getInstance();
calendar.set(2017, 1, 21, 0, 0, 0);
calendar.add(Calendar.DAY_OF_MONTH,18);
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str=df.format(calendar.getTime());
/*
槽点:明明返回一个Date却叫做getTime();如果返回一个时间戳,居然是getTime().getTime(),什么鬼?
*/
System.out.println(str);

//////////////////////////
//Joda-time
DateTime dateTime = new DateTime(2017, 2, 21, 0, 0);
String str=dateTime.plusDays(18).toString("yyyy-MM-dd HH:mm:ss");
System.out.println(str);

两个时间之间的时间差,需要借助时间跨度类。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//计算两个时间时间隔了多少天
DateTime dateTime=new DateTime(2008,12,8,0,0);
Duration duration=new Duration(dateTime,DateTime.now());
System.out.println(duration.getStandardDays());

joda-time与date的转换

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//date to dateTime
Date date=new Date();
DateTime dateTime = new DateTime(date.getTime());

//datetime to date
date=dateTime.toDate();

//calendar to datetime
Calendar calendar=Calendar.getInstance();
dateTime=new DateTime(calendar);

//datetime to calendar
calendar=dateTime.toCalendar(Locale.CHINA);
System.out.println(calendar);

局部时间

如果我们只关心日期或者时间,可以使用LocalDate和LocalTime类。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DateTime dateTime=DateTime.now();
String format="yyyy-MM-dd HH:mm:ss";
System.out.println(dateTime.toString(format));

LocalDate localDate=dateTime.toLocalDate();
System.out.println(localDate.toString());

LocalTime localTime=dateTime.toLocalTime();
System.out.println(localTime.toString());

注意:toString()有bug,需要开发者在编码阶段就去保证使用了正确的格式字符串。如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
System.out.println(localDate.toString("yyyy-MM-dd HH:mm:ss"));
//2017-02-21 ��:��:��

jdk 1.8也引入了这两个类,在java.time包中,但是一如既往的不方便操作仍然存在。他们处理这种格式化字符串的方式是抛 UnsupportedTemporalTypeException 异常。

时间格式化

joda通过ISODateTimeFormat类提供了一些工厂方法来创建不同的格式化,如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
System.out.println(DateTime.now().toString(ISODateTimeFormat.dateHourMinuteSecond()));
//2017-02-21T18:25:36

其他方法可查看javadocs,不过没有提供我们常用的yyyy-MM-dd HH:mm:ss,那么我们只有自己来构建了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
System.out.println(DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
//2017-02-21 18:26:49

Property(重要)

joda为每一个时间类创建一个内部静态类,叫Property,便于访问实例中的各个字段。而Joda更赋予了它强大的能力,就像穿越一样在时间线上游走。

由于它存在于多个类中,如果你希望先构建这个对象再使用,import包会有点小麻烦,因为名字一样存在于不同的类中。如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DateTime dateTime=DateTime.now();
Property property=dateTime.dayOfYear();
System.out.println(property.get());

这时应该 import org.joda.time.DateTime.Property;,有时使用ide时有可能误操作导入 org.joda.time.YearMonth.Property;等等。

正确的使用姿势是,把这个Property作为一个中间变量。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DateTime dateTime=new DateTime(2017,2,21,0,0);
//当月最后一天的日期 28
System.out.println(dateTime.dayOfMonth().getMaximumValue());
//当月最后一天的datetime 2017-02-28T17:00:00:000+08:00
System.out.println(dateTime.dayOfMonth().withMaximumValue());

类似的Property有:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
yearOfCentury
dayOfYear
monthOfYear
dayOfMonth
dayOfWeek

泛泛的说这些不太容易说清楚,看例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DateTime dateTime=new DateTime(2017,2,21,0,0);
System.out.println(dateTime.dayOfMonth()
    .setCopy(28)//穿越到2017-02-28
    .minusYears(9)//穿越到9年前
    .dayOfMonth()
    .withMaximumValue()//穿越到那年那月的最后一天,那天是29日
    .dayOfWeek()
    //.get()//29日那天是星期五
    .setCopy(1)//(不管29日是星期几)穿越到29日那天所在的星期一
    //Hello,我来过 2008-02-25T00:00:00.000+08:00

说明一下:setCopy是为前面的属性对应的字段指定一个值,并返回这个DateTime实例;withMaximumValue()是将这个值设置为该字段的最大值,并返回这个DateTime实例,它相当于是setCopy的一个特殊情况,withMinimumValue()同样的道理。

所以可以知道,最后一个setCopy(1) 替换为 withMinimumValue() 结论是一样的。

小结

Joda-time 的确是比jdk的Date和Calendar好用,但是(还是要说但是),实际开发中真的用得到这么细粒度的时间计算的场景并不多,往往我们常用的也就是获取当前时间,偶尔用一下从字符串到时间的parse操作,为了几次偶尔的操作引入一个jar的意义有多大,值得商榷。

而且(还有而且),很多框架使用Date很自然,比如ORM框架,而如果要使用joda还需要做一些附加的工作。

如此说来,joda-time 只是一个美好的故事,如果jdk能够完全吸收就完美了。BTW,java8中的Date Time API是遵循jsr310,该规范的主导者即是joda-time的作者 Stephen Colebourne,但Property和toString(fmt)特性并没有引入。

同样的境遇还有guava,不禁感慨:好事多磨啊。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
(33) Joda-Time / 计算机程序的思维逻辑
Joda-Time 上节介绍了JDK API中的日期和时间类,我们提到了JDK API的一些不足,并提到,实践中有一个广泛使用的日期和时间类库,Joda-Time,本节我们就来介绍Joda-Time。俗话说,工欲善其事,必先利其器,Joda-Time就是操作日期和时间的一把利器。 Joda-Time的官网是http://www.joda.org/joda-time/。它的基本概念和工作原理与上节介绍的是类似的,比如说,都有时刻和年历的概念,都有时区和Locale的概念,主要工作,都是在毫秒和年月日等年历信息
swiftma
2018/01/31
1K0
Joda-Time几个用法小记
1, 获取每天的零点 DateTime dt=new DateTime().withMillisOfDay(0); System.out.println(dt.toString("yyyy-MM-dd HH:mm:ss"));//结果2016-09-09 00:00:00 2, 在每天的6:30处理一些东西 DateTime dt=new DateTime().withHourOfDay(6).withMinuteOfHour(30).withSecondOfMinute(0); System.out.pr
我是攻城师
2018/05/14
1.1K0
Java 时间处理
在标准 Java 类库中包含一个 Date 类。它的对象表示一个特定的瞬间,精确到毫秒。
帅飞
2019/01/22
2.2K0
joda-time使用教程
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
suveng
2019/09/18
2.4K0
joda-time使用教程
Java基础组件快速入门
最近需要上线很多新的JAVA项目,然而很多JAVA的相关库都不太熟悉,项目实现起来遇到了不小阻力,熬了好几天夜。现在手头的工作基本完成了,因此打算好好来归纳下java的相关工具库,将来需要借助你们,好
用户1216676
2018/01/24
1.4K0
java8新特性整理
官方文档:http://docs.oracle.com/javase/specs/jls/se8/html/index.html
pollyduan
2019/11/04
1.1K0
[Java]Java日期及时间库插件 -- Joda Time.
来到新公司工作也有一个多月了, 陆陆续续做了一些简单的项目. 今天做一个新东西的时候发现了 Joda Time的这个东西, 因为以前用的都是JDK原生的时间处理API, 大家都知道Java原生的时间处理的API一直都是不太好用, 所以这个有必要去学习下, 去总结下. 来到新公司学到的东西挺多的, 比如我们用了Guava, ElasticSearch, kafka/mns/ons, GuavaCache/Ehcache/Memcahe .... 等很多东西都是我以前没有接触过的. 所以待我学习的东西还有很多.
一枝花算不算浪漫
2018/05/18
2.4K0
Java时间处理神器之Joda-Time
以前总觉得在Java里面处理各种日期转换很麻烦,虽然我也封装过一些工具包,但是总体感觉还是不够完美,也使用过一些开源的apachecommons里面的时间处理工具类感觉还是不够灵活和强大。 第一次与Joda-Time有一面之缘的时候,是在我使用ELK框架给公司做日志收集分析检索系统的时候,我发现使用jruby重写的logstash里面使用的时间处理工具类是joda-time,当时就对这个框架有点好奇,只不过没太注意,至于为什么会发现?相信搞过ELK的都知道logstash的时间处理比较独特,或者说不了解的情
我是攻城师
2018/05/14
2.3K0
每日一课:强大易用的日期和时间类库Joda-Time
https://pan.baidu.com/s/1qYWsYIg
BUG弄潮儿
2022/06/30
2910
JodaTime时间处理工具使用详解
工作中经常用到java日期类型Date、Calendar或SimpleDateFormat,但是这些日期工具类要么提供了过期的方法(Date),要么就是功能不够强大。最近突然用到了Joda-Time日期工具,发现非常好用,就撰写此文,以便学习和交流。
全栈程序员站长
2022/07/05
5570
Java基础篇(04):日期与时间API用法详解
在系统开发中,日期与时间作为重要的业务因素,起到十分关键的作用,例如同一个时间节点下的数据生成,基于时间范围的各种数据统计和分析,集群节点统一时间避免超时等。
知了一笑
2021/03/10
5820
Joda Time 使用
---- layout: default title: Joda Time 使用 category: [工具, Java] comments: true --- Joda Time 使用 对于系统的一些时间操作很是不方便,为了方便转化,有时候用date,有时候用timestmp,有时候用calendar,忍不住想更改了. 但是任务巨大,先把笔记收藏了,后面有机会再更改了.下面只是几个使用的例子. 1、 获取今天的开始时间:比如:2014-06-19 00:00:00 //joda
@坤的
2018/06/04
1.2K0
【Java8新特性】06 新的日期和时间:LocalDate LocalTime LocalDateTime
java.util.Date类是Jdk 1.0引入的,易用性非常糟糕,比如年份的起始是1900年,月份的起始是0。比如要表示2019年6月18日,创建一个Date实例:
爱笑的架构师
2020/09/24
1.3K0
【Java8新特性】06 新的日期和时间:LocalDate LocalTime LocalDateTime
【程序猿硬核科普】Java获取指定时间年月日 | 时间戳转换bug你的项目中招了吗 | yyyy和YYYY的区别
最近在知乎看到有篇回答说:跨年导致日期格式YYYY和yyyy导致日期显示Bug的帖子,微信公众号、一些论坛好多中招了,快来看看你的项目里面有没有这个bug吧,哈哈lo(╥﹏╥)o。
浩Coding
2020/02/13
2.3K0
【程序猿硬核科普】Java获取指定时间年月日 | 时间戳转换bug你的项目中招了吗 | yyyy和YYYY的区别
Java 8新特性 全新的日期时间API
Java 8 Date Time AP 是受开发者最受追捧的变更。 java在之前并没有处理日期、时间的一致性方法。
青山师
2023/05/04
5020
java8的日期API总结(JSR310)
有了 java.util.Date 又搞出个java.sql.Date,改个名字不行?
pollyduan
2019/11/04
9970
Java8新特性时间日期库DateTime API及示例
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
程序新视界
2019/10/22
1.2K0
Java日期计算常用方法《简述版》
总的来说,Java 8 引入的java.time包提供了更为方便和灵活的日期计算方式,避免了以前java.util.Calendar的繁琐操作。根据需要,选择适合的日期类和方法来执行日期计算和操作。
猫头虎
2024/04/07
1190
玩转 Java 时间 + 面试题
在 JDK 8 之前,Java 语言为我们提供了两个类用于操作时间,它们分别是:java.util.Date 和 java.util.Calendar,但在 JDK 8 的时候为了解决旧时间操作类的一些缺陷,提供了几个新的类,用于操作时间和日期,它们分别是:LocalTime、LocalDateTime、Instant,都位于 java.time 包下。时间的操作在我们日常的开发中经常见到,比如,业务数据都要记录创建时间和修改时间,并要把这些时间格式化之后显示到前端页面,再比如我们需要计算业务数据的时间间隔等,都离不开对时间的操作,那如何正确而优雅地使用时间?这就是我们接下来要讨论的话题。
架构师修炼
2020/07/17
1.1K0
Java8新特性:新的时间和日期类库
Java 8另一个新增的重要特性就是引入了新的时间和日期API,它们被包含在java.time包中。借助新的时间和日期API可以以更简洁的方法处理时间和日期。
我的小碗汤
2019/07/30
1.7K0
推荐阅读
相关推荐
(33) Joda-Time / 计算机程序的思维逻辑
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文