这里我们先来认识一下Joda-time有哪些有关时间的重要类吧。
一、日期和时间
首先说明一点的就是Joda-time里面的时间全都是不可变的,也就是不可变性,这点我会在本文最后介绍。
DateTime:类似于JDK中的Calendar,提供了更多的方法。
DateMidnight:这个概念稍微复杂,封装某个时区(通常为默认时区)在特定年/月/日的午夜时分的时刻。它基本上类似于 DateTime,不同之处在于时间部分总是为与该对象关联的特定 DateTimeZone 时区的午夜时分。
LocalDate:无时间的类,只包含年月日。(不包含时区)
LocalTime:无日期的类,只包含时间。(不包含时区)
LocalDateTime:包含日期和时间。(不包含时区)
下面举一些简单的例子说明Joda-time的强大之处。
获取当前月份:
1 2 |
DateTime dt = new DateTime(); int month = dt.getMonthOfYear(); |
设定2000年/获取当前小时+2的小时:
1 2 3 4 5 |
DateTime dt = new DateTime(); DateTime year2000 = dt.withYear(2000); DateTime twoHoursLater = dt.plusHours(2); System.out.println(year2000.getYear()); System.out.println(twoHoursLater.getHourOfDay()); |
以及下面的一些操作:
1 2 3 4 5 6 7 8 |
String monthName = dt.monthOfYear().getAsText(); String frenchShortName = dt.monthOfYear().getAsShortText(Locale.FRENCH); boolean isLeapYear = dt.year().isLeap(); DateTime rounded = dt.dayOfMonth().roundFloorCopy(); System.out.println(monthName); // 本地月份名称 System.out.println(frenchShortName); // 法语月份简称 System.out.println(isLeapYear); // 是否闰年 System.out.println(rounded); // 获取当天0:0:0的DateTime对象 |
二、日历系统及时区
Joda-time支持多种年表(即日历系统)及所有时区。主要的两个类如下:
Chronology:年表,Joda-time支持很多年表。就像JDK有Calendar,也有GregorianCalendar。
DateTimeZone:时区。
示例如下,一般系统都没有这个需求。
1 2 3 4 5 6 |
Chronology coptic = CopticChronology.getInstance(); System.out.println(coptic); // CopticChronology[Asia/Shanghai] DateTimeZone zone = DateTimeZone.forID("Asia/Tokyo"); Chronology gregorianJuian = GJChronology.getInstance(zone); System.out.println(gregorianJuian); // GJChronology[Asia/Tokyo] |
三、时间跨度
Joda-time支持的时间跨度有三个,分别如下:
Interval:根据开始、结束时间表示一个特定的时间跨度。其为半开区间,即包括起始时刻,不包含结束时刻。
Period:Period设定了一些特定的时间跨度,比如小时、天、月。
Duration:表示绝对的精准跨度,以毫秒为单位。
部分使用示例如下:
1 2 3 4 5 6 7 8 9 10 11 |
DateTime beginDateTime = new DateTime(2010, 1, 1, 0, 0, 0); DateTime endDateTime = new DateTime(2015, 1, 1, 0, 0, 0); Interval interval = new Interval(beginDateTime, endDateTime); System.out.println(interval.containsNow()); // 是否包含当前时间 System.out.println(interval.toDurationMillis()); // 时间间隔毫秒数 DateTime dt = new DateTime(2005, 3, 26, 12, 0, 0, 0); DateTime plusPeriod = dt.plus(Period.days(1)); System.out.println(plusPeriod); // Period的方式+1天 DateTime plusDuration = dt.plus(new Duration(24L * 60L * 60L * 1000L)); System.out.println(plusDuration); // Duration的方式+1天 |
四、Joda-time使用的理念
不可变性(Immutability)
瞬间性(Instant)
局部性(Partial)
年表(Chronology)
时区(Time zone)
不可变性
Joda-time的类具有不可变性,因此它们的实例无法被修改。(不可变类的一个优点就是它们是线程安全的)。用于处理日期计算的 API 方法全部返回一个对应 Joda-time 类的新实例,同时保持原始实例不变。当我们通过一个 API 方法操作 Joda 类时,我们必须捕捉该方法的返回值,因为我们正在处理的实例不能被修改。你可能对这种模式很熟悉,这正是 java.lang.String 的各种操作方法的工作方式。
瞬间性
Instant 表示时间上的某个精确的时刻,使用从 epoch 开始计算的毫秒表示。这一定义与 JDK 相同,这就是为什么任何 Joda Instant 子类都可以与 JDK Date 和 Calendar 类兼容的原因。
更通用一点的定义是:一个瞬间 就是指时间线上只出现一次且唯一的一个时间点,并且这种日期结构只能以一种有意义的方式出现一次。
局部性
一个局部时间,正如我将在本文中将其称为局部时间片段一样,它指的是时间的一部分片段。瞬间性指定了与 epoch 相对的时间上的一个精确时刻,与此相反,局部时间片段指的是在时间上可以来回 “移动” 的一个时刻,这样它便可以应用于多个实例。比如,6 月 2 日 可以应用于任意一年的 6 月份(使用 Gregorian 日历)的第二天的任意瞬间。同样,11:06 p.m. 可以应用于任意一年的任意一天,并且每天只能使用一次。即使它们没有指定一个时间上的精确时刻,局部时间片段仍然是有用的。
我喜欢将局部时间片段看作一个重复周期中的一点,这样的话,如果我正在考虑的日期构建可以以一种有意义的方式出现多次(即重复的),那么它就是一个局部时间。
年表
Joda 本质——以及其设计核心——的关键就是年表(它的含义由一个同名抽象类捕捉)。从根本上讲,年表是一种日历系统——种计算时间的特殊方式——并且是一种在其中执行日历算法的框架。受 Joda 支持的年表的例子包括:ISO(默认)、Coptic、Julian、Islamic等。
时区
时区是值一个相对于英国格林威治的地理位置,用于计算时间。要了解事件发生的精确时间,还必须知道发生此事件的位置。任何严格的时间计算都必须涉及时区(或相对于 GMT),除非在同一个时区内发生了相对时间计算(即时这样时区也很重要,如果事件对于位于另一个时区的各方存在利益关系的话)。
DateTimeZone 是 Joda 库用于封装位置概念的类。许多日期和时间计算都可以在不涉及时区的情况下完成,但是仍然需要了解 DateTimeZone 如何影响 Joda 的操作。默认时间,即从运行代码的机器的系统时钟检索到的时间,在大部分情况下被使用。
本系列所有示例代码见github:https://github.com/irfen/joda-time-example
本文发表自赵伊凡BLOG
©原创文章,转载请注明来源: 赵伊凡's Blog
©本文链接地址: 2、Joda-time入门教程(二)——包含的类及适用情况
“2、Joda-time入门教程(二)——包含的类及适用情况”的33个回复