吐槽java时间那点事儿 Joda Time
2017-02-21 18:57
225 查看
官网:http://www.joda.org/joda-time/
pom
Duration:提供了日、时、分、秒、毫秒几个单位的工厂方法来创建。
Period:在Duration基础上增加了年、月、周作为单位。
Interval:这个类表示一个特定的时间跨度,将使用一个明确的时刻界定这段时间跨度的范围。Interval 为半开 区间,这表示由 Interval 封装的时间跨度包括这段时间的起始时刻,但是不包含结束时刻。
两个时间之间的时间差,需要借助时间跨度类。
注意:toString()有bug,需要开发者在编码阶段就去保证使用了正确的格式字符串。如:
jdk 1.8也引入了这两个类,在java.time包中,但是一如既往的不方便操作仍然存在。他们处理这种格式化字符串的方式是抛 UnsupportedTemporalTypeException 异常。
其他方法可好看javadocs,不过没有提供我们常用的
由于它存在于多个类中,如果你希望先构建这个对象再使用,import包会有点小麻烦,因为名字一样存在于不同的类中。如:
这时应该
正确的使用姿势是,把这个Property作为一个中间变量。
类似的Property有:
泛泛的说这些不太容易说清楚,看例子:
说明一下:setCopy是为前面的属性对应的字段指定一个值,并返回这个DateTime实例;withMaximumValue()是将这个值设置为该字段的最大值,并返回这个DateTime实例,它相当于是setCopy的一个特殊情况,withMinimumValue()同样的道理。
所以可以知道,最后一个
而且(还有而且),很多框架使用Date很自然,比如ORM框架,而如果要使用joda还需要做一些附加的工作。
如此说来,joda-time 只是一个美好的故事,如果jdk能够完全吸收就完美了。
同样的境遇还有guava,不禁感慨:好事多磨啊。
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,不禁感慨:好事多磨啊。
相关文章推荐
- 替代Java类的日期和时间【 Joda Time】
- JAVA中的时间操作
- Java的时间处理(续<计算Java时间>)
- 《Java 手机/PDA 程序设计入门》读书笔记8--LCDAUI低级API之 线程 时间控制
- 时间和日历类的设计(Java的Date和Calendar的C++实现)
- (转载)java语言对时间的处理
- 时间和日历类的设计(Java的Date和Calendar的C++实现)
- Java的时间处理(续)
- Java时间转换问题
- java中时间格式匹配
- java获取Date时间的各种方式汇总
- 用Java做时间的减法
- java时间日期方法
- java语言时间日期学习
- Java走势分析 --作者:清华大学 王克宏 丁峰 发文时间:2003.03.26 10:18:40
- Java实现时间日期格式转换示例
- JAVA日期和时间类彻底解决(2)
- Java的时间处理(续)
- java中关于星期时间的操作
- Java的时间格式