java日期

来源:互联网 发布:淘宝的微淘怎么弄2016 编辑:程序博客网 时间:2024/06/11 06:20
参考:http://www.joda.org/joda-time/index.html
简介一下Joda-Time
这个是作为替代JDK的事件库而存在的。因为JDK的时间API有点不太好用。下面介绍一下:

获取属性
get方法
DateTime有一大波get方法,getDayOfYear,getDayOfWeek,getWeekOfWeekyear等等等等,终于,月份是从1开始了~~这些方法并不是DateTime实现的,而是父类AbstractDateTime实现的,仔细看源代码,具体实现的也不是AbstractDateTime类,而是Chronology(历法)类,这个类的职责,类似于日历,他的具体子类定义了不同种类的日历。细思极恐,居然可以把日历抽象到这种地步!!!

另外,补充一下year和yearOfEra的区别:
        DateTime dt = new DateTime(-100,1,1,0,0);
        System.out.println(dt.getYearOfEra());
        System.out.println(dt.getYear());
yearOfEra是带有公元/公元前的标志的,类似于我们说的6:00PM一样,year和yearOfEra在公元中是一样的,公元前则是不同的。year用负数表示公元前,yearOfEra则用正数,并且,绝对值差1。
输出:
101
-100
为啥捏?!
因为并没有公元0年这个概念,所以,不适用公元标志的时候,0是表示公元前1年,100表示公元前101年。
property属性
DateTime还有一个内置静态类,Property。也是获取年月日等属性,功能更加丰富:


           dt = new DateTime(2004,2,15,0,0);
           DateTime.Property year = dt.year();
           DateTime.Property month = dt.monthOfYear();
           DateTime.Property day = dt.dayOfMonth();
           System.out.println(year.isLeap());
           System.out.println(month.getAsShortText());
           System.out.println(day.getMaximumValue());
          //获取当月最后一天的日期
          System.out.println(day.setCopy(day.getMaximumValue()));

输出:
true
二月
29
2004-02-29T00:00:00.000+08:00
这些功能可以判断闰年,可以获取最大值等等。最后一个例子演示了如何求一个月的最后一天。setCopy可以返回当前属性修改后的DateTime对象。

日期计算
DateTime提供了大量易用的加减方法,用于日期的计算,作用类似于Calendar的Set方法,却比Set方法简单易用:

        //三周后的星期日
        DateTime dt = DateTime.now();
        System.out.println(dt
                .plusWeeks(3)
                .withDayOfWeek(DateTimeConstants.SUNDAY)
                .toString("yyyy-MM-dd HH:mm:ss.SSS EEEE"));

可以看到,DateTime用的都是比较直观的方式命名,plusWeeks,withDayOfWeek,其他的还有,plus从Years到Millis,with从Years到Millis,其实还有minus。这些命名方式,一看就明白。而且,支持链式操作(就是可以一直“点”下去),非常方便。要实现链式操作其实非常简单,每次返回一个DateTime对象就可以,不过这里不是为了支持链式操作才这么做的,而是因为他是不可变的,

那么什么是不可变
就是创建了的对象,什么属性,你都改不了。比如上面的plusWeeks,其实也没有改变本身,而是返回了一个加了3周后的对象,原来的对象,根本没有改变。

为什么要设计成不可变的
  • 设计使用简单:既然是不可变的,设计使用就简单得多,反正也不让你改,这样出错的可能也就少了。比如拷贝这个问题,DateTime这个类,根本就没实现拷贝接口!因为不需要,反正你不能改,直接拿去用。
  • 线程安全:反正你也不能改,当然可以自由的共享,也就是说,他是线程安全的~

withDayOfWeek 这个命名也是有讲究的,为什么是with而不是set,也是因为不可变的原因。

性能问题
jdk中也有许多不可变类,比如string,字符串拼接就有很大的性能问题,所以string还有个StringBuilder这种可变类。同理,DateTime也有可变的版本MutableDateTime。


时间间隔与时间段
时间间隔
Joda-Time使用Interval表示时间间隔。它含有两个属性,开始和结束。这是个半闭包结构,包括开始,不包括结束。

           DateTime dt2018 = new DateTime(2018,1,1,0,0);
           DateTime dt2017 = new DateTime(2017,1,1,0,0);
           DateTime dt2016 = new DateTime(2016,1,1,0,0);
           DateTime dt2015 = new DateTime(2015,1,1,0,0);

           Interval t0506 = new Interval(dt2015, dt2016);
           Interval t0507 = new Interval(dt2015, dt2017);
           Interval t0708 = new Interval(dt2017, dt2018);

           //判断是否相交
           System.out.println(t0506.overlaps(t0507));
           //判断是否包含
           System.out.println(t0506.contains(t0507));
           //求相交部分
           System.out.println(t0506.overlap(t0507));
           //求间距
           System.out.println(t0506.gap(t0708));
API中还有很多方法,我没有列出来,输出:
true
false
2015-01-01T00:00:00.000+08:00/2016-01-01T00:00:00.000+08:00
2016-01-01T00:00:00.000+08:00/2017-01-01T00:00:00.000+08:00
时间段
Duration和Period类,都表示时间段,细节上有所差别。英语的本意分别是“持续”和“周期”,Duration表示连续的时间段,毫秒为单位。而Period则表示周期性时间,比如年月日,一年一定是365天么,一个月一定是30天么,一天一定是24小时么,都不一定。而Period表示的就是这种时间。
这两种时间段,都可以和DateTime做时间加减:
           //100天
           Period days100 = Period.days(100);
           //2年
           Period years2 = Period.years(2);
           //2年3个月
           Period years2Months3 = years2.withMonths(3);

           DateTime dt = DateTime.now();

           System.out.println(dt.plus(days100));
           System.out.println(dt.minus(years2));
           System.out.println(dt.plus(years2Months3));

           Duration dayStandar2 = Duration.standardDays(2);
           Duration hourStandar3 = Duration.standardHours(3);

           System.out.println(dt.plus(dayStandar2));
           System.out.println(dt.minus(hourStandar3));

定义了这两个类,就更加准确的定义了时间段这个东西,有了这个东西,就可以准确的表示1天,到底是1天前还是24小时前这个问题了。再也不用担心沟通产生的歧义了~~

小结
个人感觉,时间段和时间间隔类的定义,一个是明确定义了几种我们常用的场镜,另一个就是简单实现了场镜中的方法。

格式化与解析
joda-time的格式化与解析的字母模板和JDK的是兼容的,所以,没什么好说的:

          DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMdd");
           System.out.println(fmt.print(DateTime.now()));

           DateTime dt2000 = fmt.parseDateTime("20000101");
           System.out.println(fmt.print(dt2000));

输出:
20170322
20000101


对象类型转换
在API中一堆to的方法就是喽~

0 0
原创粉丝点击