浏览代码

update 优化 重构DateUtils工具类 更加实用

疯狂的狮子Li 6 月之前
父节点
当前提交
29c5ff89ba

+ 146 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/FormatsType.java

@@ -0,0 +1,146 @@
+package org.dromara.common.core.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.dromara.common.core.utils.StringUtils;
+
+/*
+ * 日期格式
+ * "yyyy":4位数的年份,例如:2023年表示为"2023"。
+ * "yy":2位数的年份,例如:2023年表示为"23"。
+ * "MM":2位数的月份,取值范围为01到12,例如:7月表示为"07"。
+ * "M":不带前导零的月份,取值范围为1到12,例如:7月表示为"7"。
+ * "dd":2位数的日期,取值范围为01到31,例如:22日表示为"22"。
+ * "d":不带前导零的日期,取值范围为1到31,例如:22日表示为"22"。
+ * "EEEE":星期的全名,例如:星期三表示为"Wednesday"。
+ * "E":星期的缩写,例如:星期三表示为"Wed"。
+ * "DDD" 或 "D":一年中的第几天,取值范围为001到366,例如:第200天表示为"200"。
+ * 时间格式
+ * "HH":24小时制的小时数,取值范围为00到23,例如:下午5点表示为"17"。
+ * "hh":12小时制的小时数,取值范围为01到12,例如:下午5点表示为"05"。
+ * "mm":分钟数,取值范围为00到59,例如:30分钟表示为"30"。
+ * "ss":秒数,取值范围为00到59,例如:45秒表示为"45"。
+ * "SSS":毫秒数,取值范围为000到999,例如:123毫秒表示为"123"。
+ */
+
+/**
+ * 日期格式与时间格式枚举
+ */
+@Getter
+@AllArgsConstructor
+public enum FormatsType {
+
+    /**
+     * 例如:2023年表示为"23"
+     */
+    YY("yy"),
+
+    /**
+     * 例如:2023年表示为"2023"
+     */
+    YYYY("yyyy"),
+
+    /**
+     * 例例如,2023年7月可以表示为 "2023-07"
+     */
+    YYYY_MM("yyyy-MM"),
+
+    /**
+     * 例如,日期 "2023年7月22日" 可以表示为 "2023-07-22"
+     */
+    YYYY_MM_DD("yyyy-MM-dd"),
+
+    /**
+     * 例如,当前时间如果是 "2023年7月22日下午3点30分",则可以表示为 "2023-07-22 15:30"
+     */
+    YYYY_MM_DD_HH_MM("yyyy-MM-dd HH:mm"),
+
+    /**
+     * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023-07-22 15:30:45"
+     */
+    YYYY_MM_DD_HH_MM_SS("yyyy-MM-dd HH:mm:ss"),
+
+    /**
+     * 例如:下午3点30分45秒,表示为 "15:30:45"
+     */
+    HH_MM_SS("HH:mm:ss"),
+
+    /**
+     * 例例如,2023年7月可以表示为 "2023/07"
+     */
+    YYYY_MM_SLASH("yyyy/MM"),
+
+    /**
+     * 例如,日期 "2023年7月22日" 可以表示为 "2023/07/22"
+     */
+    YYYY_MM_DD_SLASH("yyyy/MM/dd"),
+
+    /**
+     * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023/07/22 15:30:45"
+     */
+    YYYY_MM_DD_HH_MM_SLASH("yyyy/MM/dd HH:mm"),
+
+    /**
+     * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023/07/22 15:30:45"
+     */
+    YYYY_MM_DD_HH_MM_SS_SLASH("yyyy/MM/dd HH:mm:ss"),
+
+    /**
+     * 例例如,2023年7月可以表示为 "2023.07"
+     */
+    YYYY_MM_DOT("yyyy.MM"),
+
+    /**
+     * 例如,日期 "2023年7月22日" 可以表示为 "2023.07.22"
+     */
+    YYYY_MM_DD_DOT("yyyy.MM.dd"),
+
+    /**
+     * 例如,当前时间如果是 "2023年7月22日下午3点30分",则可以表示为 "2023.07.22 15:30"
+     */
+    YYYY_MM_DD_HH_MM_DOT("yyyy.MM.dd HH:mm"),
+
+    /**
+     * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023.07.22 15:30:45"
+     */
+    YYYY_MM_DD_HH_MM_SS_DOT("yyyy.MM.dd HH:mm:ss"),
+
+    /**
+     * 例如,2023年7月可以表示为 "202307"
+     */
+    YYYYMM("yyyyMM"),
+
+    /**
+     * 例如,2023年7月22日可以表示为 "20230722"
+     */
+    YYYYMMDD("yyyyMMdd"),
+
+    /**
+     * 例如,2023年7月22日下午3点可以表示为 "2023072215"
+     */
+    YYYYMMDDHH("yyyyMMddHH"),
+
+    /**
+     * 例如,2023年7月22日下午3点30分可以表示为 "202307221530"
+     */
+    YYYYMMDDHHMM("yyyyMMddHHmm"),
+
+    /**
+     * 例如,2023年7月22日下午3点30分45秒可以表示为 "20230722153045"
+     */
+    YYYYMMDDHHMMSS("yyyyMMddHHmmss");
+
+    /**
+     * 时间格式
+     */
+    private final String timeFormat;
+
+    public static FormatsType getFormatsType(String str) {
+        for (FormatsType value : values()) {
+            if (StringUtils.contains(str, value.getTimeFormat())) {
+                return value;
+            }
+        }
+        throw new RuntimeException("'FormatsType' not found By " + str);
+    }
+}

+ 185 - 67
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java

@@ -3,16 +3,15 @@ package org.dromara.common.core.utils;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import org.apache.commons.lang3.time.DateFormatUtils;
+import org.dromara.common.core.enums.FormatsType;
+import org.dromara.common.core.exception.ServiceException;
 
 import java.lang.management.ManagementFactory;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
+import java.time.*;
 import java.util.Date;
+import java.util.concurrent.TimeUnit;
 
 /**
  * 时间工具类
@@ -21,86 +20,137 @@ import java.util.Date;
  */
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
-
-    public static final String YYYY = "yyyy";
-
-    public static final String YYYY_MM = "yyyy-MM";
-
-    public static final String YYYY_MM_DD = "yyyy-MM-dd";
-
-    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
-
-    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
-
     private static final String[] PARSE_PATTERNS = {
         "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
         "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
         "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
 
     /**
-     * 获取当前Date型日期
+     * 获取当前日期和时间
      *
-     * @return Date() 当前日期
+     * @return 当前日期和时间的 Date 对象表示
      */
     public static Date getNowDate() {
         return new Date();
     }
 
     /**
-     * 获取当前日期, 默认格式为yyyy-MM-dd
+     * 获取当前日期的字符串表示,格式为YYYY-MM-DD
      *
-     * @return String
+     * @return 当前日期的字符串表示
      */
     public static String getDate() {
-        return dateTimeNow(YYYY_MM_DD);
+        return dateTimeNow(FormatsType.YYYY_MM_DD);
+    }
+
+    /**
+     * 获取当前日期的字符串表示,格式为yyyyMMdd
+     *
+     * @return 当前日期的字符串表示
+     */
+    public static String getCurrentDate() {
+        return DateFormatUtils.format(new Date(), FormatsType.YYYYMMDD.getTimeFormat());
     }
 
+    /**
+     * 获取当前日期的路径格式字符串,格式为"yyyy/MM/dd"
+     *
+     * @return 当前日期的路径格式字符串
+     */
+    public static String datePath() {
+        Date now = new Date();
+        return DateFormatUtils.format(now, FormatsType.YYYY_MM_DD_SLASH.getTimeFormat());
+    }
+
+    /**
+     * 获取当前时间的字符串表示,格式为YYYY-MM-DD HH:MM:SS
+     *
+     * @return 当前时间的字符串表示
+     */
     public static String getTime() {
-        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+        return dateTimeNow(FormatsType.YYYY_MM_DD_HH_MM_SS);
     }
 
-    public static String dateTimeNow() {
-        return dateTimeNow(YYYYMMDDHHMMSS);
+    /**
+     * 获取当前时间的字符串表示,格式为 "HH:MM:SS"
+     *
+     * @return 当前时间的字符串表示,格式为 "HH:MM:SS"
+     */
+    public static String getTimeWithHourMinuteSecond() {
+        return dateTimeNow(FormatsType.HH_MM_SS);
     }
 
-    public static String dateTimeNow(final String format) {
-        return parseDateToStr(format, new Date());
+    /**
+     * 获取当前日期和时间的字符串表示,格式为YYYYMMDDHHMMSS
+     *
+     * @return 当前日期和时间的字符串表示
+     */
+    public static String dateTimeNow() {
+        return dateTimeNow(FormatsType.YYYYMMDDHHMMSS);
     }
 
-    public static String dateTime(final Date date) {
-        return parseDateToStr(YYYY_MM_DD, date);
+    /**
+     * 获取当前日期和时间的指定格式的字符串表示
+     *
+     * @param format 日期时间格式,例如"YYYY-MM-DD HH:MM:SS"
+     * @return 当前日期和时间的字符串表示
+     */
+    public static String dateTimeNow(final FormatsType format) {
+        return parseDateToStr(format, new Date());
     }
 
-    public static String parseDateToStr(final String format, final Date date) {
-        return new SimpleDateFormat(format).format(date);
+    /**
+     * 将指定日期格式化为 YYYY-MM-DD 格式的字符串
+     *
+     * @param date 要格式化的日期对象
+     * @return 格式化后的日期字符串
+     */
+    public static String formatDate(final Date date) {
+        return parseDateToStr(FormatsType.YYYY_MM_DD, date);
     }
 
-    public static Date dateTime(final String format, final String ts) {
-        try {
-            return new SimpleDateFormat(format).parse(ts);
-        } catch (ParseException e) {
-            throw new RuntimeException(e);
-        }
+    /**
+     * 将指定日期格式化为 YYYY-MM-DD HH:MM:SS 格式的字符串
+     *
+     * @param date 要格式化的日期对象
+     * @return 格式化后的日期时间字符串
+     */
+    public static String formatDateTime(final Date date) {
+        return parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, date);
     }
 
     /**
-     * 日期路径 即年/月/日 如2018/08/08
+     * 将指定日期按照指定格式进行格式化
+     *
+     * @param format 要使用的日期时间格式,例如"YYYY-MM-DD HH:MM:SS"
+     * @param date   要格式化的日期对象
+     * @return 格式化后的日期时间字符串
      */
-    public static String datePath() {
-        Date now = new Date();
-        return DateFormatUtils.format(now, "yyyy/MM/dd");
+    public static String parseDateToStr(final FormatsType format, final Date date) {
+        return new SimpleDateFormat(format.getTimeFormat()).format(date);
     }
 
     /**
-     * 日期路径 即年/月/日 如20180808
+     * 将指定格式的日期时间字符串转换为 Date 对象
+     *
+     * @param format 要解析的日期时间格式,例如"YYYY-MM-DD HH:MM:SS"
+     * @param ts     要解析的日期时间字符串
+     * @return 解析后的 Date 对象
+     * @throws RuntimeException 如果解析过程中发生异常
      */
-    public static String dateTime() {
-        Date now = new Date();
-        return DateFormatUtils.format(now, "yyyyMMdd");
+    public static Date parseDateTime(final FormatsType format, final String ts) {
+        try {
+            return new SimpleDateFormat(format.getTimeFormat()).parse(ts);
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     /**
-     * 日期型字符串转化为日期 格式
+     * 将对象转换为日期对象
+     *
+     * @param str 要转换的对象,通常是字符串
+     * @return 转换后的日期对象,如果转换失败或输入为null,则返回null
      */
     public static Date parseDate(Object str) {
         if (str == null) {
@@ -115,6 +165,8 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
 
     /**
      * 获取服务器启动时间
+     *
+     * @return 服务器启动时间的 Date 对象表示
      */
     public static Date getServerStartDate() {
         long time = ManagementFactory.getRuntimeMXBean().getStartTime();
@@ -122,35 +174,66 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
     }
 
     /**
-     * 计算相差天数
+     * 计算两个日期之间的天数差(以毫秒为单位)
+     *
+     * @param date1 第一个日期
+     * @param date2 第二个日期
+     * @return 两个日期之间的天数差的绝对值
      */
     public static int differentDaysByMillisecond(Date date1, Date date2) {
         return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
     }
 
     /**
-     * 计算两个时间差
+     * 计算两个日期之间的时间差,并以天、小时和分钟的格式返回
+     *
+     * @param endDate 结束日期
+     * @param nowDate 当前日期
+     * @return 表示时间差的字符串,格式为"天 小时 分钟"
      */
     public static String getDatePoor(Date endDate, Date nowDate) {
-        long nd = 1000 * 24 * 60 * 60;
-        long nh = 1000 * 60 * 60;
-        long nm = 1000 * 60;
-        // long ns = 1000;
-        // 获得两个时间的毫秒时间差异
-        long diff = endDate.getTime() - nowDate.getTime();
-        // 计算差多少天
-        long day = diff / nd;
-        // 计算差多少小时
-        long hour = diff % nd / nh;
-        // 计算差多少分钟
-        long min = diff % nd % nh / nm;
-        // 计算差多少秒//输出结果
-        // long sec = diff % nd % nh % nm / ns;
-        return day + "天" + hour + "小时" + min + "分钟";
-    }
-
-    /**
-     * 增加 LocalDateTime ==> Date
+        long diffInMillis = endDate.getTime() - nowDate.getTime();
+        long day = TimeUnit.MILLISECONDS.toDays(diffInMillis);
+        long hour = TimeUnit.MILLISECONDS.toHours(diffInMillis) % 24;
+        long min = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) % 60;
+        return String.format("%d天 %d小时 %d分钟", day, hour, min);
+    }
+
+    /**
+     * 计算两个时间点的差值(天、小时、分钟、秒),当值为0时不显示该单位
+     *
+     * @param endDate 结束时间
+     * @param nowDate 当前时间
+     * @return 时间差字符串,格式为 "x天 x小时 x分钟 x秒",若为 0 则不显示
+     */
+    public static String getTimeDifference(Date endDate, Date nowDate) {
+        long diffInMillis = endDate.getTime() - nowDate.getTime();
+        long day = TimeUnit.MILLISECONDS.toDays(diffInMillis);
+        long hour = TimeUnit.MILLISECONDS.toHours(diffInMillis) % 24;
+        long min = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) % 60;
+        long sec = TimeUnit.MILLISECONDS.toSeconds(diffInMillis) % 60;
+        // 构建时间差字符串,条件是值不为0才显示
+        StringBuilder result = new StringBuilder();
+        if (day > 0) {
+            result.append(String.format("%d天 ", day));
+        }
+        if (hour > 0) {
+            result.append(String.format("%d小时 ", hour));
+        }
+        if (min > 0) {
+            result.append(String.format("%d分钟 ", min));
+        }
+        if (sec > 0) {
+            result.append(String.format("%d秒", sec));
+        }
+        return result.length() > 0 ? result.toString().trim() : "0秒";
+    }
+
+    /**
+     * 将 LocalDateTime 对象转换为 Date 对象
+     *
+     * @param temporalAccessor 要转换的 LocalDateTime 对象
+     * @return 转换后的 Date 对象
      */
     public static Date toDate(LocalDateTime temporalAccessor) {
         ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
@@ -158,11 +241,46 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
     }
 
     /**
-     * 增加 LocalDate ==> Date
+     * 将 LocalDate 对象转换为 Date 对象
+     *
+     * @param temporalAccessor 要转换的 LocalDate 对象
+     * @return 转换后的 Date 对象
      */
     public static Date toDate(LocalDate temporalAccessor) {
         LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
         ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
         return Date.from(zdt.toInstant());
     }
+
+    /**
+     * 校验日期范围
+     *
+     * @param startDate 开始日期
+     * @param endDate   结束日期
+     * @param maxValue  最大时间跨度的限制值
+     * @param unit      时间跨度的单位,可选择 "DAYS"、"HOURS" 或 "MINUTES"
+     */
+    public static void validateDateRange(Date startDate, Date endDate, int maxValue, TimeUnit unit) {
+        // 校验结束日期不能早于开始日期
+        if (endDate.before(startDate)) {
+            throw new ServiceException("结束日期不能早于开始日期");
+        }
+
+        // 计算时间跨度
+        long diffInMillis = endDate.getTime() - startDate.getTime();
+
+        // 根据单位转换时间跨度
+        long diff = switch (unit) {
+            case DAYS -> TimeUnit.MILLISECONDS.toDays(diffInMillis);
+            case HOURS -> TimeUnit.MILLISECONDS.toHours(diffInMillis);
+            case MINUTES -> TimeUnit.MILLISECONDS.toMinutes(diffInMillis);
+            default -> throw new IllegalArgumentException("不支持的时间单位");
+        };
+
+        // 校验时间跨度不超过最大限制
+        if (diff > maxValue) {
+            throw new ServiceException("最大时间跨度为 " + maxValue + " " + unit.toString().toLowerCase());
+        }
+    }
+
 }