mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 12:18:42 +08:00 
			
		
		
		
	CRM:优化【客户统计】的代码实现
This commit is contained in:
		@@ -1,5 +1,6 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.common.enums;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.ArrayUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
 | 
			
		||||
import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
@@ -7,7 +8,7 @@ import lombok.Getter;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 时间间隔类型枚举
 | 
			
		||||
 * 时间间隔的枚举
 | 
			
		||||
 *
 | 
			
		||||
 * @author dhb52
 | 
			
		||||
 */
 | 
			
		||||
@@ -15,26 +16,19 @@ import java.util.Arrays;
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
public enum DateIntervalEnum implements IntArrayValuable {
 | 
			
		||||
 | 
			
		||||
    TODAY(1, "今天"),
 | 
			
		||||
    YESTERDAY(2, "昨天"),
 | 
			
		||||
    THIS_WEEK(3, "本周"),
 | 
			
		||||
    LAST_WEEK(4, "上周"),
 | 
			
		||||
    THIS_MONTH(5, "本月"),
 | 
			
		||||
    LAST_MONTH(6, "上月"),
 | 
			
		||||
    THIS_QUARTER(7, "本季度"),
 | 
			
		||||
    LAST_QUARTER(8, "上季度"),
 | 
			
		||||
    THIS_YEAR(9, "本年"),
 | 
			
		||||
    LAST_YEAR(10, "去年"),
 | 
			
		||||
    CUSTOMER(11, "自定义"),
 | 
			
		||||
    DAY(1, "天"),
 | 
			
		||||
    WEEK(2, "周"),
 | 
			
		||||
    MONTH(3, "月"),
 | 
			
		||||
    QUARTER(4, "季度"),
 | 
			
		||||
    YEAR(5, "年")
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DateIntervalEnum::getType).toArray();
 | 
			
		||||
    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DateIntervalEnum::getInterval).toArray();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 类型
 | 
			
		||||
     */
 | 
			
		||||
    private final Integer type;
 | 
			
		||||
 | 
			
		||||
    private final Integer interval;
 | 
			
		||||
    /**
 | 
			
		||||
     * 名称
 | 
			
		||||
     */
 | 
			
		||||
@@ -45,4 +39,8 @@ public enum DateIntervalEnum implements IntArrayValuable {
 | 
			
		||||
        return ARRAYS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static DateIntervalEnum valueOf(Integer interval) {
 | 
			
		||||
        return ArrayUtil.firstMatch(item -> item.getInterval().equals(interval), DateIntervalEnum.values());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -65,19 +65,11 @@ public class DateUtils {
 | 
			
		||||
        return new Date(System.currentTimeMillis() + duration.toMillis());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean isExpired(Date time) {
 | 
			
		||||
        return System.currentTimeMillis() > time.getTime();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean isExpired(LocalDateTime time) {
 | 
			
		||||
        LocalDateTime now = LocalDateTime.now();
 | 
			
		||||
        return now.isAfter(time);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static long diff(Date endTime, Date startTime) {
 | 
			
		||||
        return endTime.getTime() - startTime.getTime();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 创建指定时间
 | 
			
		||||
     *
 | 
			
		||||
@@ -134,37 +126,6 @@ public class DateUtils {
 | 
			
		||||
        return a.isAfter(b) ? a : b;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 计算当期时间相差的日期
 | 
			
		||||
     *
 | 
			
		||||
     * @param field  日历字段.<br/>eg:Calendar.MONTH,Calendar.DAY_OF_MONTH,<br/>Calendar.HOUR_OF_DAY等.
 | 
			
		||||
     * @param amount 相差的数值
 | 
			
		||||
     * @return 计算后的日志
 | 
			
		||||
     */
 | 
			
		||||
    public static Date addDate(int field, int amount) {
 | 
			
		||||
        return addDate(null, field, amount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 计算当期时间相差的日期
 | 
			
		||||
     *
 | 
			
		||||
     * @param date   设置时间
 | 
			
		||||
     * @param field  日历字段 例如说,{@link Calendar#DAY_OF_MONTH} 等
 | 
			
		||||
     * @param amount 相差的数值
 | 
			
		||||
     * @return 计算后的日志
 | 
			
		||||
     */
 | 
			
		||||
    public static Date addDate(Date date, int field, int amount) {
 | 
			
		||||
        if (amount == 0) {
 | 
			
		||||
            return date;
 | 
			
		||||
        }
 | 
			
		||||
        Calendar c = Calendar.getInstance();
 | 
			
		||||
        if (date != null) {
 | 
			
		||||
            c.setTime(date);
 | 
			
		||||
        }
 | 
			
		||||
        c.add(field, amount);
 | 
			
		||||
        return c.getTime();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否今天
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,18 @@
 | 
			
		||||
package cn.iocoder.yudao.framework.common.util.date;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.hutool.core.date.DatePattern;
 | 
			
		||||
import cn.hutool.core.date.LocalDateTimeUtil;
 | 
			
		||||
import cn.hutool.core.lang.Assert;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum;
 | 
			
		||||
 | 
			
		||||
import java.time.Duration;
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.time.LocalTime;
 | 
			
		||||
import java.time.*;
 | 
			
		||||
import java.time.format.DateTimeParseException;
 | 
			
		||||
import java.time.temporal.ChronoUnit;
 | 
			
		||||
import java.time.temporal.TemporalAdjusters;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 时间工具类,用于 {@link java.time.LocalDateTime}
 | 
			
		||||
@@ -21,6 +26,22 @@ public class LocalDateTimeUtils {
 | 
			
		||||
     */
 | 
			
		||||
    public static LocalDateTime EMPTY = buildTime(1970, 1, 1);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 解析时间
 | 
			
		||||
     *
 | 
			
		||||
     * 相比 {@link LocalDateTimeUtil#parse(CharSequence)} 方法来说,会尽量去解析,直到成功
 | 
			
		||||
     *
 | 
			
		||||
     * @param time 时间
 | 
			
		||||
     * @return 时间字符串
 | 
			
		||||
     */
 | 
			
		||||
    public static LocalDateTime parse(String time) {
 | 
			
		||||
        try {
 | 
			
		||||
            return LocalDateTimeUtil.parse(time, DatePattern.NORM_DATE_PATTERN);
 | 
			
		||||
        } catch (DateTimeParseException e) {
 | 
			
		||||
            return LocalDateTimeUtil.parse(time);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static LocalDateTime addTime(Duration duration) {
 | 
			
		||||
        return LocalDateTime.now().plus(duration);
 | 
			
		||||
    }
 | 
			
		||||
@@ -54,6 +75,21 @@ public class LocalDateTimeUtils {
 | 
			
		||||
        return new LocalDateTime[]{buildTime(year1, mouth1, day1), buildTime(year2, mouth2, day2)};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 判指定断时间,是否在该时间范围内
 | 
			
		||||
     *
 | 
			
		||||
     * @param startTime 开始时间
 | 
			
		||||
     * @param endTime 结束时间
 | 
			
		||||
     * @param time 指定时间
 | 
			
		||||
     * @return 是否
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime, String time) {
 | 
			
		||||
        if (startTime == null || endTime == null || time == null) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        return LocalDateTimeUtil.isIn(parse(time), startTime, endTime);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 判断当前时间是否在该时间范围内
 | 
			
		||||
     *
 | 
			
		||||
@@ -122,6 +158,16 @@ public class LocalDateTimeUtils {
 | 
			
		||||
        return date.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获得指定日期所在季度
 | 
			
		||||
     *
 | 
			
		||||
     * @param date 日期
 | 
			
		||||
     * @return 所在季度
 | 
			
		||||
     */
 | 
			
		||||
    public static int getQuarterOfYear(LocalDateTime date) {
 | 
			
		||||
        return (date.getMonthValue() - 1) / 3 + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取指定日期到现在过了几天,如果指定日期在当前日期之后,获取结果为负
 | 
			
		||||
     *
 | 
			
		||||
@@ -168,4 +214,94 @@ public class LocalDateTimeUtils {
 | 
			
		||||
        return LocalDateTime.now().with(TemporalAdjusters.firstDayOfYear()).with(LocalTime.MIN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List<LocalDateTime[]> getDateRangeList(LocalDateTime startTime,
 | 
			
		||||
                                                         LocalDateTime endTime,
 | 
			
		||||
                                                         Integer interval) {
 | 
			
		||||
        // 1.1 找到枚举
 | 
			
		||||
        DateIntervalEnum intervalEnum = DateIntervalEnum.valueOf(interval);
 | 
			
		||||
        Assert.notNull(intervalEnum, "interval({}} 找不到对应的枚举", interval);
 | 
			
		||||
        // 1.2 将时间对齐
 | 
			
		||||
        startTime = LocalDateTimeUtil.beginOfDay(startTime);
 | 
			
		||||
        endTime = LocalDateTimeUtil.endOfDay(endTime);
 | 
			
		||||
 | 
			
		||||
        // 2. 循环,生成时间范围
 | 
			
		||||
        List<LocalDateTime[]> timeRanges = new ArrayList<>();
 | 
			
		||||
        switch (intervalEnum) {
 | 
			
		||||
            case DateIntervalEnum.DAY:
 | 
			
		||||
                while (startTime.isBefore(endTime)) {
 | 
			
		||||
                    timeRanges.add(new LocalDateTime[]{startTime, startTime.plusDays(1).minusNanos(1)});
 | 
			
		||||
                    startTime = startTime.plusDays(1);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case DateIntervalEnum.WEEK:
 | 
			
		||||
                while (startTime.isBefore(endTime)) {
 | 
			
		||||
                    LocalDateTime endOfWeek = startTime.with(DayOfWeek.SUNDAY).plusDays(1).minusNanos(1);
 | 
			
		||||
                    timeRanges.add(new LocalDateTime[]{startTime, endOfWeek});
 | 
			
		||||
                    startTime = endOfWeek.plusNanos(1);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case DateIntervalEnum.MONTH:
 | 
			
		||||
                while (startTime.isBefore(endTime)) {
 | 
			
		||||
                    LocalDateTime endOfMonth = startTime.with(TemporalAdjusters.lastDayOfMonth()).plusDays(1).minusNanos(1);
 | 
			
		||||
                    timeRanges.add(new LocalDateTime[]{startTime, endOfMonth});
 | 
			
		||||
                    startTime = endOfMonth.plusNanos(1);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case DateIntervalEnum.QUARTER:
 | 
			
		||||
                while (startTime.isBefore(endTime)) {
 | 
			
		||||
                    LocalDateTime quarterEnd = startTime.withMonth(getQuarterOfYear(startTime) * 3 + 1)
 | 
			
		||||
                            .withDayOfMonth(1).minusNanos(1);
 | 
			
		||||
                    timeRanges.add(new LocalDateTime[]{startTime, quarterEnd});
 | 
			
		||||
                    startTime = quarterEnd.plusNanos(1);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case DateIntervalEnum.YEAR:
 | 
			
		||||
                while (startTime.isBefore(endTime)) {
 | 
			
		||||
                    LocalDateTime endOfYear = startTime.with(TemporalAdjusters.lastDayOfYear()).plusDays(1).minusNanos(1);
 | 
			
		||||
                    timeRanges.add(new LocalDateTime[]{startTime, endOfYear});
 | 
			
		||||
                    startTime = endOfYear.plusNanos(1);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                throw new IllegalArgumentException("Invalid interval: " + interval);
 | 
			
		||||
        }
 | 
			
		||||
        // 3. 兜底,最后一个时间,需要保持在 endTime 之前
 | 
			
		||||
        LocalDateTime[] lastTimeRange = CollUtil.getLast(timeRanges);
 | 
			
		||||
        if (lastTimeRange != null) {
 | 
			
		||||
            lastTimeRange[1] = endTime;
 | 
			
		||||
        }
 | 
			
		||||
        return timeRanges;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 格式化时间范围
 | 
			
		||||
     *
 | 
			
		||||
     * @param startTime 开始时间
 | 
			
		||||
     * @param endTime   结束时间
 | 
			
		||||
     * @param interval  时间间隔
 | 
			
		||||
     * @return 时间范围
 | 
			
		||||
     */
 | 
			
		||||
    public static String formatDateRange(LocalDateTime startTime, LocalDateTime endTime, Integer interval) {
 | 
			
		||||
        // 1. 找到枚举
 | 
			
		||||
        DateIntervalEnum intervalEnum = DateIntervalEnum.valueOf(interval);
 | 
			
		||||
        Assert.notNull(intervalEnum, "interval({}} 找不到对应的枚举", interval);
 | 
			
		||||
 | 
			
		||||
        // 2. 循环,生成时间范围
 | 
			
		||||
        switch (intervalEnum) {
 | 
			
		||||
            case DateIntervalEnum.DAY:
 | 
			
		||||
                return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATE_PATTERN);
 | 
			
		||||
            case DateIntervalEnum.WEEK:
 | 
			
		||||
                return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATE_PATTERN)
 | 
			
		||||
                        + StrUtil.format("(第 {} 周)", LocalDateTimeUtil.weekOfYear(startTime));
 | 
			
		||||
            case DateIntervalEnum.MONTH:
 | 
			
		||||
                return LocalDateTimeUtil.format(startTime, DatePattern.NORM_MONTH_PATTERN);
 | 
			
		||||
            case DateIntervalEnum.QUARTER:
 | 
			
		||||
                return StrUtil.format("{}-Q{}", startTime.getYear(), getQuarterOfYear(startTime));
 | 
			
		||||
            case DateIntervalEnum.YEAR:
 | 
			
		||||
                return LocalDateTimeUtil.format(startTime, DatePattern.NORM_YEAR_PATTERN);
 | 
			
		||||
            default:
 | 
			
		||||
                throw new IllegalArgumentException("Invalid interval: " + interval);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user