吐槽java时间那点事儿 Joda Time

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

pom

<dependency>
  <groupId>joda-time</groupId>
  <artifactId>joda-time</artifactId>
  <version>2.9.7</version>
</dependency>

为什么要用joda?

创建对象

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

//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 封装的时间跨度包括这段时间的起始时刻,但是不包含结束时刻。

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天以后的时间呢?

//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);

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

//计算两个时间时间隔了多少天
DateTime dateTime=new DateTime(2008,12,8,0,0);
Duration duration=new Duration(dateTime,DateTime.now());
System.out.println(duration.getStandardDays());

joda-time与date的转换

//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类。

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,需要开发者在编码阶段就去保证使用了正确的格式字符串。如:

System.out.println(localDate.toString("yyyy-MM-dd HH:mm:ss"));
//2017-02-21 ��:��:��

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

时间格式化

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

System.out.println(DateTime.now().toString(ISODateTimeFormat.dateHourMinuteSecond()));
//2017-02-21T18:25:36

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

System.out.println(DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
//2017-02-21 18:26:49

Property

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

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

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作为一个中间变量。

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

yearOfCentury
dayOfYear
monthOfYear
dayOfMonth
dayOfWeek

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

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能够完全吸收就完美了。

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

时间: 2024-09-08 04:19:33

吐槽java时间那点事儿 Joda Time的相关文章

java 时间运算 类型转换

问题描述 java 时间运算 类型转换 获得当前时间(yy-MM-dd HH-mm-ss)t1,每天规定时间t2(HH-mm-ss) t1与t2相减运算得到int类型的数据结果 解决方案 Date().getTime() 就能将时间转为数字,我感觉你想做定时器..相见java Timer类

Java 时间转换的实例代码_java

Java 时间转换的实例代码 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * Created by Edward on 2016/6/30. */ public class TimeUtil { /** * 将 1467341232351 转换为 指定格式 "yyyy-MM-dd HH:mm:ss.

Java时间:GMT以及UTC

Edit Java时间:GMT以及UTC GMT即格林威治标准时间,以英国伦敦郊区皇家格林威治天文台的标准时间.世界被分为24个时区.而北京在东八区 UTC即世界协调时间,以格林威治时间为准,经过平均太阳时等修正后,以秒为单位的国际原子时所综合计算而成的时间.所以UTC比GMT更加精准. Java Date使用UTC时间,如Tue Nov 11 16:59:08 CST 2014,CST表示China Standard Time UT+8:00 由于Date的相关 API 不易于实现国际化.从

JAVA时间日期处理类实例_java

本文实例讲述了JAVA时间日期处理类,主要用来遍历两个日期之间的每一天.分享给大家供大家参考.具体如下: /** * * 文 件 名: AccountDate.java * * 创建时间: 2008-11-18 * * Email : **@163.com */ import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.A

java 时间比较

问题描述 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");Date dt=sdf.parse("1901-01-01");system.out.println(dt);WfAcptTbl wfAcptTbl = new WfAcptTbl();wfAcptTbl.setAcptDt(dt);system.out.println(wfAcptTbl.getAcptDt());system.out.prin

最全的java时间处理工具类

package com.momo.util;import java.io.Serializable;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;import java.util.GregorianCalendar;/** * @company:hrj * @author:章小飞 * @since:2007-12-3

java时间日期格式化工具类程序

例1.整理了一份可重用的日期格式化工具类,在日常开发中悲催的程序员离不开这个工具类的 下面给大家把java日期工具类代码贡献上:  代码如下 复制代码 /**  * 日期工具类-www.111cn.net网整理  * 默认使用 "yyyy-MM-dd HH:mm:ss" 格式化日期  * @author xw素材网  */ public final class DateUtils { /** * 英文简写(默认)如:2010-12-01 */ public static String

java时间处理工具类

1 import java.io.PrintStream; 2 import java.sql.Time; 3 import java.sql.Timestamp; 4 import java.text.ParsePosition; 5 import java.text.SimpleDateFormat; 6 import java.util.Date; 7 public class TimeUtil 8 { 9 /* 10 * java编程 11 */ 12 public TimeUtil()

Java时间帮助类DateUtil

  package com.xy.util; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class DateUtil {  public static final String yyMMdd = "yy-MM-dd";  public static final String yyyyMMdd = "yyyy-MM-dd&qu