如何生成连续的日期? (添加 N 天到现在)

How to generate succesive dates? (add N days to date)

我正在编写一个简单的批处理脚本,允许用户输入开始日期和结束日期,然后它会传输名称中包含日期的文件。它需要像“20220215”这样的年月日。例如,用户输入“20211110”,然后输入“20211215”,它会抓取从 2021 年 11 月 11 日到 2021 年 12 月 15 日的文件。我试图从输入字符串中抓取日期和月份,但问题是值“08” ' 和 '09' 会因为十六进制值等原因给脚本带来麻烦。所以我为文件日做案例,因为它在字符串的末尾,所以工作正常。问题是月份。这是代码:

REM Works fine
IF !temp_var:~6! == 08 (
    SET /A file_day = 8
) ELSE IF !temp_var:~6! == 09 (
    SET /A file_day = 9
) ELSE (
    SET /A file_day = !temp_var:~6!
)

REM Crashes script
IF !temp_var:~4, -2! == 08 (
    SET /A file_month = 8
) ELSE IF !temp_var:~4, -2! == 09 (
    SET /A file_month = 9
) ELSE (
    SET /A file_month = !temp_var:~4, -2!

我在 运行 脚本时收到的错误是

-2 was unexpected at this time.

我发现它只是在月份块的第一个 IF 语句中。但是每次我搜索如何从变量中获取数字时,它都使用 %var:~#:#% 格式。

我已经考虑切换到另一种语言或方法来执行此操作,但我认为我尝试自动化的任务很简单,可以通过将批处理 运行 几个命令哈哈来实现。

感谢您的帮助!

此程序生成一系列连续日期:

@echo off
setlocal

echo      Date format: YYYYMMDD
set /P "startDate=Enter start date: "
set /P "endDate=Enter end date:   "
echo/
echo %startDate%

set /A "YYYY=%startDate:~0,4%, m=1%startDate:~4,2%-100, d=1%startDate:~6%-100"
:nextDate
set /A "d+=1, nextMon=!(d-(31+((m+m/8)&1)-!(m-2)*(2-!(YYYY%%4)))), d=d*!nextMon+nextMon, m+=nextMon, nextYear=!(m-13), m=m*!nextYear+nextYear, YYYY+=nextYear, MM=100+m, DD=100+d"
set "nextDate=%YYYY%%MM:~1%%DD:~1%
echo %nextDate%
if %nextDate% neq %endDate% goto nextDate

这是对所用方法的描述:

  • d+=1是第二天。
  • 30+((m+m/8)&1)-!(m-2)*(2-!(YYYY%%4)) 是每个月对应的天数:

1=31、2=28 或 29、3=31、4=30、5=31、6=30、7=31、8=31、9=30、10=31、11=30和 12=31.

也就是说,从 1 到 7 的奇数月份获得 30 + 1(否则为 30+0),并在 7 之后的偶数月份切换为 30 + 1(否则为 30+0),并额外调整( 2 月份的结果为 -2 或 -1)。为了得到这样的结果,我们使用了这些部分:

(m+m/8) 对于 M<8 是 M,否则是 M+1。 ((m+m/8)&1) 是我们在月 <> 2 中添加到 30 的 1 或 0。

(m-2) 对于 M==2 为 0,否则为 <>0,因此 !(m-2) 对于 M==2 为 1,否则为 0,而 !(m-2)*2 是我们的 2当 M==2 时,30 减去 28。当年份可以被 4 整除时 YYYY%%4 为 0,否则为 <>0,因此当年份为闰年时 !(YYYY%%4) 是对 1 的调整(我们从得出 28 的 2 开始调整)(所以在闰年二月给出 29).

最后,我们 assemble 所有这些部分并得到: 30+((m+m/8)&1)-!(m-2)*(2-!(YYYY%%4)) 这是所有月份和所有年份的每月天数。将 30 更改为 31 给出 DaysPerMonthPlusOne 的数量。

技术提示:此公式不符合被 400 整除的年份 不是 闰年的规则(如 2000),因此该方法将失败在2400年。为了修正这一点,我们需要在年份被400整除时取消调整1,即:31+((m+m/8)&1)-!(m-2)*(2-!(YYYY%%4)+!(YYYY%%400))

  • d-(DaysPerMonthPlusOne)当第二天超过当月的天数时为0,所以nextMon=!(d-(DaysPerMonthPlusOne))当月份改变时为1,否则为0。

  • d=d*!nextMon+nextMon 当月份没有变化时是相同的 D 值,否则为 1(nextMon 的值)。

  • m+=nextMon 当月份改变时递增 M。

  • m-13 当 M 超过年份时为 0,所以当年份改变时 nextYear=!(m-13) 为 1(否则为 0)。

  • m=m*!nextYear+nextYear 年份不变时为相同的 M 值,否则为 1(下一年的值)。

  • YYYY+=nextYear 当年份改变时递增 YYYY。

  • 最后MM=100+m, DD=100+d是3位数的变量(如m为3时的103),分别用两位数表示月份和日期。

参考:这个方法是我自己开发的...;)

EDIT 2022/03/23添加几天的修改

我修改了这个程序以增加几天(超过一天)。只要天数的增量不跳到超过一个月,该方法就可以正常工作。尽管可以很容易地修改该方法以适用于任意天数,但无法在单个算术表达式中实现修改...

@echo off
setlocal

echo      Date format: YYYYMMDD
set /P "startDate=Enter start date: "
set /P "endDate=Enter end date:   "
set /P "numDays=Enter days increment: "
echo/
echo %startDate%

set /A "YYYY=%startDate:~0,4%, m=1%startDate:~4,2%-100, d=1%startDate:~6%-100"
:nextDate
set /A "d+=numDays, DPM=30+((m+m/8)&1)-!(m-2)*(2-!(YYYY%%4)), nextMon=((d-1-DPM)>>31)+1, d-=nextMon*DPM, m+=nextMon, nextYear=!(m-13), m=m*!nextYear+nextYear, YYYY+=nextYear, MM=100+m, DD=100+d"
set "nextDate=%YYYY%%MM:~1%%DD:~1%
echo %nextDate%
if %nextDate% lss %endDate% goto nextDate

这些是新方法中更改的详细信息:

  • (d-1-DPM) 当日期小于或等于 DaysPerMonth 时为 负数 否则为 0 或正数,因此 ((d-1-DPM)>>31) (这样的结果右移 31 位)当日期在同一月份时为 -1,否则为 0,因此 nextMon=((d-1-DPM)>>31)+1 当月份发生变化时为 1,否则为 0。

  • d-=nextMon*DPM当某天属于下个月时减去当月的天数