3

How can I subtract 1 day from this cmd code:

%date:~10,4%%date:~4,2%%date:~7,2%

Every post I see here says I need to use power shell and etc. I just would like to remove 1 day from here.

The cmd returns this:

20180227

And I would like to:

20180226
Racer SQL
  • 207
  • 1
  • 3
  • 14
  • 1
    Possible duplicate of [Date arithmetic in cmd scripting](https://stackoverflow.com/questions/355425/date-arithmetic-in-cmd-scripting) – phuclv Feb 27 '18 at 15:04
  • 1
    so many duplicates https://stackoverflow.com/q/11891335/995714 https://stackoverflow.com/q/19980034/995714 https://stackoverflow.com/q/24177864/995714 https://stackoverflow.com/q/2954359/995714 ... – phuclv Feb 27 '18 at 15:06
  • I have personally probably answered this question a half dozen times on SO. And my answers are probably pure bactch. Although it is much easier to use `powershell` within the batch file. – Squashman Feb 27 '18 at 15:40

2 Answers2

6

I don't know about coding but this work for me:

set YY=%date:~10,4%
set MM=%date:~4,2%
set DD=%date:~7,2%
set /a DD1= %DD% - 1
echo %YY%%MM%%DD1%
Dominique
  • 16,450
  • 15
  • 56
  • 112
Adie Oxide
  • 61
  • 2
  • 2
1

Here is two code options. I am using functions in both to get the current date and time. If you don't need that you can remove that.

This is the fastest of the two options. It converts the date to a Julian date to do the math, then converts it back to a normal date.

@echo off
setlocal

REM Get the current date
REM Will return variables YY, YYYY, MM, DD, HH, Min and Sec
Call :GetDateTime

REM Add or Subtract from the current date
REM Must use + or - symbol
REM Revised date will be assigned to RetVar
REM LeapDay
Call :AddSubDate 2016 03 01 -1 LeapDay
REM Yesterday
Call :AddSubDate %YYYY% %MM% %DD% -2 past
REM Tomorrow
Call :AddSubDate %YYYY% %MM% %DD% +2 future

echo LeapDay  : %LeapDay%
echo Past     : %past%
echo Today    : %YYYY%%MM%%DD%
echo Future   : %future%
pause
GOTO :EOF

:AddSubDate Year Month Day <+/-Days> RetVar
setlocal & set a=%4
set "yy=%~1"&set "mm=%~2"&set "dd=%~3"
set /a "yy=10000%yy% %%10000,mm=100%mm% %% 100,dd=100%dd% %% 100"
if %yy% LSS 100 set /a yy+=2000 &rem Adds 2000 to two digit years
set /a JD=dd-32075+1461*(yy+4800+(mm-14)/12)/4+367*(mm-2-(mm-14)/12*12)/12-3*((yy+4900+(mm-14)/12)/100)/4
if %a:~0,1% equ + (set /a JD=%JD%+%a:~1%) else set /a JD=%JD%-%a:~1%
set /a L= %JD%+68569,     N= 4*L/146097, L= L-(146097*N+3)/4, I= 4000*(L+1)/1461001
set /a L= L-1461*I/4+31, J= 80*L/2447,  K= L-2447*J/80,      L= J/11
set /a J= J+2-12*L,      I= 100*(N-49)+I+L
set /a YYYY= I, MM=100+J, DD=100+K
set MM=%MM:~-2% & set DD=%DD:~-2%
set ret=%YYYY: =%%MM: =%%DD: =%
endlocal & set %~5=%ret%
exit /b

:GetDateTime Year Month Day Hour Minute Second
@echo off & setlocal
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%"
( ENDLOCAL
   set "YY=%YY%" 
   set "YYYY=%YYYY%" 
   set "MM=%MM%" 
   set "DD=%DD%"
   set "HH=%HH%" 
   set "Min=%Min%"
   set "Sec=%Sec%"
)
exit /b

The second option uses a trick with the xcopy command to check if the date is a valid date. So it is technically not doing any date math like the previous solution which is converting to the Julian date to do that date math. This option only does subtraction. The first option can add or subtract.

@echo off
setlocal

REM set the number of days to substract
SET DAYS=180

REM Call function to check if the date is valid.
CALL :validdate "%days%" subdate
echo Old date: %subdate%

pause

endlocal
GOTO :EOF

:validdate
setlocal
set "day=%~1"
set rand=%random%
md "%temp%\dummy%rand%\empty%rand%"

REM Get todays date
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"

REM set year month and day into its own variables.
set /a y=%dt:~0,4%
set /a m=1%dt:~4,2%
set /a d=1%dt:~6,2%

:loop
if "%day%"=="0" (
    rd /s /q "%temp%\dummy%rand%"
    endlocal &set "%~2=%y%%m:~-2%%d:~-2%"
    GOTO :EOF
)
set /a d-=1

if %d% lss 101 (
    set d=131
    set /a m-=1

    if %m% lss 101 (
        set m=112
        set /a y-=1
    )
)

xcopy /d:%m:~-2%-%d:~-2%-%y% /t "%temp%\dummy%rand%\empty%rand%" "%temp%\dummy%rand%" >nul 2>&1 && (set /a day-=1 & goto loop) || goto loop

GOTO :EOF
Squashman
  • 13,649
  • 5
  • 27
  • 36