import java.time.DayOfWeek;import java.time.LocalDate;import java.time.LocalDateTime;import java.time.Month;import java.time.temporal.*;/** * 日期类型 - 枚举类 * * @author mingrn97 <br > mingrn97@gmail.com * @date 2021/01/31 15:43 */public enum DateTimeType { /** 年份 */ YEAR("Year", "年份", new Chrono() { @Override protected Chrono computeInterval() { return computeInterval(LocalDate.now()); } @Override protected Chrono computeInterval(Temporal benchmark) { compute(benchmark, YEAR); return this; } }), /** 季度 */ QUARTER("Quarter", "季度", new Chrono() { @Override protected Chrono computeInterval() { return computeInterval(LocalDate.now()); } @Override protected Chrono computeInterval(Temporal benchmark) { compute(benchmark, QUARTER); return this; } }), /** 月份 */ MONTH("Month", "月份", new Chrono() { @Override protected Chrono computeInterval() { return computeInterval(LocalDate.now()); } @Override protected Chrono computeInterval(Temporal benchmark) { compute(benchmark, MONTH); return this; } }), /** 周 */ WEEK("Week", "周", new Chrono() { @Override protected Chrono computeInterval() { return computeInterval(LocalDate.now()); } @Override protected Chrono computeInterval(Temporal benchmark) { compute(benchmark, WEEK); return this; } }), /** 天 */ DAY("Day", "天", new Chrono() { @Override protected Chrono computeInterval() { return computeInterval(LocalDateTime.now()); } @Override protected Chrono computeInterval(Temporal benchmark) { compute(benchmark, DAY); return this; } }), ; private final String type; private final String phrase; private final Chrono chrono; DateTimeType(String type, String phrase, Chrono chrono) { this.type = type; this.phrase = phrase; this.chrono = chrono; } public String type() { return type; } public String phrase() { return phrase; } public Chrono chrono() { return chrono; } public static DateTimeType resolve(String type) { for (DateTimeType dateTimeType : values()) { if (dateTimeType.type.equalsIgnoreCase(type)) { return dateTimeType; } } return null; } public static String value(String type) { DateTimeType dateTimeType = resolve(type); if (dateTimeType == null) { throw new IllegalArgumentException("No matching constant for [" + type + "]"); } return dateTimeType.phrase; } public abstract static class Chrono { /** 上周期开始与结束时间 */ private String lastIntervalStart; private String lastIntervalEnd; /** 本周期开始与结束时间 */ private String intervalStart; private String intervalEnd; public String lastIntervalStart() { return lastIntervalStart; } public String lastIntervalEnd() { return lastIntervalEnd; } public String intervalStart() { return intervalStart; } public String intervalEnd() { return intervalEnd; } /** * 周期计算 * * @return this */ protected abstract Chrono computeInterval(); /** * 周期计算 * * @param benchmark 指定基准时间 * @return this */ protected abstract Chrono computeInterval(Temporal benchmark); /** * 计算 * * @param benchmark 指定基准时间 * @param dateTimeType 计算日期类型 */ protected void compute(Temporal benchmark, DateTimeType dateTimeType) { LocalDate date; LocalDate last; switch (dateTimeType) { case YEAR: date = convert2LocalDate(benchmark); this.intervalStart = date.with(TemporalAdjusters.firstDayOfYear()).toString(); this.intervalEnd = date.with(TemporalAdjusters.firstDayOfNextYear()).toString(); last = date.minus(1, ChronoUnit.YEARS); this.lastIntervalStart = last.with(TemporalAdjusters.firstDayOfYear()).toString(); this.lastIntervalEnd = this.intervalStart; break; case QUARTER: date = convert2LocalDate(benchmark); // 当前季度第一个月第一天 Month qMonth = date.getMonth().firstMonthOfQuarter(); date = LocalDate.of(date.getYear(), qMonth, 1); // 下季度第一天 LocalDate nextQ = date.plusMonths(3L); // 上季度第一天 LocalDate lastQ = date.minusMonths(3L); this.intervalStart = date.toString(); this.intervalEnd = nextQ.toString(); this.lastIntervalStart = lastQ.toString(); this.lastIntervalEnd = this.intervalStart; break; case MONTH: date = convert2LocalDate(benchmark); // 本周期 this.intervalStart = date.with(TemporalAdjusters.firstDayOfMonth()).toString(); this.intervalEnd = date.with(TemporalAdjusters.firstDayOfNextMonth()).toString(); // 上周期 last = date.minusMonths(1L); this.lastIntervalStart = last.with(TemporalAdjusters.firstDayOfMonth()).toString(); this.lastIntervalEnd = this.intervalStart; break; case WEEK: date = convert2LocalDate(benchmark); TemporalField dayOfWeekField = WeekFields.of(DayOfWeek.MONDAY, 1).dayOfWeek(); // 本周 this.intervalStart = date.with(dayOfWeekField, 1).toString(); this.intervalEnd = date.plusWeeks(1L).with(dayOfWeekField, 1).toString(); // 上周 this.lastIntervalStart = date.minusWeeks(1L).with(dayOfWeekField, 1).toString(); this.lastIntervalEnd = this.intervalStart; break; case DAY: date = convert2LocalDate(benchmark); // 当前天 this.intervalStart = date.toString(); this.intervalEnd = date.plusDays(1L).toString(); // 上一天 this.lastIntervalStart = date.minusDays(1L).toString(); this.lastIntervalEnd = this.intervalStart; break; default: throw new UnsupportedOperationException("日期类型错误"); } } private static LocalDate convert2LocalDate(Temporal benchmark) { if (benchmark instanceof LocalDate) { return (LocalDate) benchmark; } else if (benchmark instanceof LocalDateTime) { LocalDateTime dateTime = (LocalDateTime) benchmark; return LocalDate.of(dateTime.getYear(), dateTime.getMonth(), dateTime.getDayOfMonth()); } else { throw new UnsupportedOperationException("参数 java.time.temporal.Temporal " + "只支持 java.time.LocalDate 以及 java.time.LocalDateTime"); } } }}
public static Map<String, Object> calculateTimePeriod(String format, String begTime, String endTime) { Map<String, Object> map = new HashMap<>(); try { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); LocalDate begDate = LocalDate.parse(begTime, formatter); LocalDate endDate = LocalDate.parse(endTime, formatter); int begDay = begDate.getDayOfMonth(); int endYear = endDate.getYear(); int endMonth = endDate.getMonthValue(); int endDay = endDate.getDayOfMonth(); LocalDate compareDate = LocalDate.of(endYear, endDay < begDay ? endMonth - 1 : endMonth, begDay); long y = ChronoUnit.YEARS.between(begDate, compareDate); long m = ChronoUnit.MONTHS.between(begDate, compareDate) % 12; long d = ChronoUnit.DAYS.between(compareDate, endDate); map.put("y", y); map.put("m", m); map.put("d", d); map.put("desc", y + "年" + m + "月" + d + "日"); } catch (Exception e) { e.printStackTrace(); } return map; }