People often ask how to calculate the date N days ago. Because this involves the issues of big months and small months, common years and leap years, the code becomes relatively complicated and tends to scare people off.
Although willsort posted code like this two years ago (please refer to: (Ended) Deleting files older than N days from the DOS command line under WINDOWS), and although the idea is extremely simple—convert the date into a relative number, do the subtraction, then convert the relative number back into a date—the numbers 2472632 and 146097 and the like appear too abruptly, making it hard to figure out what's going on. To be honest, limited by my own level, even now I still find it very confusing.
Now I'm posting three batch files for getting the date N days ago ( the date may include the weekday, but it must be arranged in year-month-day order, and the year must be four digits, otherwise there will be errors). The key parts all have comments, so they're a bit easier to understand than willsort's:
Code 1:
Code 2:
Code 3:
[ Last edited by namejm on 2007-6-8 at 11:15 PM ]
Although willsort posted code like this two years ago (please refer to: (Ended) Deleting files older than N days from the DOS command line under WINDOWS), and although the idea is extremely simple—convert the date into a relative number, do the subtraction, then convert the relative number back into a date—the numbers 2472632 and 146097 and the like appear too abruptly, making it hard to figure out what's going on. To be honest, limited by my own level, even now I still find it very confusing.
Now I'm posting three batch files for getting the date N days ago ( the date may include the weekday, but it must be arranged in year-month-day order, and the year must be four digits, otherwise there will be errors). The key parts all have comments, so they're a bit easier to understand than willsort's:
Code 1:
@echo off
:: Get the date N days ago
:: Idea:
:: Simulate manual calculation: subtract the number of days from the date number;
:: when the difference is negative, borrow 1 from the higher place value.
:: Features:
:: The code is concise and easy to understand; speed depends on the size of the specified number of days
setlocal enabledelayedexpansion
:Main
cls
:: The date may include the weekday, but it must be arranged in year-month-day order
:: The year must be four digits, otherwise there will be errors
set day=%date%
set days=0
echo.&echo.
echo The specified date is: %day%
echo.
set /p input= Please specify how many days to trace back:
:: Extract the date
for /f "tokens=1-3 delims=-/. " %%i in ("%day%") do (
set /a sy=%%i, sm=100%%j %% 100, sd=100%%k %% 100
)
set /a sd-=input
if %sd% leq 0 call :count
cls
echo.&echo.
echo The specified date is: %day%
echo.
set sm=0%sm%
set sd=0%sd%
echo The date %input% days ago is: %sy%-%sm:~-2%-%sd:~-2%
pause>nul
goto Main
:count
set /a sm-=1
if !sm! equ 0 set /a sm=12, sy-=1
call :days
set /a sd+=days
if %sd% leq 0 goto count
goto :eof
:days
:: Get the total number of days in the specified month
set /a leap="^!(sy %% 4) & ^!(^!(sy %% 100)) | ^!(sy %% 400)"
set /a max=28+leap
set num=0
set str=31 %max% 31 30 31 30 31 31 30 31 30 31
for %%i in (%str%) do (
set /a num+=1
if %sm% equ !num! set days=%%i&goto :eof
)
goto :eofCode 2:
@echo off
:: Get the date N days ago
:: Idea:
:: Convert the current date into a day count
:: Subtract N days from the current day count
:: Then convert the result back into a date
:: Specific operation:
:: Calculate the day count year by year
:: Features:
:: The code is concise and easy to understand; relatively slow, but not affected by the size of the specified number of days
setlocal enabledelayedexpansion
:Main
cls
:: The date may include the weekday, but it must be arranged in year-month-day order
:: The year must be four digits, otherwise there will be errors
set day=%date%
set days=0
echo.&echo.
echo The specified date is: %day%
echo.
set /p input= Please specify how many days to trace back:
rem ========Convert the specified date into a day count========
:: Extract the date
for /f "tokens=1-3 delims=-/. " %%i in ("%day%") do (
set /a sy=%%i, sm=100%%j %% 100, sd=100%%k %% 100
)
:: Convert the year into a day count
for /l %%i in (1,1,%sy%) do (
set /a leap="^!(%%i %% 4) & ^!(^!(%%i %% 100)) | ^!(%%i %% 400)"
set /a days=days+365+leap
)
:: Convert the month into a day count
set /a num=0, mday=0, max=28+leap
set str=0 31 %max% 31 30 31 30 31 31 30 31 30
for %%i in (%str%) do (
set /a num+=1
if !num! leq !sm! set /a mday+=%%i
)
set /a days=days+mday+sd
set /a days-=input
rem ========Convert the day count into a date========
:: Get the year
for /l %%i in (1,1,%sy%) do (
set /a leap="^!(%%i %% 4) & ^!(^!(%%i %% 100)) | ^!(%%i %% 400)"
set /a days_tmp=365+leap
if !days! gtr !days_tmp! (
set /a days-=days_tmp
set y=%%i
)
)
:: Get the month and date
set /a m=1, max=28+%leap%
set str=31 %max% 31 30 31 30 31 31 30 31 30
for %%i in (%str%) do (
if !days! gtr %%i (
set /a days-=%%i
set /a m+=1
) else goto next
)
:next
set m=0%m%
set d=0%days%
cls
echo.&echo.
echo The specified date is: %day%
echo.
echo The date %input% days ago is: %y%-%m:~-2%-%d:~-2%
pause>nul
goto MainCode 3:
@echo off
:: Get the date N days ago
:: Idea:
:: Convert the current date into a day count
:: Subtract N days from the current day count
:: Then convert the result back into a date
:: Specific operation:
: First calculate using 365 days per year, then calculate the number of leap years
:: Finally do the conversion
:: Features:
:: The code is complicated and not easy to understand, but very fast
:: There is still a bug in the calculation; you can use 11111 to compare and test against the first two. I don't have time to update it for now
setlocal enabledelayedexpansion
:Main
cls
:: The date may include the weekday, but it must be arranged in year-month-day order
:: The year must be four digits, otherwise there will be errors
set day=2007-01-02
set /a days=0, sum=0
echo.&echo.
echo The specified date is: %day%
echo.
set /p input= Please specify how many days to trace back:
rem =======Convert the date into a day count=======
:: Extract the date
for /f "tokens=1-3 delims=/-. " %%i in ("%day%") do (
set /a sy=%%i, sm=100%%j %% 100, sd=100%%k %% 100, y=%%i
)
:: Convert the year into a day count
set num=0
if %sy% lss 400 goto next1
call :leap_num
:next1
set /a leap_num=sy/4-num
:: Convert the month into a day count
set /a leap="^!(sy %% 4) & ^!(^!(sy %% 100)) | ^!(sy %% 400)"
set /a max=28+leap
set num=0
set str=31 %max% 31 30 31 30 31 31 30 31 30 31
for %%i in (%str%) do (
set /a num+=1
if !num! lss %sm% set /a sum+=%%i
)
set /a days=365*sy+leap_num+sum+sd
set /a days-=input
rem =======Convert the day count into a date=======
:: Get the year
set /a y=days/365
set /a mod1=days %% 365
call :leap_num
set /a mod2=mod1-leap_num
:loop2
if %mod2% lss 0 (
set /a y-=1
set /a mod2=365+mod2
) else goto next2
goto loop2
:: Get the month and date
:next2
set /a m=1, days=mod2+1, max=28+%leap%
set str=31 %max% 31 30 31 30 31 31 30 31 30
for %%i in (%str%) do (
if !days! gtr %%i (
set /a days-=%%i
set /a m+=1
) else goto next3
)
:next3
set m=0%m%
set d=0%days%
cls
echo.&echo.
echo The specified date is: %day%
echo.
echo The date %input% days ago is: %y%-%m:~-2%-%d:~-2%
pause>nul
goto Main
:leap_num
:: Count the years divisible by 100 but not by 400
set /a y_tmp=(%y:~0,1%%y%-%y%)/10
set num=0
:loop1
set /a mod=y_tmp %% 400
if %mod% neq 0 set /a num+=1
set /a y_tmp-=100
if %y_tmp% geq 100 goto loop1
set /a leap_num=y/4-num
goto :eof
[ Last edited by namejm on 2007-6-8 at 11:15 PM ]
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
考虑问题复杂化,解决问题简洁化。

DigestI