JAVA的时间日期处理一直是一个比较复杂的问题,大多数程序员都不能很轻松的来处理这些问题。首先Java中关于时间的类,从 JDK 1.1 开始,Date的作用很有限,相应的功能已由Calendar与DateFormat代替。使用Calendar类实现日期和时间字段之间转换,使用 DateFormat 类来格式化和分析日期字符串。

Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。

TimeZone : 表示时区偏移量。

Locale : 表示了特定的地理、政治和文化地区。需要 Locale 来执行其任务的操作称为语言环境敏感的操作,它使用 Locale 为用户量身定制信息。

SimpleDateFormat : 主要是用来格式化Date,用过之后就会发现,它其实不完善,对Calendar提供的支持很少.

经历几个项目发现apache提供的第三方扩展类库,org.apache.commons.lang.time包比较好用,可以将程序中时间处理变的简单一点,提高你的开发效率,下面介绍下常用的方法和具体使用。

org.apache.commons.lang.time 包括以下几个类:

a. DateFormatUtils        【格式化Calendar与Date并依赖于 FastDateFormat】

b. DateUtils                  【围绕Calendar与Date的实用方法】

c. DurationFormatUtils 【毫秒数格式化Calendar与Date】

d. FastDateFormat        【线程安全的SimpleDateFormat】

e. StopWatch               【提供一个方便的定时的API 】

1. DateFormatUtils 和 FastDateFormat

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)

原来项目中是这样写的:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String nowDay = sdf.format(new Date());

现在可以这样写:

String nowDay = DateFormatUtils.format(nowDay,"yyyy-MM-dd HH:mm:ss");

DateFormatUtils预定义的日期格式有9种之多,基本能满足项目时间格式化的要求,当然也可以自己自定义格式:

  public static final FastDateFormat ISO_DATETIME_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
public static final FastDateFormat ISO_DATETIME_TIME_ZONE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ");
public static final FastDateFormat ISO_DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd");
public static final FastDateFormat ISO_DATE_TIME_ZONE_FORMAT = FastDateFormat.getInstance("yyyy-MM-ddZZ");
public static final FastDateFormat ISO_TIME_FORMAT = FastDateFormat.getInstance("'T'HH:mm:ss");
public static final FastDateFormat ISO_TIME_TIME_ZONE_FORMAT = FastDateFormat.getInstance("'T'HH:mm:ssZZ");
public static final FastDateFormat ISO_TIME_NO_T_FORMAT = FastDateFormat.getInstance("HH:mm:ss");
public static final FastDateFormat ISO_TIME_NO_T_TIME_ZONE_FORMAT = FastDateFormat.getInstance("HH:mm:ssZZ");

所以上面的也可以这样写:

DateFormatUtils.ISO_DATETIME_FORMAT.format(date);

DateFormatUtils 预定义的日期格式,通过公有的静态final字段来暴露这些常量简化了类的使用,但是却有一些地方是需要注意的,在这方面FastDateFormat做得还是相当不错的。要使final字段真正的不可变,

a. 这些字段是基本类型的值(int,String等),

b. 指向一个不可变对象的引用。

c. 需要注意的特殊情况是,长度为零的数组总是可变的,要么通过不可变的Collection来包装,

要么使数组变成私有的,并添加一个公有的方法,返回一个数组的备份,这在effective java上的Item 15上有详细的介绍。上面的final 字段代表一个不可变的FastDateFormat,然而要让FastDateFormat字段真正的不可变,

FastDateFormat内部必须遵循相应的规则才可以。

a. 不要提供能修改对象状态的方法

b. 确保类不会被继承

c. 让所有字段都成为static final字段

d. 确保所有可变的组件不能被访问

详细介绍可参考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 类中,对应方法则更加的强大:

eg:

public static Date parseDate(String str, String parsePatterns[]);
String partterns[] = new String[5];
partterns[0] = "yyyy-MM-dd";
DateUtils.parseDate("2015-09-28", partterns);

因parsePatterns可以包括多种pattern,只要满足其中的一种即可。如果使用SimpleDateFormat,则先要通过SimpleDateFormat(String str)创建实例,然后通过applyPattern(String pattern)来变换不同的pattern。

2. DateUtils

DateUtils提供了很多很方便的功能,减轻了使用Date的复杂性。把原来需用Calendar才能完成的功能统一集中了起来,也就是说没有对应的CalendarUtils类。在JDK中,Date与Calendar概念本身就有些混淆,只是为了保持兼容性才引入的Calendar。相对于Calendar提供的方法,DateUtils提供了更加合理的方法,

对时间的单个字段操作变得更加的容易。如需要修改时间Date的某个字段,必须先获得Date对象实例,再传入Calendar,才能修改,如:

eg:

//方法已经过时了
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的确做得很完善,现在可以这样写:

eg:

 1     /**
2 * @Description: 给当前日期的特定字段,进行增量设置,0为当前,1 为 +1,-1 -1 4 addYears(new Date(), 1) 输出2016
5 */
6 public static Date addYears(Date date, int amount)
10 public static Date addMonths(Date date, int amount)
14 public static Date addWeeks(Date date, int amount) 18 public static Date addDays(Date date, int amount)
22 public static Date addHours(Date date, int amount)
26 public static Date addMinutes(Date date, int amount)
30 public static Date addSeconds(Date date, int amount)
34 public static Date addMilliseconds(Date date, int amount)
38 public static Date add(Date date, int calendarField, int amount) {
39 if (date == null) {
40 throw new IllegalArgumentException("The date must not be null");
41 }
42 Calendar c = Calendar.getInstance();
43 c.setTime(date);
44 c.add(calendarField, amount);
45 return c.getTime();
46 }
47 /**
48 * @Description: 全量设置日期特定字段,
49 * @date:2015年9月18日上午11:41:35
50 * eg: setYears(new Date(), 2015)
51 */
52 public static Date setYears(Date date, int amount)
56 public static Date setMonths(Date date, int amount) 60 public static Date setDays(Date date, int amount)
64 public static Date setHours(Date date, int amount)
68 public static Date setMinutes(Date date, int amount)
72 public static Date setSeconds(Date date, int amount)
76 public static Date setMilliseconds(Date date, int amount)
80 private static Date set(Date date, int calendarField, int amount) {
81 if (date == null) {
82 throw new IllegalArgumentException("The date must not be null");
83 }
84 Calendar c = Calendar.getInstance();
85 c.setLenient(false);
86 c.setTime(date);
87 c.set(calendarField, amount);
88 return c.getTime();
89 }

方法名也非常的直观,使用也更加方便了。但有一些方法不是很好理解,就像下面这个函数:

eg:

 public static long getFragmentInSeconds(Date date,int fragment)

 这个方法的作用是:返回一个指定时间的秒数。关键的是参数fragment,它的作用非常重要。它的值必须是Calendar的时间常量字段。如Calendar.MONTH ,

 需要注意的是,小时必须用24小时制的,即Calendar.HOUR_OF_DAY ,而不能用Calendar.HOUR字段。
/*
* 如现在是2014-10-23 13:27:00,那么
* DateUtils.getFragmentInDays(new Date(), Calendar.MONTH)返回23,表示从当月起已经过去23天了,
* DateUtils.getFragmentInDays(new Date(), Calendar.YEAR)返回296,表示从当年起已经过去296天了,
* DateUtils.getFragmentInHours(new Date(), Calendar.DATE)返回13,表示从今天起已经过去13个小时了
*/

当然在DateUtils也有一些一看就知道是做什么的函数,我在这里列一下,不具体给例子了:

@Description: 判断是否是同一天
public static boolean isSameDay(Calendar cal1, Calendar cal2) @Description: Date 转 Calendar
public static Calendar toCalendar(Date date); @Description: 从日期特定字段开始四舍五入
public static Calendar round(Calendar date, int field); * @Description: 格式化截取日期,从给定字段开始
public static Date truncate(Date date, int field); @Description: 从日期特定字段开始向上舍入
public static Date ceiling(Date date, int field); eg :
假设当前时间 2015-09-14 ceiling(new Date(),Calendar.MONTH); 输出 2015-10-01 round(new Date(), Calendar.MONTH); 输出 2015-09-01 假设当前时间 2015-09-16,超过半月,上面输出结果是一致的 @Description: 比较日历对应字段是否相等
public static boolean truncatedEquals(Calendar cal1, Calendar cal2, int field);

3. DurationFormatUtils 和 StopWatch

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

eg:

 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方法用于计算两个时间之间的片断,然后转化成相应的日期字符串类型,即能表示的最大单位

 1 public static java.lang.String formatPeriod(long startMillis, long endMillis, java.lang.String format)
2
3
4 String[] parsePatterns = {"yyyy-MM-dd HH:mm:ss"};
5 String str = "2009-09-29 15:30:12";
6 String str2 = "2010-09-30 15:40:18";
7 Date date = DateUtils.parseDate(str, parsePatterns);
8 Date date2 = DateUtils.parseDate(str2, parsePatterns);
9 long durationMillis = DateUtils.getFragmentInMilliseconds(date, Calendar.YEAR);
10 long durationMillis2 =DateUtils.getFragmentInMilliseconds(date2,Calendar.YEAR);
11
12 String s = DurationFormatUtils.formatPeriod(durationMillis, durationMillis2,"yyyy-MM-dd HH:mm:ss")
13
14 其中s的值为:0000-00-01 00:10:06

StopWatch 是一个计时器,具体举个简单的例子:

         StopWatch stWatch = new StopWatch();
stWatch.start();
/**
* 从周日开始,获取一周的 Calendar 对象
*/
Iterator<?> itr = iterator(new Date(),RANGE_MONTH_MONDAY);
while (itr.hasNext()) {
Calendar gCal = (Calendar) itr.next();
System.out.println(formatDateObject(gCal.getTime(),"yyyy-MM-dd HH:mm:ss"));
}
stWatch.stop();
System.out.println("花费时间 >>" + stWatch.getTime() + ",毫秒");

让时间处理简单化 【第三方扩展类库org.apache.commons.lang.time】的更多相关文章

  1. Apache Commons Lang之日期时间工具类

    码农不识Apache,码尽一生也枉然. FastDateFormat FastDateFormat是一个快速且线程安全的时间操作类,它完全可以替代SimpleDateFromat.因为是线程安全的,所 ...

  2. thinkphp5.1 使用第三方扩展类库

    此案例介绍的不是通过composer加载的,是手工下载放入extend目录下的扩展类库,仍然以phpspider为例 将owner888目录放入extend目录下,也可以直接将phpspider目录放 ...

  3. tp5 加载第三方扩展类库与手动加载的问题

    =============================================================== <?phpnamespace my; /*** 加载第三方类库*/ ...

  4. 一篇关于apache commons类库的详解

    1.1. 开篇 在Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默默无闻的.在我看来,成功而默默无闻的那些框架值得我们格外的尊敬和关注,Jakarta C ...

  5. 一篇关于apache commons类库的详解[转]

    1.1. 开篇 在Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默默无闻的.在我看来,成功而默默无闻的那些框架值得我们格外的尊敬和关注,Jakarta C ...

  6. apache commons类库的学习

    原文地址http://www.tuicool.com/articles/iyEbquE 1.1. 开篇 在Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默 ...

  7. 让EFCore更疯狂些的扩展类库(二):查询缓存、分部sql、表名替换的策略配置

    前言 上一篇介绍了扩展类库的功能简介,通过json文件配置sql语句 和 sql语句的直接执行,这篇开始说明sql配置的策略模块:策略管理器与各种策略的配置. 类库源码:github:https:// ...

  8. laravel中的自定义函数的加载和第三方扩展库加载

    l 1. 创建文件 app/Helpers/functions.php <?php // 示例函数 function foo() { return "foo"; } 2. 修 ...

  9. WeUI教程/第三方扩展及其他UI框架对比

    WeUI 是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一.包含button.cell.dialog. progress. toa ...

随机推荐

  1. python 读写文件

    #! -*- encoding:utf-8 -*- import os from config import * from function import GetCsspToken, RegistIn ...

  2. 数据表格,查询、导出共用一个form表单,实现文件流方式下载

    在开发中遇到问题是这样的: 在维护老的管理系统的过程中,老板说让加导出功能:项目中,查询的筛选条件是用的表单提交的方式写的. 解决方案有两种: 一.用ajax方式导出 var array = $('# ...

  3. 解决easy ui 1.4datebox控件不能清空的问题

    用easy ui遇到这个问题,在网上找到了解决方案,不过是1.3.6版本的.现提供1.4版本的修改的具体位置和代码. 我们用的是这个 修改位置:12739行,添加代码: , { text: funct ...

  4. HTML基础(五)——-css样式表——样式属性——格式与布局

    一.position:fixed 锁定位置(相对于浏览器的位置),例如有些网站的右下角的弹出窗口. 示例: 二.position:absolute     绝对位置: 1.外层没有position:a ...

  5. 十五天精通WCF——第十二天 说说wcf中的那几种序列化

    我们都知道wcf是由信道栈组成的,在我们传输的参数走到传输信道层之前,先需要经过序列化的过程,也就是将参数序列化为message,这篇 我们就来说说这里的序列化,蛮有意思的,可能初学者也明白,在wcf ...

  6. 编写IoDemo.java的Java应用程序,程序完成的功能是:首先读取text.txt文件内容,再通过键盘输入文件的名称为iodemo.txt,把text.txt的内容存入iodemo.txt

    package zuoye; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundExcep ...

  7. mongoDB删除表中一个字段

    使用update命令 update命令 update命令格式: db.collection.update(criteria,objNew,upsert,multi) 参数说明: criteria:查询 ...

  8. 【转】MySQL 数据库存储引擎

    原文地址:http://blog.jobbole.com/94385/ 简单介绍 存储引擎就是指表的类型.数据库的存储引擎决定了表在计算机中的存储方式.存储引擎的概念是MySQl的特点,而且是一个插入 ...

  9. QT5.5.0版本添加icon图标步骤

    1.制作icon图标文件 可以进入这个网站在线制作:http://www.ico.la/ 2.创建资源文件:qrc文件 接着 添加2两项,先点击prefix,然后添加文件--->图标路径 3.可 ...

  10. linux vi编辑器操作手册

    简介 Linux下的文本编辑器有很多种,vi 是最常用的,也是各版本Linux的标配.注意,vi 仅仅是一个文本编辑器,可以给字符着色,可以自动补全,但是不像 Windows 下的 word 有排版功 ...