让时间处理简单化 【第三方扩展类库org.apache.commons.lang.time】
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】的更多相关文章
- Apache Commons Lang之日期时间工具类
码农不识Apache,码尽一生也枉然. FastDateFormat FastDateFormat是一个快速且线程安全的时间操作类,它完全可以替代SimpleDateFromat.因为是线程安全的,所 ...
- thinkphp5.1 使用第三方扩展类库
此案例介绍的不是通过composer加载的,是手工下载放入extend目录下的扩展类库,仍然以phpspider为例 将owner888目录放入extend目录下,也可以直接将phpspider目录放 ...
- tp5 加载第三方扩展类库与手动加载的问题
=============================================================== <?phpnamespace my; /*** 加载第三方类库*/ ...
- 一篇关于apache commons类库的详解
1.1. 开篇 在Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默默无闻的.在我看来,成功而默默无闻的那些框架值得我们格外的尊敬和关注,Jakarta C ...
- 一篇关于apache commons类库的详解[转]
1.1. 开篇 在Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默默无闻的.在我看来,成功而默默无闻的那些框架值得我们格外的尊敬和关注,Jakarta C ...
- apache commons类库的学习
原文地址http://www.tuicool.com/articles/iyEbquE 1.1. 开篇 在Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默 ...
- 让EFCore更疯狂些的扩展类库(二):查询缓存、分部sql、表名替换的策略配置
前言 上一篇介绍了扩展类库的功能简介,通过json文件配置sql语句 和 sql语句的直接执行,这篇开始说明sql配置的策略模块:策略管理器与各种策略的配置. 类库源码:github:https:// ...
- laravel中的自定义函数的加载和第三方扩展库加载
l 1. 创建文件 app/Helpers/functions.php <?php // 示例函数 function foo() { return "foo"; } 2. 修 ...
- WeUI教程/第三方扩展及其他UI框架对比
WeUI 是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一.包含button.cell.dialog. progress. toa ...
随机推荐
- IO流05--毕向东JAVA基础教程视频学习笔记
Day20 10 创建java文件列表11 Properties简述12 Properties存取13 Properties存取配置文件14 Properties练习15 PrintWriter16 ...
- 挖一挖C#中那些我们不常用的东西之系列(2)——IsXXX 系列方法
不知道有人做没做过对日外包,如果做过的话,那么对vb.net应该非常熟悉了,当年我刚毕业的时候也做过四个月的外包,那种日子简直 不是人过的,就连大楼下面买珠宝的阿姨都说,这些孩子,只看过他们上班,就没 ...
- 使用dig查询dns解析
原文地址:使用dig查询dns解析 作者:chenwenming 一般来说linux下查询域名解析有两种选择,nslookup或者dig,而在使用上我觉得dig更加方便顺手. 如果是在debian下的 ...
- x01.Excel: 合计件数
由于 VBA 与 Excel 是耦合的,所以还是先看表: 件数的计算,用 Mod 即可.但考虑到要求码洋.数量等多种需求,就该 VBA 登场了.代码如下: '===================== ...
- android java数组应用与说明
如果定义类或结构数据则需每个都进行创建才可以使用,不然都为null 如: PointF pts[] = new PointF[5] ;//pts[0].x =CSSliderSize / 2;//这样 ...
- 翻译《Writing Idiomatic Python》(三):变量、字符串、列表
原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...
- 线程实现方式以及序列化 反序列化.java
一.序列化与反序列化 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上, ...
- KSFramework常见问题:Excel如何进行SVN协作、差异比较?
Excel如何进行SVN协作.差异比较? 嗯,这是一个令人困惑的问题.游戏开发.程序开发时,使用Excel可以添加文档.注释.图标.批注等等各种辅助信息: 但是Excel是非纯文本格式,在使用SVN. ...
- Extjs API - JS Duck
1. 安裝JS Duck3 tar.gz版本 https://nodeload.github.com/senchalabs/jsduck/tarball/master exe版本 http://c ...
- Android之SDK、NDK、JNI和so文件
1. SDK Android SDK(AndroidSoftware Development Kit),即Android软件开发工具包,Android的SDK基于Java实现,这意味着基于An ...