让时间处理简单化 【第三方扩展类库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 ...
随机推荐
- 最受欢迎的Java第三方库
前言 翻译自programcreek: 典型的Java项目通常会依赖一些第三方库,本文总结了一些最受欢迎的Java库,这些类库在各种应用程序中被广泛使用: 当然,Java SDK是最广泛使用的Java ...
- 操作linux命令
一.Linux下重启Tomcat 1. 进入tomcat下的bin目录:cd /user/standard/tomcat/bin; 使用关闭命令:./shutdown.sh; 查看Java进程是否关闭 ...
- Windows7 系统 CMD命令行,点阵字体不能改变大小以及中文乱码的问题
之前装了oracle 11g后,发现开机速度竟然奇葩的达到了3分钟.经过旁边大神指点,说是因为oracle某个(具体不清楚)服务,在断网的时候会不断的ping网络,导致速度变慢.然后就关服务呗,然后一 ...
- MFC MDI 主框架和标签页数据互操作
==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完 ...
- Keepalived+MySQL双主架构
l 架构准备 Node1 192.168.15.3 Node2 192.168.15.4 VIP 192.168.15.254 l 软件 MySQL 5.6 Keepalive yum insta ...
- DBA的技能图谱
最近发现公布的技术岗位的技能图谱中没有DBA的,比较心塞,于是根据自己的工作经验写了一个,写的过程中发现,还的不断的完善,但是先放出来,欢迎大家提建议.
- 烂泥:Linux系统与windows系统文件同步
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 上篇文章中,我们介绍了有关Linux系统之间的文件同步,这篇文章我们来介绍下,有关Linux系统与windows系统,以及windows系统与windo ...
- mysql避免重复插入的三种方法
在开发中,我们经常遇到这样的需求,如果插入的数据不存在就插入存在就更新(或者不做任何操作).mysql的insert就提供了此功能,不需要我们在自己的业务逻辑代码上做处理.直接用mysql提供的功能来 ...
- Javascript为元素添加事件处理函数
document.getElementById("test").onclick = function(){ ... };
- log4j 日志信息的引入(通用版)——解决项目运行过程中的日志信息
定义 log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.NT的事件记录器.UNIX Syslog守护进程 ...