如何编写适配DST变更、支持夏令时规则的通用CRON表达式
可行实现方案
前提说明
标准Linux原生cron不支持直接配置动态日期范围规则,以下分两种常用场景给出可落地的方案,所有方案默认将调度时区设置为America/New_York,自动适配EST/EDT切换,无需维护两套独立调度计划。
方案1:适用于支持高级CRON的调度框架(Quartz、Spring Scheduler等)
通过多条CRON规则组合实现需求,所有规则时区统一设为America/New_York:
- 4月-10月全月每日18点触发:
0 0 18 * 4-10 ? - 3月仅第二个周日及之后每日18点触发,拆分为两条规则:
- 3月第二个周日当天触发:
0 0 18 ? 3 SUN#2 - 3月15日-31日每日18点触发:
0 0 18 15-31 3 ?
- 3月第二个周日当天触发:
- 11月仅第一个周日之前的日期触发:
0 0 18 1-6 11 ?
逻辑验证:3月第二个周日最晚为3月14日,因此15日之后的所有3月日期都符合范围;11月第一个周日最早为11月1日,最晚为11月7日,因此11月1-6日都符合范围,10月31日天然归属于4-10月的规则覆盖。
方案2:适用于Linux原生cron场景
通过「cron定时触发+脚本前置校验」的方式实现,步骤如下:
- 配置cron规则,每天18点触发执行脚本,时区设置为
America/New_York:
0 18 * * * /path/to/your/script.sh
- 在你的业务脚本最开头加入以下判断逻辑,不符合时间范围直接退出:
# 获取当前日期的月份、当天日期 current_month=$(date +%m) current_day=$(date +%d) current_day=$((10#$current_day)) # 12-2月直接退出 if [ $((10#$current_month)) -ge 12 ] || [ $((10#$current_month)) -le 2 ]; then exit 0 fi # 3月判断:是否已过第二个周日 if [ "$current_month" = "03" ]; then # 计算当年3月第二个周日的日期 first_day_week=$(date -d "$(date +%Y)-03-01" +%w) first_sun_offset=$(( (7 - 10#$first_day_week) % 7 )) second_sun=$(( first_sun_offset + 8 )) if [ $current_day -lt $second_sun ]; then exit 0 fi fi # 11月判断:是否早于第一个周日 if [ "$current_month" = "11" ]; then # 计算当年11月第一个周日的日期 first_day_week=$(date -d "$(date +%Y)-11-01" +%w) first_sun=$(( 10#$first_day_week == 0 ? 1 : 7 - 10#$first_day_week + 1 )) if [ $current_day -ge $first_sun ]; then exit 0 fi fi # 下方写入实际业务执行逻辑
内容的提问来源于stack exchange,提问作者Abhinav
相关产品推荐
相关产品推荐

