package com.java110.utils.util; import java.math.BigDecimal; import java.sql.Timestamp; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Period; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.*; /** * Created by wuxw on 2017/7/24. */ public class DateUtil { public static final String DATE_FORMATE_STRING_MILLI = "yyyyMMddHHmmssSSS"; // 17位:年月日时分秒毫秒 private static DateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss"); public static final String LAST_TIME = "2050-01-01 00:00:00"; public static int getTotalDaysInMonth(int year, int month) { LocalDate date = LocalDate.of(year, month, 1); // 创建一个日期对象,年份和月份为指定值,日期为1号 return date.lengthOfMonth(); // 返回该月的天数 } private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); public static boolean isValidDate(String dateStr) { // ✅ 关键修复:先彻底去除前后空白(包括空格、制表符、换行) if (dateStr == null || dateStr.isEmpty()) { return true; } // 去掉所有空白后再校验 String cleanDate = dateStr.trim(); try { LocalDate.parse(cleanDate, DATE_FORMATTER); return true; } catch (DateTimeParseException e) { return false; } } private static Map formats = new HashMap(); public static final String DATE_FORMATE_STRING_DEFAULT = "yyyyMMddHHmmss"; public static final String DATE_FORMATE_STRING_A = "yyyy-MM-dd HH:mm:ss"; public static final String DATE_FORMATE_STRING_B = "yyyy-MM-dd"; public static final String DATE_FORMATE_STRING_SLASH_NON_ZERO = "yyyy/M/d"; public static final String DATE_FORMATE_STRING_C = "MM/dd/yyyy HH:mm:ss a"; public static final String DATE_FORMATE_STRING_D = "yyyy-MM-dd HH:mm:ss a"; public static final String DATE_FORMATE_STRING_E = "yyyy-MM-dd'T'HH:mm:ss'Z'"; public static final String DATE_FORMATE_STRING_F = "yyyy-MM-dd'T'HH:mm:ssZ"; public static final String DATE_FORMATE_STRING_G = "yyyy-MM-dd'T'HH:mm:ssz"; public static final String DATE_FORMATE_STRING_H = "yyyyMMdd"; public static final String DATE_FORMATE_STRING_I = "yyyy-MM-dd HH:mm:ss.SSS"; public static final String DATE_FORMATE_STRING_J = "yyyyMMddHHmmss.SSS"; public static final String DATE_FORMATE_STRING_K = "yyyyMMddHHmmssSSS"; public static final String DATE_FORMATE_STRING_L = "MMdd"; public static final String DATE_FORMATE_STRING_M = "yyyyMM"; public static final String DATE_FORMATE_STRING_N = "HHmmss"; public static final String DATE_FORMATE_STRING_O = "yyyyMMddHHmm"; public static final String DATE_FORMATE_STRING_Q = "yyyy-MM"; private static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); static { formats.put("yyyyMMddHHmmss", new SimpleDateFormat("yyyyMMddHHmmss")); formats.put("yyyy-MM-dd HH:mm:ss", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); formats.put("yyyy-MM-dd", new SimpleDateFormat("yyyy-MM-dd")); formats.put("yyyy/MM/dd", new SimpleDateFormat("yyyy/M/d")); formats.put("MM/dd/yyyy HH:mm:ss a", new SimpleDateFormat("MM/dd/yyyy HH:mm:ss a")); formats.put("yyyy-MM-dd HH:mm:ss a", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a")); formats.put("yyyy-MM-dd'T'HH:mm:ss'Z'", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")); formats.put("yyyy-MM-dd'T'HH:mm:ssZ", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")); formats.put("yyyy-MM-dd'T'HH:mm:ssz", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz")); formats.put("yyyyMMdd", new SimpleDateFormat("yyyyMMdd")); formats.put("yyyy-MM-dd HH:mm:ss.SSS", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")); formats.put("yyyyMMddHHmmss.SSS", new SimpleDateFormat("yyyyMMddHHmmss.SSS")); formats.put("yyyyMMddHHmmssSSS", new SimpleDateFormat("yyyyMMddHHmmssSSS")); formats.put("MMdd", new SimpleDateFormat("MMdd")); formats.put("yyyyMM", new SimpleDateFormat("yyyyMM")); formats.put("HHmmss", new SimpleDateFormat("HHmmss")); formats.put("yyyyMMddHHmm", new SimpleDateFormat("yyyyMMddHHmm")); formats.put("yyyy-MM", new SimpleDateFormat("yyyy-MM")); } /** * 返回 yyyyMMddhhmmss 格式的日期串 * * @return */ public static String getyyyyMMddhhmmssDateString() { return dateFormat.format(new Date()); } /** * 获取当前时间 * * @return */ public static Date getCurrentDate() { Calendar calendar = Calendar.getInstance(); return calendar.getTime(); } /** * 获取当前月 * * @return */ public static int getCurrentMonth() { Calendar calendar = Calendar.getInstance(); return calendar.get(Calendar.MONTH) + 1; } public static Date getLastDate() throws ParseException { return getDateFromString("2037-12-01", DATE_FORMATE_STRING_B); } /** * 转TimeStamp * * @param date * @return */ public static Timestamp getTimestamp(Date date) { Timestamp timestamp = new Timestamp(date.getTime()); return timestamp; } /** * 获取未来时间 * * @param second 秒 * @return */ public static Date getFutureDate(int second) { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.SECOND, second); return calendar.getTime(); } public static String getFormatTimeString(Date date, String pattern) { SimpleDateFormat sDateFormat = getDateFormat(pattern); synchronized (sDateFormat) { return sDateFormat.format(date); } } public static String getFormatTimeStringA(Date date) { SimpleDateFormat sDateFormat = getDateFormat(DateUtil.DATE_FORMATE_STRING_A); synchronized (sDateFormat) { return sDateFormat.format(date); } } public static String getFormatTimeStringB(Date date) { SimpleDateFormat sDateFormat = getDateFormat(DateUtil.DATE_FORMATE_STRING_B); synchronized (sDateFormat) { return sDateFormat.format(date); } } public static String getDefaultFormateTimeString(Date date) { return getFormatTimeString(date, "yyyyMMddHHmmss"); } public static SimpleDateFormat getDateFormat(String pattern) { SimpleDateFormat sDateFormat = (SimpleDateFormat) formats.get(pattern); if (sDateFormat == null) { sDateFormat = new SimpleDateFormat(pattern); formats.put(pattern, sDateFormat); } return sDateFormat; } public static Date getDateFromString(String date, String pattern) throws ParseException { SimpleDateFormat sDateFormat = getDateFormat(pattern); synchronized (sDateFormat) { return sDateFormat.parse(date); } } public static Date getDateFromStringB(String date) { SimpleDateFormat sDateFormat = getDateFormat(DateUtil.DATE_FORMATE_STRING_B); try { synchronized (sDateFormat) { return sDateFormat.parse(date); } } catch (Exception e) { throw new IllegalArgumentException(e); } } public static Date getDateFromStringA(String date) { SimpleDateFormat sDateFormat = getDateFormat(DateUtil.DATE_FORMATE_STRING_A); try { synchronized (sDateFormat) { return sDateFormat.parse(date); } } catch (Exception e) { e.printStackTrace(); throw new IllegalArgumentException(e); } } public static Date getDefaultDateFromString(String date) throws ParseException { return getDateFromString(date, "yyyyMMddHHmmss"); } public static String getNowDefault() { return getNow("yyyyMMddHHmmss"); } public static String getNow(String pattern) { return getFormatTimeString(new Date(), pattern); } public static String getLastTime() { return LAST_TIME; } public static String getNowII() { return getFormatTimeString(new Date(), "yyyyMMdd"); } public static long dateString2Long(String str, String pattern) throws ParseException { return getDateFromString(str, pattern).getTime(); } /** * 校验字符串是否可以格式化为时间 * * @param str * @param pattern * @return */ public static boolean judgeDate(String str, String pattern) { try { dateString2Long(str, pattern); } catch (Exception e) { return false; } return true; } public static String longToDateStringDefault(long time) { return getFormatTimeString(new Date(time), "yyyyMMddHHmmss"); } public static String longToDateString(long time, String pattern) { return getFormatTimeString(new Date(time), pattern); } public static long date2Long(Date date) { return date.getTime(); } public static Date longToDate(long time) { return new Date(time); } public static Date getDateFromStringAdaptTwoPattern(String date) throws ParseException { try { return getDateFromString(date, "yyyy-MM-dd HH:mm:ss"); } catch (ParseException e) { } return getDateFromString(date, "yyyy-MM-dd"); } public static String changeNumDateToDate(String numdate, String inFormat, String outFormat) throws ParseException { Date date = getDateFromString(numdate, inFormat); return getFormatTimeString(date, outFormat); } public static String getNextMonthFistDay(String nowdate, String inFormat, String outFormat) throws ParseException { Date date = getDateFromString(nowdate, inFormat); Calendar cl = Calendar.getInstance(); cl.setTime(date); cl.set(2, cl.get(2) + 1); cl.set(5, 1); date = cl.getTime(); return getFormatTimeString(date, outFormat); } public static boolean isLeapYear(int year) { if (year % 400 == 0) return true; if (year % 4 == 0) { return (year % 100 != 0); } return false; } public static String getLastDay(String nowdate, String inFormat, String outFormat) throws ParseException { String returndate = ""; Date date = getDateFromString(nowdate, inFormat); Calendar cl = Calendar.getInstance(); cl.setTime(date); switch (cl.get(2)) { case 0: cl.set(5, 31); break; case 1: int year = cl.get(1); if (isLeapYear(year)) cl.set(5, 29); else { cl.set(5, 28); } break; case 2: cl.set(5, 31); break; case 3: cl.set(5, 30); break; case 4: cl.set(5, 31); break; case 5: cl.set(5, 30); break; case 6: cl.set(5, 31); break; case 7: cl.set(5, 31); break; case 8: cl.set(5, 30); break; case 9: cl.set(5, 31); break; case 10: cl.set(5, 30); break; case 11: cl.set(5, 31); } date = cl.getTime(); returndate = getFormatTimeString(date, outFormat); return returndate; } public static String getMonthLastDay(String fmt) { String returndate = ""; Date date = null; Calendar cl = Calendar.getInstance(); switch (cl.get(2)) { case 0: cl.set(5, 31); break; case 1: int year = cl.get(1); if (isLeapYear(year)) cl.set(5, 29); else { cl.set(5, 28); } break; case 2: cl.set(5, 31); break; case 3: cl.set(5, 30); break; case 4: cl.set(5, 31); break; case 5: cl.set(5, 30); break; case 6: cl.set(5, 31); break; case 7: cl.set(5, 31); break; case 8: cl.set(5, 30); break; case 9: cl.set(5, 31); break; case 10: cl.set(5, 30); break; case 11: cl.set(5, 31); } date = cl.getTime(); returndate = getFormatTimeString(date, fmt); return returndate; } public static Date getNextMonthFirstDate() { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.DAY_OF_MONTH, 1); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.add(Calendar.MONTH, 1); return calendar.getTime(); } public static Date getNextMonthFirstDate(String curDate) { Date date = DateUtil.getDateFromStringB(curDate); return getNextMonthFirstDate(date); } public static Date getNextMonthFirstDate(Date curDate) { return getNextMonthFirstDate(curDate, 1); } public static Date getNextMonthFirstDate(Date curDate, int monthCount) { Calendar curDateCal = Calendar.getInstance(); curDateCal.setTime(curDate); curDateCal.set(Calendar.DAY_OF_MONTH, 1); curDateCal.set(Calendar.HOUR_OF_DAY, 0); curDateCal.set(Calendar.MINUTE, 0); curDateCal.set(Calendar.SECOND, 0); curDateCal.add(Calendar.MONTH, monthCount); return curDateCal.getTime(); } public static Date getFirstDate() { Calendar curDateCal = Calendar.getInstance(); curDateCal.set(Calendar.DAY_OF_MONTH, 1); curDateCal.set(Calendar.HOUR_OF_DAY, 0); curDateCal.set(Calendar.MINUTE, 0); curDateCal.set(Calendar.SECOND, 0); Date curDate = curDateCal.getTime(); return curDate; } public static Date getFirstDate(Date curDate) { Calendar curDateCal = Calendar.getInstance(); curDateCal.setTime(curDate); curDateCal.set(Calendar.DAY_OF_MONTH, 1); curDateCal.set(Calendar.HOUR_OF_DAY, 0); curDateCal.set(Calendar.MINUTE, 0); curDateCal.set(Calendar.SECOND, 0); return curDateCal.getTime(); } public static Date getFirstDate(String curDate) { Date date = DateUtil.getDateFromStringB(curDate); Calendar curDateCal = Calendar.getInstance(); curDateCal.setTime(date); curDateCal.set(Calendar.DAY_OF_MONTH, 1); curDateCal.set(Calendar.HOUR_OF_DAY, 0); curDateCal.set(Calendar.MINUTE, 0); curDateCal.set(Calendar.SECOND, 0); return curDateCal.getTime(); } public static String getNextMonthFirstDay(String fmt) { String returndate = ""; Date date = getNextMonthFirstDate(); returndate = getFormatTimeString(date, fmt); return returndate; } public static boolean compareDate(String fistDate, String secondDate, String format) throws ParseException { boolean flag = false; Date fist = null; Date second = null; fist = getDateFromString(fistDate, format); second = getDateFromString(secondDate, format); if (fist.before(second)) { flag = true; } return flag; } public static boolean isRightDate(String value, String varValue) { try { SimpleDateFormat format = new SimpleDateFormat(varValue); format.setLenient(false); format.parse(value); } catch (ParseException e) { return false; } return true; } public static int getCurrentMonthDay() { Calendar a = Calendar.getInstance(); a.set(Calendar.DATE, 1); a.roll(Calendar.DATE, -1); int maxDate = a.get(Calendar.DATE); return maxDate; } public static int getMonthDay(Date date) { Calendar a = Calendar.getInstance(); a.setTime(date); return a.getActualMaximum(Calendar.DAY_OF_MONTH); } public static String getAddDayString(Date date, String pattern, int days) { SimpleDateFormat sf = new SimpleDateFormat(pattern); Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.DAY_OF_MONTH, days); return sf.format(c.getTime()); } public static String getAddDayStringB(Date date, int days) { SimpleDateFormat sf = new SimpleDateFormat(DATE_FORMATE_STRING_B); Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.DAY_OF_MONTH, days); return sf.format(c.getTime()); } public static String getAddDayStringA(Date date, int days) { SimpleDateFormat sf = new SimpleDateFormat(DATE_FORMATE_STRING_A); Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.DAY_OF_MONTH, days); return sf.format(c.getTime()); } public static String getAddHoursStringA(Date date, int hours) { SimpleDateFormat sf = new SimpleDateFormat(DATE_FORMATE_STRING_A); Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.HOUR_OF_DAY, hours); return sf.format(c.getTime()); } public static String getAddMonthStringA(Date date, int month) { SimpleDateFormat sf = new SimpleDateFormat(DATE_FORMATE_STRING_A); Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.MONTH, month); return sf.format(c.getTime()); } /** * 在给定的日期加上或减去指定月份后的日期 * * @param sourceDate 原始时间 * @param month 要调整的月份,向前为负数,向后为正数 * @return */ public static Date stepMonth(Date sourceDate, int month) { Calendar c = Calendar.getInstance(); c.setTime(sourceDate); c.add(Calendar.MONTH, month); return c.getTime(); } /** * 在给定的日期加上或减去指定天数后的日期 * * @param sourceDate 原始时间 * @param day 要调整的月份,向前为负数,向后为正数 * @return */ public static Date stepDay(Date sourceDate, int day) { Calendar c = Calendar.getInstance(); c.setTime(sourceDate); c.add(Calendar.DATE, day); return c.getTime(); } public static String dateTimeToDate(String dateTime) { String dateStr = ""; try { Date date = getDateFromString(dateTime, DATE_FORMATE_STRING_A); dateStr = getFormatTimeString(date, DATE_FORMATE_STRING_B); } catch (ParseException e) { dateStr = dateTime; } return dateStr; } public static int getYear() { Date date = getCurrentDate(); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); return calendar.get(Calendar.YEAR); } public static int getMonth() { Date date = getCurrentDate(); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); return calendar.get(Calendar.MONTH) + 1; } /** * 判断时间是否在时间段内 * * @param nowTime * @param beginTime * @param endTime * @return */ public static boolean belongCalendar(Date nowTime, Date beginTime, Date endTime) { Calendar date = Calendar.getInstance(); date.setTime(nowTime); Calendar begin = Calendar.getInstance(); begin.setTime(beginTime); Calendar end = Calendar.getInstance(); end.setTime(endTime); if (date.after(begin) && date.before(end)) { return true; } else if (nowTime.compareTo(beginTime) == 0 || nowTime.compareTo(endTime) == 0) { return true; } else { return false; } } //获取两个日期之间的天数 public static int daysBetween(Date now, Date returnDate) { Calendar cNow = Calendar.getInstance(); Calendar cReturnDate = Calendar.getInstance(); cNow.setTime(now); cReturnDate.setTime(returnDate); setTimeToMidnight(cNow); setTimeToMidnight(cReturnDate); long todayMs = cNow.getTimeInMillis(); long returnMs = cReturnDate.getTimeInMillis(); long intervalMs = todayMs - returnMs; return millisecondsToDays(intervalMs); } //获取两个日期之间的毫秒数 private static void setTimeToMidnight(Calendar calendar) { calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); } //获取两个日期之间的分钟数 private static int millisecondsToDays(long intervalMs) { return (int) (intervalMs / (1000 * 86400)); } /** *    *字符串的日期格式的计算 */ public static int daysBetween(String smdate, String bdate) { long between_days = 0; try { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Calendar cal = Calendar.getInstance(); cal.setTime(sdf.parse(smdate)); long time1 = cal.getTimeInMillis(); cal.setTime(sdf.parse(bdate)); long time2 = cal.getTimeInMillis(); between_days = (time2 - time1) / (1000 * 3600 * 24); } catch (Exception e) { e.printStackTrace(); } return Integer.parseInt(String.valueOf(between_days)); } // public static double dayCompare(Date fromDate, Date toDate) { // double resMonth = 0.0; // Calendar from = Calendar.getInstance(); // from.setTime(fromDate); // Calendar to = Calendar.getInstance(); // to.setTime(toDate); // //比较月份差 可能有整数 也会负数 // int result = to.get(Calendar.MONTH) - from.get(Calendar.MONTH); // //比较年差 // int month = (to.get(Calendar.YEAR) - from.get(Calendar.YEAR)) * 12; // // //真实 相差月份 // result = result + month; // // //开始时间 2021-06-01 2021-08-05 result = 2 2021-08-01 // Calendar newFrom = Calendar.getInstance(); // newFrom.setTime(fromDate); // newFrom.add(Calendar.MONTH, result); // //如果加月份后 大于了当前时间 默认加 月份 -1 情况 12-19 21-01-10 // //这个是神的逻辑一定好好理解 // if (newFrom.getTime().getTime() > toDate.getTime()) { // newFrom.setTime(fromDate); // result = result - 1; // newFrom.add(Calendar.MONTH, result); // } // // // t1 2021-08-01 t2 2021-08-05 // long t1 = newFrom.getTime().getTime(); // long t2 = to.getTime().getTime(); // //相差毫秒 // double days = (t2 - t1) * 1.00 / (24 * 60 * 60 * 1000); // BigDecimal tmpDays = new BigDecimal(days); //相差天数 // BigDecimal monthDay = null; // Calendar newFromMaxDay = Calendar.getInstance(); // newFromMaxDay.set(newFrom.get(Calendar.YEAR), newFrom.get(Calendar.MONTH), 1, 0, 0, 0); // newFromMaxDay.add(Calendar.MONTH, 1); //下个月1号 // //在当前月中 这块有问题 // if (toDate.getTime() < newFromMaxDay.getTime().getTime()) { // monthDay = new BigDecimal(newFrom.getActualMaximum(Calendar.DAY_OF_MONTH)); // return tmpDays.divide(monthDay, 4, BigDecimal.ROUND_HALF_UP).add(new BigDecimal(result)).doubleValue(); // } // // 上月天数 // days = (newFromMaxDay.getTimeInMillis() - t1) * 1.00 / (24 * 60 * 60 * 1000); // tmpDays = new BigDecimal(days); // monthDay = new BigDecimal(newFrom.getActualMaximum(Calendar.DAY_OF_MONTH)); // BigDecimal preRresMonth = tmpDays.divide(monthDay, 4, BigDecimal.ROUND_HALF_UP); // // //下月天数 // days = (t2 - newFromMaxDay.getTimeInMillis()) * 1.00 / (24 * 60 * 60 * 1000); // tmpDays = new BigDecimal(days); // monthDay = new BigDecimal(newFromMaxDay.getActualMaximum(Calendar.DAY_OF_MONTH)); // resMonth = tmpDays.divide(monthDay, 4, BigDecimal.ROUND_HALF_UP).add(new BigDecimal(result)).add(preRresMonth).doubleValue(); // return resMonth; // } /** * 通过时间秒毫秒数判断两个时间的间隔 * * @param date1 * @param date2 * @return */ public static int differentDaysUp(Date date1, Date date2) { double days = ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24 * 1.00)); return new Double(Math.ceil(days)).intValue(); } /** * 获取两个日期之间的所有月份 (年月) * * @param startTime * @param endTime * @return:list */ public static List getMonthBetweenDate(Date startTime, Date endTime) { return getMonthBetweenDate(DateUtil.getFormatTimeStringA(startTime), DateUtil.getFormatTimeStringA(endTime)); } /** * 获取两个日期之间的所有月份 (年月) * * @param startTime * @param endTime * @return:list */ public static List getMonthBetweenDate(String startTime, String endTime) { SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMATE_STRING_Q); // 声明保存日期集合 List list = new ArrayList<>(); try { // 转化成日期类型 Date startDate = sdf.parse(startTime); Date endDate = sdf.parse(endTime); //用Calendar 进行日期比较判断 Calendar calendar = Calendar.getInstance(); while (startDate.getTime() <= endDate.getTime()) { // 把日期添加到集合 list.add(sdf.format(startDate)); // 设置日期 calendar.setTime(startDate); //把月数增加 1 calendar.add(Calendar.MONTH, 1); // 获取增加后的日期 startDate = calendar.getTime(); } } catch (Exception e) { e.printStackTrace(); } return list; } /** * 除去 小时 分 秒 * * @param time * @return */ public static Date timeToDate(Date time) { Calendar calendar = Calendar.getInstance(); calendar.setTime(time); setTimeToMidnight(calendar); return calendar.getTime(); } /** * 除去 小时 分 秒 * * deadtime 本来就少了一秒 * * @param time * @return */ public static Date deadTimeToDate(Date time) { Calendar calendar = Calendar.getInstance(); calendar.setTime(time); calendar.add(Calendar.SECOND,1); setTimeToMidnight(calendar); return calendar.getTime(); } public static boolean sameMonthDay(Date startDate, Date endDate) { Calendar startCalendar = Calendar.getInstance(); startCalendar.setTime(startDate); Calendar endCalender = Calendar.getInstance(); endCalender.setTime(endDate); if ( startCalendar.get(Calendar.DAY_OF_MONTH) == endCalender.get(Calendar.DAY_OF_MONTH) && startCalendar.get(Calendar.HOUR_OF_DAY) == endCalender.get(Calendar.HOUR_OF_DAY) ) { return true; } return false; } public static double dayCompare(Date fromDate, Date toDate) { return dayCompare(fromDate, toDate, false); } /** * 计算 fromDate 2023-01-12 toDate 2023-09-15 * 2023-01-12--->2023-01-01 ---> 2023-09-01 ------> 2023-09-15 * fromDate ---> fromDateFirstDate ---> toDateFirstDate ----> toDate * * @param fromDate * @param toDate * @return */ public static double dayCompare(Date fromDate, Date toDate, boolean plusOneSec) { if (plusOneSec) { Calendar toD = Calendar.getInstance(); toD.setTime(toDate); toD.add(Calendar.SECOND, 1); toDate = toD.getTime(); } //todo 需要计算三端时间 相加即可 Date fromDateFirstDate = fromDate; // 第一个1日 Date toDateFirstDate = toDate; // 最后一个1日 boolean firstDay = true; //todo 1.0 计算 fromDateFirstDate Calendar fromDateCal = Calendar.getInstance(); fromDateCal.setTime(fromDate); fromDateCal.set(Calendar.DAY_OF_MONTH, 1); fromDateCal.set(Calendar.HOUR_OF_DAY, 0); fromDateCal.set(Calendar.MINUTE, 0); if (fromDate.getTime() > fromDateCal.getTime().getTime()) { fromDateCal.add(Calendar.MONTH, 1); firstDay = false; fromDateFirstDate = fromDateCal.getTime(); } //todo 2.0 计算 toDateFirstDate Calendar toDateCal = Calendar.getInstance(); toDateCal.setTime(toDate); toDateCal.set(Calendar.DAY_OF_MONTH, 1); toDateCal.set(Calendar.HOUR_OF_DAY, 0); toDateCal.set(Calendar.MINUTE, 0); if (toDate.getTime() > toDateCal.getTime().getTime()) { toDateFirstDate = toDateCal.getTime(); } // todo 3.0 计算整数月 fromDateFirstDate ---> toDateFirstDate Calendar from = Calendar.getInstance(); from.setTime(fromDateFirstDate); Calendar to = Calendar.getInstance(); to.setTime(toDateFirstDate); //比较月份差 可能有整数 也会负数 int result = to.get(Calendar.MONTH) - from.get(Calendar.MONTH); //比较年差 int month = (to.get(Calendar.YEAR) - from.get(Calendar.YEAR)) * 12; //真实 相差月份 result = result + month; //todo 3.1 如果 fromDate 和toDate 是同一天 则直接返回整月,不再计算 4.0 和5.0 if (DateUtil.sameMonthDay(fromDate, toDate)) { return firstDay ? result : result + 1; } // todo 4.0 计算 fromDate ---> fromDateFirstDate 的月份 double days = (fromDateFirstDate.getTime() - fromDate.getTime()) * 1.00 / (24 * 60 * 60 * 1000); BigDecimal tmpDays = new BigDecimal(days); //相差天数 BigDecimal monthDay = new BigDecimal(DateUtil.getMonthDay(fromDate)); BigDecimal resMonth = tmpDays.divide(monthDay, 4, BigDecimal.ROUND_HALF_UP).add(new BigDecimal(result)); // todo 5.0 计算 toDateFirstDate ----> toDate 月份 days = (toDate.getTime() - toDateFirstDate.getTime()) * 1.00 / (24 * 60 * 60 * 1000); tmpDays = new BigDecimal(days); //相差天数 monthDay = new BigDecimal(DateUtil.getMonthDay(toDate)); resMonth = tmpDays.divide(monthDay, 4, BigDecimal.ROUND_HALF_UP).add(resMonth); return resMonth.doubleValue(); } public static Date getTargetEndTime(double month, Date startDate) { Calendar endDate = Calendar.getInstance(); endDate.setTime(startDate); Double intMonth = Math.floor(month); endDate.add(Calendar.MONTH, intMonth.intValue()); double doubleMonth = month - intMonth; if (doubleMonth <= 0) { return endDate.getTime(); } int futureDay = endDate.getActualMaximum(Calendar.DAY_OF_MONTH); Double hour = doubleMonth * futureDay * 24; endDate.add(Calendar.HOUR_OF_DAY, hour.intValue()); return endDate.getTime(); } public static String getNextSecTime(String time) { Date tTime = getDateFromStringA(time); return getNextSecTime(tTime); } public static Date getNextSecDateTime(Date time) { Calendar calendar = Calendar.getInstance(); calendar.setTime(time); calendar.add(Calendar.SECOND, 1); return calendar.getTime(); } public static String getNextSecTime(Date time) { Calendar calendar = Calendar.getInstance(); calendar.setTime(time); calendar.add(Calendar.SECOND, 1); return getFormatTimeStringA(calendar.getTime()); } public static String getPreSecTime(String time) { Date tTime = getDateFromStringA(time); return getPreSecTime(tTime); } public static String getPreSecTime(Date time) { Calendar calendar = Calendar.getInstance(); calendar.setTime(time); calendar.add(Calendar.SECOND, -1); return getFormatTimeStringA(calendar.getTime()); } public static Date getPreSecTime(Date time,int month) { Calendar calendar = Calendar.getInstance(); calendar.setTime(time); calendar.add(Calendar.MONTH,month); calendar.add(Calendar.SECOND, -1); return calendar.getTime(); } public static String getPreSecTimeStr(Date time,int month) { return getFormatTimeStringB(getPreSecTime(time,month)); } public static String calculateTimeDifference(Date start, Date end) { Duration duration = Duration.between(start.toInstant(), end.toInstant()); long days = duration.toDays(); long hours = duration.toHours() % 24; long minutes = duration.toMinutes() % 60; StringBuilder result = new StringBuilder(); if (days > 0) { result.append(days).append("天"); } if (hours > 0) { result.append(hours).append("时"); } if (minutes > 0 || (days == 0 && hours == 0 && minutes == 0)) { result.append(minutes).append("分"); } return result.toString(); } /** * 计算两个字符串日期之间的月数(超过一个整月则+1) * @param startDateStr 开始日期字符串 * @param endDateStr 结束日期字符串 * @return 月数差 */ public static int calculateMonths(String startDateStr, String endDateStr) { startDateStr = dateTimeToDate(startDateStr); endDateStr = dateTimeToDate(endDateStr); // 解析时间字符串为LocalDateTime LocalDateTime start = LocalDateTime.parse(startDateStr + " 00:00:00", DEFAULT_FORMATTER); LocalDateTime end = LocalDateTime.parse(endDateStr + " 23:59:59", DEFAULT_FORMATTER); // 确保开始时间在结束时间之前 if (start.isAfter(end)) { LocalDateTime temp = start; start = end; end = temp; } // 提取日期部分计算完整月数 Period period = Period.between(start.toLocalDate(), end.toLocalDate()); int fullMonths = period.getYears() * 12 + period.getMonths(); // 计算完整月数后的目标时间(用于判断是否刚好整月) LocalDateTime targetTime = start.plusYears(period.getYears()).plusMonths(period.getMonths()); // 判断实际结束时间是否超过目标时间(即存在额外时间) boolean hasExtraTime = end.isAfter(targetTime); // 有额外时间则加1个月 if (hasExtraTime) { fullMonths++; } return fullMonths; } public static void main(String[] args) throws ParseException { // SimpleDateFormat sf = new SimpleDateFormat(DateUtil.DATE_FORMATE_STRING_A); // Calendar c = Calendar.getInstance(); // c.setTime(DateUtil.getDateFromString("2021-12-03",DateUtil.DATE_FORMATE_STRING_A)); // c.add(Calendar.DAY_OF_MONTH, 125); // System.out.println("增加一天后日期:"+sf.format(c.getTime())); System.out.println(calculateMonths("2025-02-01 00:00:00", "2025-02-28")); } }