当前位置: 首页 > ds >正文

根据指定日期和cron表达式生成下一周期的执行时间

文章目录

  • 前言
  • 一、日期计算单元类UtilityClass
  • 二、时间维度Enum类
  • 三、测试类


前言

根据指定日期和cron表达式生成下一周期的执行时间


一、日期计算单元类UtilityClass

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Preconditions;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.support.CronExpression;
import java.time.LocalDateTime;
import java.util.Date;/*** 日期计算*/
@UtilityClass
public class WoDateUtil {/*** 根据 {@code periodUnit+value} 计算下次日期* <li>单位是fixed_date:存储的是JSON array字符串,日期格式:yyyy-MM-dd,最多支持30个日期,如:["2025-05-20", "2025-06-03"] 日期和月份必须是2位</li>* <li>单位是weekly:存储的是0-6, 0代表周日</li>* <li>单位是monthly:存储的是01-31,必须是2位</li>* <li>单位是yearly:存储的是MM-dd,如: 05-20 日期和月份必须是2位</li>* @param periodUnit 周期单位* @param value 周期值* @param currentDate 当前日期 如果null则默认当前系统日期* @return 返回计算结果下次日期 格式:yyyy-MM-dd。注意:<br>*         <li>1. 返回的可能是currentDate,比如:每周四,currentDate恰好是周四</li>*         <li>2. 如果是fixed_date可能返回null</li>*/public String nextDate(PeriodUnitEnum periodUnit, String value, Date currentDate) {Preconditions.checkNotNull(periodUnit);Preconditions.checkNotNull(value);if (periodUnit == PeriodUnitEnum.UNKNOWN) {throw new QuantdoServiceException(-1, "PeriodUnitEnum.UNKNOWN无法计算");}String format = "yyyy-MM-dd";DateTime current = currentDate != null ? DateUtil.date(currentDate) : DateUtil.date();current.setMutable(false);DateTime next = null;switch (periodUnit) {case WEEKLY:case MONTHLY:case YEARLY:next = next(periodUnit, current, value);break;case FIXED_DATE:next = JSON.parseArray(value, String.class).stream().distinct().sorted().map(x -> DateUtil.parse(x, format)).filter(x -> DateUtil.compare(x, current, format) >= 0).findFirst().orElse(null);break;}return next != null ? next.toString(format) : null;}private DateTime next(PeriodUnitEnum unit, DateTime start, String value) {// cron设置的时间点为: 23:59:59 ,为了保证计算结果//包含当天需要强制将锚点start时间点设置为00:00:00。// nextDate是否包含当天选择权因由上层调用者抉择。start = DateUtil.beginOfDay(start);String cron;if (unit == PeriodUnitEnum.YEARLY) {String[] arr = StringUtils.split(value, "-");cron = StrUtil.format(unit.getCron(), Integer.parseInt(arr[1]), Integer.parseInt(arr[0]));} else {cron = StrUtil.format(unit.getCron(), Integer.parseInt(value));}LocalDateTime next = CronExpression.parse(cron).next(start.toLocalDateTime());return new DateTime(next);}
}

二、时间维度Enum类

import lombok.Getter;
import lombok.RequiredArgsConstructor;/*** 订单按时创建任务创建周期单位。* cron设置的时间点为: 23:59:59 ,为了保证计算结果包含当天。*/
@RequiredArgsConstructor
@Getter
public enum PeriodUnitEnum {WEEKLY("weekly", "每周", "59 59 23 ? * {}"),//周天至周6,0-6,如每周2 23:59:59为59 59 23 ? * 2MONTHLY("monthly", "每月", "59 59 23 {} * ?"),//如每月15号 23:59:59为59 59 23 15 * ?YEARLY("yearly", "每年", "59 59 23 {} {} ?"),//如每年1月15号 23:59:59为59 59 23 15 1 ?FIXED_DATE("fixed_date", "固定日期", ""),UNKNOWN("unknown", "未知", "");private final String code;private final String title;private final String cron;public static PeriodUnitEnum getByCode(String code) {for (PeriodUnitEnum anEnum : PeriodUnitEnum.values()) {if (anEnum.getCode().equalsIgnoreCase(code)) {return anEnum;}}return UNKNOWN;}
}

三、测试类

public static void main(String[] args) {// 日期必须要+1,因为WoDateUtil.nextDate可能会返回当天DateTime offset = DateUtil.date().offset(DateField.DAY_OF_YEAR, 1);//当前是2025年6月4号String nextYearlyExecuteDate = WoDateUtil.nextDate(PeriodUnitEnum.getByCode("yearly"), "06-02", offset);//每年6月2号String nextMonthlyExecuteDate = WoDateUtil.nextDate(PeriodUnitEnum.getByCode("monthly"), "02", offset);//每月2号String nextWeeklyExecuteDate = WoDateUtil.nextDate(PeriodUnitEnum.getByCode("weekly"), "2", offset);//每周2System.out.println(JSON.toJSONString(nextYearlyExecuteDate));System.out.println(JSON.toJSONString(nextMonthlyExecuteDate));System.out.println(JSON.toJSONString(nextWeeklyExecuteDate));DateTime dataTime = DateUtil.parse("2025-06-04","yyyy-MM-dd").offset(DateField.DAY_OF_YEAR, 1);String nextYearlyExecuteDate2 = WoDateUtil.nextDate(PeriodUnitEnum.getByCode("yearly"), "06-15", dataTime);//每年6月15号String nextMonthlyExecuteDate3 = WoDateUtil.nextDate(PeriodUnitEnum.getByCode("monthly"), "15", dataTime);//每月15号String nextWeeklyExecuteDate4 = WoDateUtil.nextDate(PeriodUnitEnum.getByCode("weekly"), "2", dataTime);//每周2System.out.println(JSON.toJSONString(nextYearlyExecuteDate2));System.out.println(JSON.toJSONString(nextMonthlyExecuteDate3));System.out.println(JSON.toJSONString(nextWeeklyExecuteDate4));
}
输出:
"2026-06-02"
"2025-07-02"
"2025-06-10"
"2025-06-15"
"2025-06-15"
"2025-06-10"

Cron在线工具

http://www.xdnf.cn/news/12446.html

相关文章:

  • C++类二
  • 吞咽与营养并重:进行性核上性麻痹患者的饮食管理方案
  • 龙虎榜——20250605
  • ubuntu安装NVIDIA驱动没有网络
  • 【GESP真题解析】第 12 集 GESP 三级 2024 年 6 月编程题 1:移位
  • Spring Cloud 2025 正式发布,你的灾难要来了
  • 系统思考持续训练
  • 前端面试题之浏览器存储技术Cookie、LocalStorage、SessionStorage、indexDB
  • FEMFAT许可管理软件推荐
  • js 比较两个对象的值,不相等就push对象的key
  • 图像去雾数据集总汇
  • Python基于方差-协方差方法实现投资组合风险管理的VaR与ES模型项目实战
  • Qt/C++学习系列之QButtonGroup的简单使用
  • w10激活方法
  • Linux免杀方案汇总(C语言)
  • 【cmder】--- Windows 下 cmder 经典常用快捷键 显著提高效率
  • 第十三节:第四部分:集合框架:HashMap、LinkedHashMap、TreeMap
  • 是否存在路径(FIFOBB算法)
  • JupyterNotebook全能指南:从入门到精通
  • LangchainRAG you need - 段落拆分
  • Setting搜索 ===》了解是如何初始搜索索引以及去掉控件搜索
  • exp1_code
  • 腾讯云服务器端口怎么全部打开?CVM和轻量端口开通教程
  • 【杂谈】-吉卜力化(Ghiblified ) AI 图像:艺术与隐私的交织
  • 06.最长连续序列
  • 我的创作纪念日——聊聊我想成为一个创作者的动机
  • 总结这几个月来我和AI一起开发并上线第一个应用的使用经验
  • 数据融合是什么?进行数据融合的4大关键环节!
  • 前端面试准备-7
  • 从 Stdio 到 HTTP SSE,在 APIPark 托管 MCP Server