当前位置: 首页 > 工具软件 > Joda-Beans > 使用案例 >

joda-time介绍

干浩阔
2023-12-01
一、Joda简介
目前Joda项目包括:
Joda-Time - Basic types for Date and Time
Joda-Money - Basic types for Money
Joda-Beans - Next generation JavaBeans
Joda-Convert - String to Object conversion
Joda-Collect - Additional collection data structures
Joda-Primitives - Primitive collections


这里简要介绍下Joda-Time。
Joda-Time令时间和日期值变得易于管理、操作和理解。并且 Joda 与 JDK 的互操作性也方便程序使用。目前Joda Time 已经纳入 JDK 8 的官方API了。


二、Maven库坐标
<dependency>
  <groupId>joda-time</groupId>
  <artifactId>joda-time</artifactId>
  <version>2.7</version>
</dependency>




三、Joda-Time的关键日期/时间概念
1. 不可变性(Immutability)
我在本文讨论的Joda-Time类具有不可变性,因此它们的实例无法被修改。(不可变类的一个优点就是它们是线程安全的)。我将向您展示的用于处理日期计算的 API方法全部返回一个对应Joda-Time类的新实例,同时保持原始实例不变。当您通过一个API方法操作Joda-Time类时,您必须捕捉该方法的返回值,因为您正在处理的实例不能被修改。您可能对这种模式很熟悉;比如,这正是 java.lang.String的各种操作方法的工作方式。


2. 瞬间性(Instant)
Instant表示时间上的某个精确的时刻,使用从epoch(1970-01-01 00:00:00 UTC)开始计算的毫秒表示。这一定义与JDK相同,这就是为什么任何Joda-Time Instant子类都可以与JDK Date和Calendar类兼容的原因。
相关类比如DateTime、DateMidnight等。


3. 局部性(Partial)
一个局部时间,正如我将在本文中将其称为局部时间片段一样,它指的是时间的一部分片段。局部时间片段指的是在时间上可以来回 “移动” 的一个时刻,这样它便可以应用于多个实例。
相关类比如:LocalDate、LocalTime等。


4. 年表(Chronology)
年表是一种日历系统、一种计算时间的特殊方式,并且是一种在其中执行日历算法的框架。Joda-Time支持8种年表,每一种都可以作为特定日历系统的计算引擎。
ISO(默认)
Buddhist
Coptic
Ethiopic
Gregorian-Julian cutover
Gregorian
Islamic
Julian
相关类比如ISOChronology、GregorianChronology等。


5. 时区(TimeZone)
时区是值一个相对于英国格林威治的地理位置,用于计算时间。任何严格的时间计算都必须涉及时区(或相对于 GMT)。
DateTimeZone 是Joda-Time库用于封装位置概念的类。许多日期和时间计算都可以在不涉及时区的情况下完成,但是仍然需要了解DateTimeZone 如何影响Joda-Time的操作。默认时间,即从运行代码的机器的系统时钟检索到的时间,在大部分情况下被使用。






四、DateTime类
1. 创建对象
DateTime类提供多种构造函数创建对象,也包括使用jdk对象作构造函数的传入参数,比如DateTime类可以传入以下对象来构造:
java.util.Date - a JDK instant
java.util.Calendar - a JDK canlendar
String - in ISO8601 format
Long - in milliseconds
any Joda-Time date-time class


例子:
java.util.Date jDate = new Date();
DateTime dt = new DateTime(jDate);


2. 属性&方法
DateTime dt = new DateTime();
int month = dt.getMonthOfYear(); // 月,1月值为1,12月值为12
int year = dt.getYear(); // 年


String monthName = dt.monthOfYear().getAsText(); // 四月
String frenchShortName = dt.monthOfYear().getAsShortText(Locale.ENGLISH); // Apr
boolean isLeapYear = dt.year().isLeap();  // false


// 值变后就会产生新对象(不可变性)
DateTime yearK2 = dt.withYear(2000).plusWeeks(2);
DateTime rounded = dt.dayOfMonth().roundFloorCopy();




五、局部日期时间
当地理位置(即时区)变得不重要时,存储日期可使用LocalDate,存储时间可使用LocalTime。
LocalDate localDate = new LocalDate(2009, 9, 6);// September 6, 2009
LocalTime localTime = new LocalTime(13, 30, 26, 0);// 1:30:26PM




六、年表&时区
Joda-Time采用可插拔方式的年表系统,相比之下,JDK使用子类的方式,比如GregorianCalendar。看例子:
Chronology coptic = CopticChronology.getInstance();


DateTimeZone zone = DateTimeZone.forID("Asia/Tokyo");
Chronology gregorianJuian = GJChronolygy.getInstance(zone);




七、间隔&区间&跨度
Interval: 它包含了「开始时间」和「结束时间」信息,包括各自的时区。所以可以根据Interval对象得到「开始时间」和「结束时间」这两个信息。
Duration: 它没有任何「开始时间」和「结束时间」的概念,只是保存了一个具体的时间间隔,是一个以毫秒为单元的整数。
Period  : 它和「Duration」差不多意思,也是没有包含「开始时间」和「结束时间」的信息,但是它和「Duration」不同的是,它所指的时间间隔不是以毫秒为单元,而是年、月、天、小时、分、秒、毫秒为相对单元。
先看例子:
DateTime start = new DateTime(2011,12,2,15,33); //开始时间
DateTime end = new DateTime(2013,3,1,12,34); //结束时间


Interval interval = new Interval(start, end);
Duration duration =new Duration(start, end);
Period period =interval.toPeriod();


boolean between = interval.contains(new DateTime(2013, 2, 1, 12, 34));
long millSeconds = duration.getMillis();
long millSeconds1 = period.getMillis();


结果:
between = true
millSeconds = 39301260000
millSeconds1 = 0


前两个值好理解,但duration和period调用getMillis()会出现不同结果就不好理解了。这里解释下:duration.getMillis返回的是绝对相差毫秒数;而period.getMillis返回0,是因为「开始时间」和「结束时间」间隔的相对时间是:1年2个月3个星期5天21个小时1分钟。




八、格式化
要格式化一个Joda-Time对象,调用它的toString()方法即可。如果您愿意的话,传递一个标准的ISO-8601或一个JDK兼容的控制字符串,以告诉JDK如何执行格式化。不需要创建单独的 SimpleDateFormat对象(但是 Joda 的确为那些喜欢自找麻烦的人提供了一个 DateTimeFormatter 类)。看例子:
1.传递SimpleDateFormat字符串
DateTime dateTime = new DateTime();
dateTime.toString("yyyy/MM/dd hh:mm:ss.SSSa"); // 2015/04/21 01:08:57.343下午
dateTime.toString("dd-MM-yyyy HH:mm:ss"); // 21-04-2015 13:08:57
dateTime.toString("EEEE dd MMMM, yyyy HH:mm:ssa"); // 星期二 21 四月, 2015 13:08:57下午
dateTime.toString("MM/dd/yyyy HH:mm ZZZZ"); // 04/21/2015 13:08 Asia/Shanghai
dateTime.toString("MM/dd/yyyy HH:mm Z"); // 04/21/2015 13:08 +0800


2. 使用ISO-8601
DateTime dateTime = new DateTime();
dateTime.toString(ISODateTimeFormat.basicDateTime()); // 20150421T121247.421+0800
dateTime.toString(ISODateTimeFormat.basicDateTimeNoMillis()); // 20150421T121247+0800
dateTime.toString(ISODateTimeFormat.basicOrdinalDateTime()); // 2015111T121247.421+0800
dateTime.toString(ISODateTimeFormat.basicWeekDateTime()); // 2015W172T121247.421+0800
 类似资料: