package com.jadyer.seed.comm.util; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.time.DurationFormatUtils; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; /** * 日期工具类 * ---------------------------------------------------------------------------------------------------------------- * @version v1.3 * @version v1.3-->增加getDistanceDay()方法,用於計算兩個日期相隔的天數 * @version v1.2-->增加getCrossDayList()方法,用于获取两个日期之间的所有日期列表 * @history v1.1-->增加根据日期获得星期的方法getWeekName() * @history v1.0-->新建不添加若干方法 * ---------------------------------------------------------------------------------------------------------------- * Created by 玄玉<https://jadyer.github.io/> on 2017/5/19 11:05. */ public final class DateUtil { private DateUtil(){} /** * 判断是否月初 */ public static boolean isFirstDayOfMonth(Date date){ return "01".equals(DateFormatUtils.format(date, "dd")); } /** * 判断是否月末 */ public static boolean isEndDayOfMonth(Date date){ return isFirstDayOfMonth(DateUtils.addDays(new Date(), 1)); } /** * 判断是否本周第一天 */ public static boolean isFirstDayOfWeek(){ return 0 == DateUtils.truncatedCompareTo(new Date(), getFirstDayOfWeek(), Calendar.DAY_OF_MONTH); } /** * 获取本周第一天 */ public static Date getFirstDayOfWeek(){ //使用默认时区和语言环境获得一个基于当前时间的日历 Calendar cal = Calendar.getInstance(); //设置一个星期的第一天是哪一天(也可以用cal.add(Calendar.DAY_OF_MONTH, -1),二者都是解决周日时获取到的是下一周的情况) cal.setFirstDayOfWeek(Calendar.MONDAY); //将给定的日历字段设置为给定值 cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); return cal.getTime(); } /** * 获取前一天日期yyyyMMdd * @see 经测试,针对闰年02月份或跨年等情况,该代码仍有效。测试代码如下 * @see calendar.set(Calendar.YEAR, 2013); * @see calendar.set(Calendar.MONTH, 0); * @see calendar.set(Calendar.DATE, 1); * @see 测试时,将其放到<code>calendar.add(Calendar.DATE, -1);</code>前面即可 * @return 返回的日期格式为yyyyMMdd */ public static String getYestoday(){ Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DATE, -1); return new SimpleDateFormat("yyyyMMdd").format(calendar.getTime()); } /** * 获取格式化的详细日期 * @param dateStr yyyyMMdd格式的日期字符串 * @return yyyy-MM-dd格式的日期字符串 */ public static String getDetailDate(String dateStr){ try { return String.format("%tF", DateUtils.parseDate(dateStr, "yyyyMMdd")); } catch (ParseException e) { throw new RuntimeException(e); } } /** * 获取当前的日期yyyyMMdd */ public static String getCurrentDate(){ return new SimpleDateFormat("yyyyMMdd").format(new Date()); } /** * 获取当前的时间yyyyMMddHHmmss */ public static String getCurrentTime(){ return new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); } /** * 获取本周开始的时间 */ public static Date getCurrentWeekStartDate(){ Calendar currentDate = Calendar.getInstance(); currentDate.setFirstDayOfWeek(Calendar.MONDAY); currentDate.set(Calendar.HOUR_OF_DAY, 0); currentDate.set(Calendar.MINUTE, 0); currentDate.set(Calendar.SECOND, 0); currentDate.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); return currentDate.getTime(); } /** * 获取本周结束的时间 */ public static Date getCurrentWeekEndDate(){ Calendar currentDate = Calendar.getInstance(); currentDate.setFirstDayOfWeek(Calendar.MONDAY); currentDate.set(Calendar.HOUR_OF_DAY, 23); currentDate.set(Calendar.MINUTE, 59); currentDate.set(Calendar.SECOND, 59); currentDate.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); return currentDate.getTime(); } /** * 计算两个日期的相差时间 * --------------------------------------------------------------------------------------------------------------- * 等价于以下两个方法 * org.apache.commons.lang3.time.DurationFormatUtils.formatDuration(time, "dd HH:mm:ss.SSS") * org.apache.commons.lang3.time.DurationFormatUtils.formatDuration(time, "dd'天'HH'小时'mm'分钟'ss'秒'SSS'毫秒'") * --------------------------------------------------------------------------------------------------------------- * @param begin 起始日期 * @param end 终止日期 * @return xx天xx小时xx分xx秒 */ public static String getDistanceTime(Date begin, Date end) { long time = end.getTime() - begin.getTime(); long day = time / (24 * 60 * 60 * 1000); long hour = (time / (60 * 60 * 1000) - day * 24); long minute = ((time / (60 * 1000)) - day * 24 * 60 - hour * 60); long second = (time / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60); return day + "天" + hour + "小时" + minute + "分" + second + "秒"; } /** * 计算两个日期相隔的天数 * ----------------------------------------------------------------------------------- * 關於相隔和相差(getDistanceTime()) * 1、开始日期20170824235959,结束日期20170825000000,差一秒,但其相差天數==0,相隔天數==1 * 2、开始日期20170824110000,结束日期20170825105959,差一秒,但其相差天數==0,相隔天數==1 * 3、开始日期20170824110000,结束日期20170825110000,相 同,但其相差天數==1,相隔天數==1 * ----------------------------------------------------------------------------------- * 有些类似于下面的方法 * org.apache.commons.lang3.time.DurationFormatUtils.formatPeriod(time, "d") * ----------------------------------------------------------------------------------- * @param begin 起始日期 * @param end 终止日期 * @return 相隔的天數 */ public static long getDistanceDay(Date begin, Date end) { String pattern = "yyyyMMdd"; try { begin = DateUtils.parseDate(DateFormatUtils.format(begin, pattern), pattern); end = DateUtils.parseDate(DateFormatUtils.format(end, pattern), pattern); } catch (ParseException e) { throw new RuntimeException(e); } long time = end.getTime() - begin.getTime(); return time / (24 * 60 * 60 * 1000); } /** * 计算两个日期相隔的月数 * ---------------------------------------------------------------------------------------- * org.apache.commons.lang3.time.DurationFormatUtils.formatPeriod(timeStart, timeEnd, "M") * 20190218 10:20 - 20190318 : return 0 * 20190218 10:20 - 20190319 : return 1 * 20190218 - 20190316 : return 0 * 20190218 - 20190318 : return 1 * 20190218 - 20190515 : return 2 * 20190218 - 20190519 : return 3 * 20190131 - 20190228 : return 0 * 20190131 - 20190430 : return 2 * 如果是算两个日期相隔的月数,那就把第二个参数format传小写的"y" * 若传的format="y-M-d",那么formatPeriod()返回的字符串就是"0-0-0"格式的,split截取即可 * 但此时要注意,比如计算20190218到20190318,算出来的就是0-1-0,所以第二个参数format很重要 * ---------------------------------------------------------------------------------------- * Comment by 玄玉<https://jadyer.cn/> on 2019/3/26 16:58. */ public static long getDistanceMonth(Date begin, Date end) { String period = DurationFormatUtils.formatPeriod(begin.getTime(), end.getTime(), "M"); //处理 [20190131 - 20190228] 的情况 if(isEndDayOfMonth(end) && Integer.parseInt(DateFormatUtils.format(begin, "dd"))>Integer.parseInt(DateFormatUtils.format(end, "dd"))){ return Long.parseLong(period) + 1; }else{ return Long.parseLong(period); } } /** * 获取指定日期相隔一定天数后的日期 * @see 该方法等效于org.apache.commons.lang3.time.DateUtils.addDays(startDate, days) * @param startDate 参照日期 * @param days 相隔的天数,正数时则往后计算,负数则往前计算 */ public static Date getIncreaseDate(Date startDate, int days){ final Calendar cal = Calendar.getInstance(); cal.setTime(startDate); cal.add(Calendar.DAY_OF_MONTH, days); return cal.getTime(); } /** * 根据日期获得星期 * @param date 字符串格式的日期,可传入20170719或者2017-07-19 * @return 星期日、星期一、星期二、星期三、星期四、星期五、星期六 */ public static String getWeekName(String dateStr){ dateStr = dateStr.replaceAll("-", ""); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); Date date; try { date = sdf.parse(dateStr); } catch (ParseException e) { throw new IllegalArgumentException("无效入参,格式应为20170719或者2017-07-19"); } return getWeekName(date); } /** * 根据日期获得星期 * @return 星期日、星期一、星期二、星期三、星期四、星期五、星期六 */ public static String getWeekName(Date date){ String[] weekNames = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" }; Calendar calendar = Calendar.getInstance(); calendar.setTime(date); int weekNameIndex = calendar.get(Calendar.DAY_OF_WEEK) - 1; if(weekNameIndex < 0){ weekNameIndex = 0; } return weekNames[weekNameIndex]; } /** * 获取两个日期之间的所有日期列表 * @param startDate 起始日期,格式为yyyyMMdd * @param endDate 结束日期,格式为yyyyMMdd * @return 返回值不包含起始日期和结束日期 */ public static List<Integer> getCrossDayList(String startDate, String endDate){ List<Integer> dayList = new ArrayList<>(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); Calendar startDay = Calendar.getInstance(); Calendar endDay = Calendar.getInstance(); try { startDay.setTime(sdf.parse(startDate)); endDay.setTime(sdf.parse(endDate)); } catch (ParseException e) { throw new IllegalArgumentException("无效入参:" + e.getMessage()); } //起始日期大于等于结束日期,则返回空列表 if(startDay.compareTo(endDay) >= 0){ return dayList; } while(true){ //日期+1,并判断是否到达了结束日 startDay.add(Calendar.DATE, 1); if(startDay.compareTo(endDay) == 0){ break; } dayList.add(Integer.parseInt(DateFormatUtils.format(startDay.getTime(), "yyyyMMdd"))); } return dayList; } }