`

commons-lang(time应用)

阅读更多
JAVA的时间日期处理一直是一个比较复杂的问题,可以说大多数程序员都不能得心应手的处理这些问题,就算通过commons.lang.time包简化了,使用起来仍然有些麻烦,个人认为这可能是最复杂的一个子包。不过相对原始的JDK API,还是简化了不少,因此此子包也相当值得关注。

首先讨论一下关于时间的类,从 JDK 1.1 开始,Date的作用很有限,相应的功能已由Calendar与DateFormat代替。使用 Calendar 类实现日期和时间字段之间转换,使用 DateFormat 类来格式化和分析日期字符串。Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。TimeZone 表示时区偏移量。Locale 对象表示了特定的地理、政治和文化地区。需要 Locale 来执行其任务的操作称为语言环境敏感的操作,它使用 Locale 为用户量身定制信息。SimpleDateFormat的作用主要是用来格式化Date,用过之后就会发现,它其实很不完善,对Calendar提供的支持很少.

关于时间的类放在org.apache.commons.lang.time 包下面,它包括以下几个类:
DateUtils 包括一组围绕Calendar与Date的实用方法.
DateFormatUtils
DurationFormatUtils
FastDateFormat 一个快速线程安全的SimpleDateFormat版本
StopWatch 提供一个方便的定时的API

DateFormatUtils相对来说比较简单,它的方法全部都是static的,所以不需要用构造器创建新的实例,但它构造器却是public的,这并不是说我们应该在程序中使用它,官方文档已说明,它是为了与其它工具的集成的准备的。它包括的方法主要就是format。主要用途就是根据传入的pattern格式化Date或Calendar。也可以有一些附加的参数,如Locale,TimeZone。
比如这样:

format(java.util.Calendar calendar, java.lang.String pattern, java.util.TimeZone timeZone, java.util.Locale locale) 


当然DateFormatUtils还有一些预定义字段。对应的则是相应的FastDateFormat。
可以这样用:

DateFormatUtils.ISO_DATETIME_FORMAT.format(date)


通过公有的静态final字段来暴露这些常量简化了类的使用,但是却有一些地方是需要注意的,在这方面FastDateFormat做得还是相当不错的。要使final字段真正的不可变,要么这些字段是基本类型的值(int,String等),要么是指向一个不可变对象的引用。同时需要注意的特殊情况是,长度为零的数组总是可变的,要么通过不可变的Collection来包装,要么使数组变成私有的,并添加一个公有的方法,返回一个数组的备份,这在effective java上的Item 15上有详细的介绍。回到原来的话题上,DateFormatUtils内部定义了一些常量,如:


 public static final FastDateFormat ISO_DATE_FORMAT
            = FastDateFormat.getInstance("yyyy-MM-dd");


上面的final 字段代表一个不可变的FastDateFormat,然而要让FastDateFormat字段真正的不可变,FastDateFormat内部必须遵循相应的规则才可以。

不要提供能修改对象状态的方法
确保类不会被继承
让所有字段都成为static final字段
确保所有可变的组件不能被访问

详细介绍可参考Effective java第二版的Item 15。仔细查看,会发现FastDateFormat都遵循这些规则,而Effective java 2rd 的出版也在commons-lang 2.4 开发之后,这说明
commons-lang的代码质量还是相当值得肯定的。

其实DateFormateUtils内部细节实现完全依靠FastDateFormat,DateFormateUtils只是把一些常用的格式化功能单独组织起来,让日期时间的使用变得简单,毕竟大多数时候用户查看API时,如果有太多的方法,会给他们纷繁复杂的感觉。如果需要更加强大灵活的日期格式化功能,可以直接使用FastDateFormat,FastDateFormat这个类编写比较复杂,它有自己的一套解析规则,同时又使用了DateFormat类的一些规则,如Pattern。与SimpleDateFormat不同,FastDateFormat是线程安全,所以这个类在多线程的服务环境中特别有用。虽然它们都继承自java.text.Format,其实FastDateFormat相当于DateFormat与SimpleDateFormat的合并,只是功能更强大而已。如果是从DateFormat迁移到FastDateFormat的话,还是有一些地方需要注意的,比如,Date(String date)被DateFormat.parse(String s) 取代了,仔细查看,FastDateFormat并没有类似的方法,其实准确的说,把日期解析放在DateFormat本身就不太合理,不看文档的话,大多数人都会认为Date应该提供该功能。所以commons-lang把它放在了DateUtils 类中,对应方法则更加的强大:

parseDate(java.lang.String str, java.lang.String[] parsePatterns) 


因parsePatterns可以包括多种pattern,只要满足其中的一种即可。如果使用SimpleDateFormat,则先要通过SimpleDateFormat(String str)创建实例,然后通过applyPattern(String pattern)来变换不同的pattern。DateUtils提供了很多很方便的功能,减轻了使用Date的复杂性。把原来需用Calendar才能完成的功能统一集中了起来,也就是说没有对应的CalendarUtils类。在JDK中,Date与Calendar概念本身就有些混淆,只是为了保持兼容性才引入的Calendar。相对于Calendar提供的方法,DateUtils提供了更加合理的方法,对时间的单个字段操作变得更加的容易。如需要修改时间Date的某个字段,必须先获得Date对象实例,再传入Calendar,才能修改,如:

	public static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

在这方面commons-lang的确做得很完善,如:

	public static Date addMinutes(Date date, int amount) {
        return add(date, Calendar.MINUTE, amount);
    }

方法名也非常的直观,使用也更加方便了。

但有一些方法不是很好理解,如:

public static long getFragmentInSeconds(Date date,int fragment)


这个方法的作用是:返回一个指定时间的秒数。关键的是参数fragment,它的作用非常重要。它的值必须是Calendar的时间常量字段。如Calendar.MONTH ,需要注意的是,小时必须用24小时制的,即Calendar.HOUR_OF_DAY ,而不能用Calendar.HOUR字段。如果使用
Calendar.HOUR_OF_DAY 则时间2009-09-29 17:02:37 会返回157 (2*60+37),即所有大于等于fragment单位的字段将被忽略。

相对于这些增强已有功能的类,还有一些对常用功能进行补充的类,如DurationFormatUtils ,这个类主要的作用就是处理时间的片断,主要包括两种方法:
formatDuration和formatPeriod。如:

formatDuration(long durationMillis, java.lang.String format) 


通过传入一个毫秒数与日期格式(如:yyyy-MM-dd HH:mm:ss),它会返回一个对应日期的字符串形式。当然Date类本身有一个与这类似的方法,即Date(String s)方法,用于创建一个Date实例,但它只是创建一个Date实例,如果要转换成相应的String,还要经过一些步骤才行。需要注意的是,此日期片断能表示的最大单位为天,用法也很简单:

String pattern = "yyyy-MM-dd HH:mm:ss";
long durationMillis = (10+20*60+13*3600+4*24*3600) * 1000;
String formatDate = DurationFormatUtils.formatDuration(durationMillis,
				pattern);
System.out.println(formatDate);



需要注意的是日期格式的小时必须用HH,而不能用hh 。
下面介绍一下formatPeriod方法:

public static java.lang.String formatPeriod(long startMillis,
                                            long endMillis,
                                            java.lang.String format)

用于计算两个时间之间的片断,然后转化成相应的日期字符串类型,即能表示的最大单位,如下例所示:
String[] parsePatterns = {"yyyy-MM-dd HH:mm:ss"};
String str = "2009-09-29 15:30:12";
String str2 = "2010-09-30 15:40:18";
Date date = DateUtils.parseDate(str, parsePatterns);
Date date2 = DateUtils.parseDate(str2, parsePatterns);
long durationMillis = DateUtils.getFragmentInMilliseconds(date, Calendar.YEAR);
long durationMillis2 =DateUtils.getFragmentInMilliseconds(date2,Calendar.YEAR);

String s =	DurationFormatUtils.formatPeriod(durationMillis, durationMillis2, 										"yyyy-MM-dd HH:mm:ss")

其中s的值为:0000-00-01 00:10:06

上述两种方法功能有些相似,本人一直以为底层用了同样的实现方法,因为看上去只要把两个时间点计算成毫秒,相后相减就与第一个方法一样了,实际不然。它们的底层完全不一样,各用各的实现方式,没有任何交差,根本原来就在于它们能表示的最大单位不一样,如下例如示:

String[] parsePatterns = {"yyyy-MM-dd HH:mm:ss"};
		String str = "2009-05-29 15:30:12";
		String str2 = "2011-09-30 14:40:18";
		Date date = DateUtils.parseDate(str, parsePatterns);
		Date date2 = DateUtils.parseDate(str2, parsePatterns);
long durationMillis = DateUtils.getFragmentInMilliseconds(date, Calendar.YEAR);
long durationMillis2 =DateUtils.getFragmentInMilliseconds(date2,Calendar.YEAR);
		System.out.println(DurationFormatUtils.formatPeriod(durationMillis, 
											durationMillis2, "yyyy-MM-dd HH:mm:ss"));
		System.out.println(DurationFormatUtils.formatDuration(durationMillis2-											durationMillis,"yyyy-MM-dd HH:mm:ss"));


结果为:

0000-04-01 23:10:06
0000-00-123 23:10:06


time包还有一个StopWatch的类,此类主要作用是用来记时,有start,split,suspend之类的方法,平时能用到的地方不多。
分享到:
评论
1 楼 hanlongjie 2016-02-23  
 

相关推荐

    commons-lang-2.4-src 源码

    Apache Commons Lang 是一个Java工具包,它提供了许多实用的类和方法来补充Java核心库的功能。这个源码包"commons-lang-2.4-src"包含了2.4版本的完整源代码,对于Java开发者来说,这是一个宝贵的资源,可以深入理解...

    commons-lang3-3.11-bin.tar.gz

    Apache Commons Lang 3.11版的这些功能在实际开发中有着广泛的应用,无论是服务器端的非空校验,还是字符串、数组、日期等的处理,都可以找到对应的高效解决方案。通过使用这个库,开发者可以减少代码量,提高代码...

    commons-lang-2.4.zip

    import org.apache.commons.lang3.time.DateUtils; Date date = DateUtils.parseDate("2022-01-01", "yyyy-MM-dd"); ``` 5. **最佳实践** 使用Apache Commons Lang可以提高代码的可读性和可维护性,但应避免...

    Commons培训

    Commons-Lang是Apache Commons项目下的一个子项目,旨在提供一系列实用且高效的基础工具类,这些工具类能够帮助开发者更便捷地进行Java应用的开发。这些工具类覆盖了诸如字符串处理、数值操作、对象操作以及集合操作...

    Jakarta Commons笔记

    本文将深入探讨Jakarta Commons的核心价值及其组成部分之一——Commons Lang,旨在帮助读者更好地理解和应用这一框架。 ### 成功而低调的Jakarta Commons Jakarta Commons由Apache基金会维护,虽然不如某些明星...

    miaosha:SpringBoot构建电商基础秒杀项目

    SpringBoot构建电商基础秒杀项目 项目简介 通过SpringBoot快速搭建的前后端分离的电商基础秒杀项目...org.apache.commons:commons-lang3 org.hibernate:hibernate-validator joda-time:joda-time junit:junit org.spri

    t淘淘商城项目 商城项目 视频和源码教程 详细

    <commons-lang3.version>3.3.2</commons-lang3.version> <commons-io.version>1.3.2</commons-io.version> <commons-net.version>3.3</commons-net.version> <pagehelper.version>3.4.2-fix ...

    apache com包

    1. **DateUtil**: `DateUtil`在Apache Commons Lang中并不是标准类名,但可能指的是`org.apache.commons.lang3.time.DateUtils`。这是一个日期时间处理工具类,提供了对Java的`java.util.Date`和`java.util.Calendar...

    java使用dbcp所需所有包

    4. **commons-lang.jar**(可能需要):虽然不是DBCP的核心依赖,但某些版本的DBCP可能会用到Apache Commons Lang库中的函数性工具类,所以有时候也会包含此包。 在使用这些包进行开发时,你需要了解以下关键概念和...

    Eclipse Activiti jar包

    Apache Commons Lang是一个实用工具库,包含许多常用的字符串处理、数学运算等方法,为Activiti提供了额外的编程便利性。 这些库共同构建了一个强大的开发环境,使得开发者能够利用Eclipse Activiti进行高效、灵活...

    java_jira所需jar包

    11. `commons-lang3-x.x.x.jar` 和 `commons-codec-x.x.x.jar`:Apache Commons Lang和Codec库,提供了一些额外的字符串处理和编码解码功能。 12. `log4j-x.x.x.jar`:Log4j的日志框架。 13. `joda-time-x.x.x.jar...

    Java开发常用技术

    - Commons-Lang:提供了许多Java语言功能的扩展,如字符串处理、日期时间操作等。 - Commons-Codec:提供了各种编码解码功能,如Base64编码。 - Joda-Time:一个强大的日期和时间处理库,比Java内置的日期类更...

    xultimate-toolkit:基于JavaEE应用程序参考架构的Spring框架

    xultimate-toolkit The X-Ultimate Toolkit provides ...封装commons-lang3,添加CompareToBuilderUtils、EqualsBuilderUtils、HashCodeBuilderUtils、ToStringBuilderUtils。 添加MapBuilder、ListBuilder、SetBuilder

    spring定时任务必须要的10个jar包.zip

    4. **Apache Commons Lang**:在处理任务时,可能会用到一些通用的字符串处理、日期时间转换等工具,`commons-lang3.jar`提供了这些功能。 5. **Apache Commons Logging**:日志记录对于调试和监控任务执行情况至关...

    Jakarta+Commons中文介绍

    ##### commons.lang.time包 此包提供了扩展Java标准时间日期处理的方法。 ##### DateFormatUtils **DateFormatUtils** 类提供了日期格式化和解析的功能,可以灵活地控制日期格式。 ##### DateUtils **DateUtils...

    Jdk1.8搭建SSh框架所需Jar包

    8. **其他依赖库**:如log4j.jar用于日志记录,commons-lang3.jar、commons-logging.jar等Apache Commons库,还有javassist.jar用于动态字节码操作。 在实际开发中,你可能还需要其他的jar包来支持额外的功能,如...

    java万年历的源代码(显示农历及节假日)

    农历转换涉及到复杂的历法规则,包括闰年、闰月等计算,这通常需要第三方库,如`com.github.tobiaszhang:china-calendar`或`org.apache.commons:commons-lang3`,它们提供了农历转换的接口。 此外,为了显示节假日...

    jakarta commons cookbook目录

    《Jakarta Commons Cookbook》是Java开发领域中一本重要的参考资料,主要涵盖了Apache Jakarta Commons项目中的各种实用工具类库的使用技巧和实践经验。这本书的核心是帮助开发者更有效地利用这些库来提高编程效率和...

    Java万年历+时分秒

    对于阴历的计算,Java标准库并没有内置的支持,因此通常需要引入第三方库,如`com.github.tony19:chronicle-date`或`org.apache.commons:commons-lang3`等,这些库提供了农历转换的方法。开发者需要理解农历和阳历...

Global site tag (gtag.js) - Google Analytics