| | |
| | | import java.text.DateFormat; |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Calendar; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | 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 = "2038-01-01 00:00:00"; |
| | | 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<String, SimpleDateFormat> 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_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("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")); |
| | | |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | 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); |
| | |
| | | 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.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(); |
| | | } |
| | | |
| | | |
| | |
| | | return maxDate; |
| | | } |
| | | |
| | | 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("2021-12-07".compareTo(DateUtil.getNow(DateUtil.DATE_FORMATE_STRING_B))); |
| | | 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 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 int daysBetween(String smdate, String bdate) { |
| | | long between_days = 0; |
| | |
| | | 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; |
| | | } |
| | | // 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)); |
| | | 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<String> getMonthBetweenDate(Date startTime, Date endTime) { |
| | | return getMonthBetweenDate(DateUtil.getFormatTimeStringA(startTime), DateUtil.getFormatTimeStringA(endTime)); |
| | | } |
| | | |
| | | /** |
| | | * 获取两个日期之间的所有月份 (年月) |
| | | * |
| | | * @param startTime |
| | | * @param endTime |
| | | * @return:list |
| | | */ |
| | | public static List<String> getMonthBetweenDate(String startTime, String endTime) { |
| | | SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMATE_STRING_Q); |
| | | // 声明保存日期集合 |
| | | List<String> 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")); |
| | | } |
| | | |
| | | } |