小巧实用日期处理 - DateUtil 在JAVA开发中,避免不了对日期的操作,但是Java本身对 `Date` 和 `Calendar` 对象使用起来混乱并且复杂,故使用此工具类做了封装。 主要由下面四部分组成  我们先来看出镜率最高的两个转换的方法 `DateUtil.toString(Date, String)` , `DateUtil.toDate(String, String...)` ## 1.DateUtil.toString(Date, String) 方法 这就是我们常用来做 Date类型转成字符串类型的方法 通常我们会这么写 ```JAVA SimpleDateFormat simpleDateFormat = new SimpleDateFormat("ddMMyyyy"); String birth = simpleDateFormat.format(date); ``` 如果有小伙伴不小心把 `simpleDateFormat` 声明成类的变量,在并发的情况下,可能会出现异常,参见 [SimpleDateFormat在多线程下不安全](http://newslxw.iteye.com/blog/1114851) 此时你可以直接使用: 示例: ```JAVA DateUtil.toString(Tue Oct 16 23:49:21 CST 2012,DatePattern.COMMON_DATE_AND_TIME_WITH_MILLISECOND) ``` 结果: ```JAVA 2012-10-16 23:49:21.525 ``` 此外,也经常看到小伙伴是这样创建时间戳文件夹的 ```JAVA Calendar calendar = Calendar.getInstance(); String userDefinedPath = calendar.get(Calendar.YEAR) + "/" + (calendar.get(Calendar.MONTH) + 1) + "/" + calendar.get(Calendar.DAY_OF_MONTH) + "/" + "propertyImage" + "/"; ``` 我们可以有更简单的代码: ```JAVA String userDefinedPath = DateUtil.toString(new Date(), "YYYY/MM/dd/") + "propertyImage/"; ``` 可以看到,代码更加简洁明了 ## 2.DateUtil.toDate(String, String...) 方法 与 `DateUtil.toString(Date, String)` 相反的,就是将字符串转成 Date 格式 将时间字符串 dateString 使用一个或者多个不同的 datePattern 模式按照顺序转换成date类型. 经常我们会看到小伙伴写出下面的代码: ```JAVA SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); Date publishTimeDate = null; try{ publishTimeDate = simpleDateFormat.parse(publishTime); }catch (ParseException e1){ e1.printStackTrace(); } ``` 可以看到直接使用 `SimpleDateFormat` 来写代码的话, 代码行数较多,并且还需要自行处理 `ParseException` checkedException异常, 而且catch里面一般都是写的都是无用代码 此时你可以一行代码搞定: ```JAVA Date publishTimeDate = DateUtil.toDate(publishTime, DatePattern.COMMON_DATE_AND_TIME_WITHOUT_SECOND); ``` 该方法,如果转换有异常,会将 `ParseException` 转成 `IllegalArgumentException` 返回,是 `UnCheckedException异常` ,非强行要求捕获处理 **示例:** ```JAVA DateUtil.toDate("2016-02-33", DatePattern.COMMON_DATE) = 2016-03-04 DateUtil.toDate("2016-06-28T01:21:12-0800", "yyyy-MM-dd'T'HH:mm:ssZ") = 2016-06-28 17:21:12 DateUtil.toDate("2016-06-28T01:21:12+0800", "yyyy-MM-dd'T'HH:mm:ssZ") = 2016-06-28 01:21:12 ``` **注意:** - 转换的时候,使用日历的`宽松模式`,参见 `java.text.DateFormat.setLenient(boolean)`,即支持传入`"2016-02-33"`,会转换成 `2016-03-04` - 如果能解析所有的字符串,那么视为成功 - 如果没有任何的模式匹配,将会抛出异常 下面出场的是经常会用作报表数据统计的方法获得 今天00:00:00,这个月第一天,这个星期第一天,今年第一天 ## 3. 用作数据统计 方法 | Description :---- | :--------- DateUtil.**getFirstDateOfThisDay**(Date) | 获得指定日期 date的 `00:00:00.000`时间. DateUtil.**getFirstDateOfThisMonth**(Date) | 获得指定日期date`所在月`的第一天,`00:00:00.000`到毫秒. DateUtil.**getFirstDateOfThisWeek**(Date) | 获得指定日期 date `所在的星期`第一天(周日) `00:00:00.000` 到毫秒. DateUtil.**getFirstDateOfThisYear**(Date) | 获得指定日期date`所在年的第一天`,`00:00:00.000` 到毫秒. DateUtil.**getLastDateOfThisDay**(Date) | 获得指定日期 date的 `23:59:59.999`时间. DateUtil.**getLastDateOfThisMonth**(Date) | 获得指定日期date`所在月的最后一天`,`23:59:59.999` 到毫秒. DateUtil.**getLastDateOfThisWeek**(Date) | 获得指定日期`所在星期的最后一天`(周六) `23:59:59.999` 到毫秒. DateUtil.**getLastDateOfThisYear**(Date) | 获得指定日期date`所在年的最后一天` `23:59:59.999` 到毫秒. ## 4. 时间运算 方法 | Description :---- | :--------- DateUtil.**addYear**(Date, int) | 指定日期 date,加减年份. DateUtil.**addMonth**(Date, int) | 指定日期 date加减月份. DateUtil.**addWeek**(Date, int) | 指定日期 date加减星期 . DateUtil.**addDay**(Date, int) | 指定日期 date加减天数. DateUtil.**addHour**(Date, int) | 指定日期 date加减小时. DateUtil.**addMinute**(Date, int) | 指定日期 date加减分钟. DateUtil.**addSecond**(Date, int) | 指定日期 date加减秒. DateUtil.**addMillisecond**(Date, int) | 指定日期 date加减毫秒. ### 4.1 实例1 生成优惠券 > 程序员鼓励师:小帅哥,帮我生成一张优惠券,有效期截至到是下个月1号 00:00:00 *普通程序员* 是这么写的: ```JAVA /** * 获取优惠券,有效期 * @return */ private Date[] getTimes(){ Date start = new Date(); //优惠券enddate Calendar calendar = Calendar.getInstance(); calendar.setTime(start); calendar.add(Calendar.MONTH,1); calendar.add(Calendar.DATE, 1); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); Date end = calendar.getTime(); Date[] dates = {start,end}; return dates; } ``` *聪明程序员* 是这么写的 ```JAVA /** * 获取优惠券,有效期 * @return */ private Date[] getTimes(){ Date start = new Date(); Date[] dates = { start, DateUtil.getFirstDateOfThisDay(DateUtil.addMonth(start, 1)) }; return dates; } ``` ### 4.2 实例2 导出数据 > 程序员鼓励师:小帅哥,帮我导出7天以来的订阅邮件数据 *普通程序员* 是这么写的: ```JAVA /* 获取上一周的数据 */ java.util.Calendar c = java.util.Calendar.getInstance(); c.add(java.util.Calendar.DAY_OF_WEEK, -7); Date startDate = c.getTime(); Date curDate = new Date(); ``` 细细一琢磨,这段代码如果执行的话,如果系统较卡,执行到这段代码的时候,会有数据丢失 *聪明程序员* 是这么写的 ```JAVA /* 获取上一周的数据 */ Date startDate =DateUtil.getFirstDateOfThisDay(DateUtil.addDay(new Date(), -7)); Date curDate = new Date(); ``` ## 5. 取到date某个时间属性 方法 | Description :---- | :--------- DateUtil.**getYear**(Date) | 获得指定日期 date中的年份. DateUtil.**getMonth**(Date) | 获得指定日期 date中的月份 (已经+1处理). DateUtil.**getWeekOfYear**(Date) | 获得指定日期所在星期的最后一天(周六) `23:59:59.999` 到毫秒. DateUtil.**getDayOfYear**(Date) | 获得指定日期 date是当年中的第几天. DateUtil.**getDayOfMonth**(Date) | 获得指定日期 date是当前月的几号. DateUtil.**getDayOfWeek**(Date) | 获得指定日期date在当前星期是星期几. DateUtil.**getHourOfDay**(Date) | 获得指定日期date中的小时(24小时制). DateUtil.**getHourOfYear**(Date) | 获得指定日期date在它一年中的小时数. DateUtil.**getMinute**(Date) | 获得指定日期date中的分钟. DateUtil.**getSecond**(Date) | 获得指定日期date中的秒. DateUtil.**getSecondOfDay**(Date) | 获得指定日期date在当天中的秒数,最大值86400. DateUtil.**getSecondOfHour**(Date) | 获得指定日期date在当前小时中的秒数,最大值3600. DateUtil.**getTime**(Date) | 返回自 `1970年1月1 日 00:00:00 GMT` 以来,此 Date 对象表示的毫秒数. ## 6. 时间比较 方法 | Description :---- | :--------- DateUtil.**isEquals**(Date, Date, String) | 在相同格式下 datePattern,将两个日期转成字符串判断是否相等. DateUtil.**isInTime**(Date, Date, Date) | 判断指定日期 date 是否在 beginDate 和 endDate两个时间之间. DateUtil.**isBefore**(Date, Date) | 判断指定日期 date是否 在 whenDate时间之前. DateUtil.**isAfter**(Date, Date) | 判断指定日期 date是否在 whenDate时间之后. ## 7. DateUtil.isLeapYear(int) 判断指定年 year 是否为闰年 ## 8. 综合运用: 下面代码 `美化` 前 ```JAVA // 判断是否支持当日达和COD private void judgeDelivery(Long areaCode,DefaultReturnResult defaultReturnResult){ boolean flag = false; DeliveryArea area = deliveryareaManager.findEnableDeliveryAreaByCode(areaCode + ""); DeliveryAreaViewCommand areaViewCommand = (DeliveryAreaViewCommand) ConvertUtils.convertTwoObject(new DeliveryAreaViewCommand(), area); if (Validator.isNotNullOrEmpty(area)){ AreaDeliveryMode areaMode = areaModeManager.findAreaDeliveryModeByAreaId(area.getId()); if (null != areaMode){ areaViewCommand = (DeliveryAreaViewCommand) ConvertUtils.convertTwoObject(areaViewCommand, areaMode); defaultReturnResult.setReturnObject(areaMode); DateFormat df = new SimpleDateFormat("HH:mm:ss"); Date now = new Date(); try{ now = df.parse(df.format(now)); if (areaViewCommand.getFirstDayDelivery().equals(AreaDeliveryMode.YES) && Validator.isNotNullOrEmpty(areaViewCommand.getFirstDeliveryStartTime()) && Validator.isNotNullOrEmpty(areaViewCommand.getFirstDeliveryEndTime())){ // 时间是否允许 now = df.parse(df.format(now)); flag = (now.before(df.parse(areaMode.getFirstDeliveryEndTime()))) && (now.after(df.parse(areaMode.getFirstDeliveryStartTime()))); defaultReturnResult.setResult(flag); } // 是否支持次日达 if (areaMode.getSecondDayDelivery().equals(AreaDeliveryMode.YES) && Validator.isNotNullOrEmpty(areaMode.getSecondDeliveryStartTime()) && Validator.isNotNullOrEmpty(areaMode.getSecondDeliveryEndTime())){ // 时间是否允许 now = df.parse(df.format(now)); flag = (now.before(df.parse(areaMode.getSecondDeliveryEndTime()))) && (now.after(df.parse(areaMode.getSecondDeliveryStartTime()))); defaultReturnResult.setResult(flag); } if (areaMode.getThirdDayDelivery().equals(AreaDeliveryMode.YES) && Validator.isNotNullOrEmpty(areaMode.getThirdDeliveryStartTime()) && Validator.isNotNullOrEmpty(areaMode.getThirdDeliveryEndTime())){ // 时间是否允许 flag = (now.before(df.parse(areaMode.getSecondDeliveryEndTime()))) && (now.after(df.parse(areaMode.getSecondDeliveryStartTime()))); defaultReturnResult.setResult(flag); } defaultReturnResult.setReturnObject(areaViewCommand); }catch (ParseException e){ LOGGER.error("DateFormat Format ERROR !", e); } }else{ defaultReturnResult.setResult(false); defaultReturnResult.setStatusCode("deliveryArea.has.not.areamode"); } }else{ defaultReturnResult.setResult(false); defaultReturnResult.setStatusCode("deliveryArea.not.exist"); } } ``` **美化后:** ```JAVA // 判断是否支持当日达和COD private void judgeDelivery(Long areaCode,DefaultReturnResult defaultReturnResult){ DeliveryArea deliveryArea = deliveryareaManager.findEnableDeliveryAreaByCode(areaCode + ""); if (isNullOrEmpty(deliveryArea)){ defaultReturnResult.setResult(false); defaultReturnResult.setStatusCode("deliveryArea.not.exist"); return; } //************************************************************************ DeliveryAreaViewCommand deliveryAreaViewCommand = (DeliveryAreaViewCommand) ConvertUtils.convertTwoObject(new DeliveryAreaViewCommand(), deliveryArea); AreaDeliveryMode areaDeliveryMode = areaModeManager.findAreaDeliveryModeByAreaId(deliveryArea.getId()); if (isNullOrEmpty(areaDeliveryMode)){ defaultReturnResult.setResult(false); defaultReturnResult.setStatusCode("deliveryArea.has.not.areamode"); return; } //************************************************************************ deliveryAreaViewCommand = (DeliveryAreaViewCommand) ConvertUtils.convertTwoObject(deliveryAreaViewCommand, areaDeliveryMode); Date now = toDate(DateUtil.toString(new Date(), COMMON_TIME), COMMON_TIME); boolean flag = false; //************************************************************************************************ String firstDeliveryStartTime = deliveryAreaViewCommand.getFirstDeliveryStartTime(); String firstDeliveryEndTime = deliveryAreaViewCommand.getFirstDeliveryEndTime(); if (YES.equals(deliveryAreaViewCommand.getFirstDayDelivery()) && isNotNullOrEmpty(firstDeliveryStartTime) && isNotNullOrEmpty(firstDeliveryEndTime)){ // 时间是否允许 flag = DateUtil.isInTime(now, toDate(areaDeliveryMode.getFirstDeliveryStartTime(), COMMON_TIME), toDate(areaDeliveryMode.getFirstDeliveryEndTime(), COMMON_TIME)); } // 是否支持次日达 String secondDeliveryEndTime = areaDeliveryMode.getSecondDeliveryEndTime(); String secondDeliveryStartTime = areaDeliveryMode.getSecondDeliveryStartTime(); if (YES.equals(areaDeliveryMode.getSecondDayDelivery()) && isNotNullOrEmpty(secondDeliveryStartTime) && isNotNullOrEmpty(secondDeliveryEndTime)){ // 时间是否允许 flag = DateUtil.isInTime(now, toDate(secondDeliveryStartTime, COMMON_TIME), toDate(secondDeliveryEndTime, COMMON_TIME)); } String thirdDeliveryStartTime = areaDeliveryMode.getThirdDeliveryStartTime(); String thirdDeliveryEndTime = areaDeliveryMode.getThirdDeliveryEndTime(); if (YES.equals(areaDeliveryMode.getThirdDayDelivery()) && isNotNullOrEmpty(thirdDeliveryStartTime) && isNotNullOrEmpty(thirdDeliveryEndTime)){ // 时间是否允许 flag = DateUtil.isInTime(now, toDate(secondDeliveryStartTime, COMMON_TIME), toDate(secondDeliveryEndTime, COMMON_TIME)); } //************************************************************************************************ defaultReturnResult.setResult(flag); defaultReturnResult.setReturnObject(deliveryAreaViewCommand); } ```