求Shell脚本逻辑:实现指定起止日期内的分段日期循环生成
Shell Script to Generate Monthly Date Ranges (22nd to Next Month's 21st)
我来帮你实现这个需求,下面是一个基于bash的脚本,它会完全按照你描述的规则——每个周期从当月22号到下月21号——生成日期范围,直到最后一个周期的结束日期不超过你指定的结束日期为止。
完整脚本
#!/bin/bash # 配置你的起始和结束日期(支持yyyyMMdd或yyyy-mm-dd格式) INPUT_START="20140101" INPUT_END="20160130" # 第一步:将输入日期统一转换为标准的yyyy-mm-dd格式,方便后续处理 startdate=$(date -d "$INPUT_START" +%Y-%m-%d 2>/dev/null || { echo "错误:起始日期格式无效,请检查输入"; exit 1; }) enddate=$(date -d "$INPUT_END" +%Y-%m-%d 2>/dev/null || { echo "错误:结束日期格式无效,请检查输入"; exit 1; }) # 第二步:确定第一个周期的起始日期(找到第一个不早于startdate的当月22号) start_year=$(date -d "$startdate" +%Y) start_month=$(date -d "$startdate" +%m) curr_start_candidate="${start_year}-${start_month}-22" # 如果当月22号早于指定的起始日期,就自动跳转到下月22号 if [[ "$curr_start_candidate" < "$startdate" ]]; then curr_start=$(date -d "$curr_start_candidate +1 month" +%Y-%m-%d) else curr_start="$curr_start_candidate" fi # 第三步:循环生成所有符合要求的日期范围 while true; do # 计算当前周期的结束日期:起始日期加1个月再减1天,正好是下月21号 curr_end=$(date -d "$curr_start +1 month -1 day" +%Y-%m-%d) # 检查当前周期的结束日期是否超出指定的结束日期,若是则退出循环 if [[ "$curr_end" > "$enddate" ]]; then break fi # 输出当前周期的起止日期(转换为你需要的yyyyMMdd格式) echo "startDate_new=$(date -d "$curr_start" +%Y%m%d)、endDate_new=$(date -d "$curr_end" +%Y%m%d)" # 更新下一个周期的起始日期为当前周期结束日期的次日(即下月22号) curr_start=$(date -d "$curr_end +1 day" +%Y-%m-%d) done
脚本逻辑说明
- 日期格式兼容:脚本支持两种输入格式(
yyyyMMdd如20140101或yyyy-mm-dd如2014-01-01),会自动转换为标准格式进行处理,避免格式错误。 - 初始周期定位:自动找到第一个不早于你指定起始日期的当月22号,确保生成的第一个周期符合你的时间范围要求。
- 周期计算规则:
- 每个周期的结束日期通过
+1 month -1 day计算,精准得到下月21号(比如2014-01-22的结束日期是2014-02-21)。 - 每次循环后自动更新下一个周期的起始日期为当前周期结束日的次日,也就是下月22号,完美匹配你的循环规则。
- 每个周期的结束日期通过
- 边界控制:当计算出的周期结束日期超过你指定的结束日期时,脚本会自动终止循环,不会生成超出范围的无效周期。
测试示例
当你设置INPUT_START="20140101"和INPUT_END="20160130"时,脚本会输出:
startDate_new=20140122、endDate_new=20140221 startDate_new=20140222、endDate_new=20140321 ... startDate_new=20151222、endDate_new=20160121
下一个周期的结束日期是20160221,超过了20160130,所以脚本自动退出,完全符合你的需求。
兼容macOS(可选)
如果你在macOS上运行脚本,因为macOS自带的date命令是BSD版本,语法和GNU date不同,你可以先通过Homebrew安装GNU date:
brew install coreutils
然后将脚本中的date替换为gdate即可正常运行。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

