Advanced Batch File Programming: YESTERDAY.BAT

Published:
YESTERDAY

YESTERDAY.BAT is inspired by a previous article I wrote entitled: TOMORROW.BAT.

The crux of this batch file revolves around the XCOPY command - a technique I discovered while looking for an easy method for validating dates avoiding complex maths. Here's the whole thing:

::================================================
                      :: YESTERDAY.BAT
                      ::
                      :: Function to return yesterday's date
                      ::================================================
                      @echo off
                      
                      set /a d=%date:~0,2%
                      set /a m=%date:~3,2%
                      set /a y=%date:~6,4%
                      
                      :loop
                        set /a d-=1
                      
                        if %d% lss 1 (
                          set d=31
                          set /a m-=1
                      
                          if %m% lss 1 (
                            set m=12
                            set /a y-=1
                          )
                        )
                      xcopy /d:%m%-%d%-%y% /l . .. >nul 2>&1 || goto loop
                      
                      echo %d%/%m%/%y%

Open in new window


INPUT
The code receives input from the system's %DATE% whose format is DD/MM/YYYY.

set /a d=%date:~0,2%
                      set /a m=%date:~3,2%
                      set /a y=%date:~6,4%

Open in new window

If your system's date format differs from DD/MM/YYYY then you will need to edit these three lines or provide some other method of delivering the date to the batch file in order for the rest of the code to work correctly.

You are reminded: This is an advanced topic and therefore, you are expect to know how to do that.
Use arithmetic 'SET /A' instead of 'SET' because 'SET /A' drops any leading zeros (a major problem due to the ambiguity between octal, decimal and hexadecimal '08' and '09') or spaces.


DECREMENTING DAY
'1' is deducted from the current day (day) value. If the resultant date is valid, it is returned to the user.  

For the most part, the loop will execute just once. If the current day is the first day of the month and if there are 30 days in the previous month, the loop will execute twice.  In the worst-case scenario, where the current day is March 1st and where February 28th falls on a non-leap year, the loop will execute four times.

:loop
                        set /a d-=1
                      
                        if %d% lss 1 (
                          set d=31
                          set /a m-=1
                      
                          if %m% lss 1 (
                            set m=12
                            set /a y-=1
                          )
                        )
                      xcopy /d:%m%-%d%-%y% /l . .. >nul 2>&1 || goto loop

Open in new window

In all cases, if 'd' is decremented past '1' it is reset to '31' and 'm' (month) is decremented. Likewise, if 'm' is decremented past '1' it is reset to '12' and 'y' (year) is dcremented.


VALIDATING THE DATE
For information on validating dates using the XCOPY command please see my article: Advanced Batch File Programming: Validating Dates

If the date in '/d:' is valid and resolvable, then XCOPY continues (to do 'nothing') and control is passed to the next line of code in the batch file.  If, on the other hand, the date is invalid, the '||' (logical OR operator) passes control to the GOTO instruction and the process is repeated by jumping back the beginning of the loop.


OUTPUT
It is not necessary to assign '%d%', '%m%' and '%y%' to a variable such as '%yesterday%' although you can if you wish to.

echo %d%/%m%/%y%

Open in new window

Notice the order in which D, M and Y are re-assembled - they are consistent with the input.

Also note that either D or M may consist of one or two digits. If you want to output this as DD/MM/YYYY then you will need to add any leading space or zero yourself. For example, the following should suffice:

set d= %d%
                      set m=0%m%
                      
                      echo %d:~-2%/%m~-2%/%y%

Open in new window

And that's about all you need to know.


CONSIDERATIONS
As it stands, the batch file's only output is a date in D/M/YY format (or DD/MM/YY if you have added any leading characters). This will work as a standalone batch file or as a function tacked onto the end of your own batch file and executed with a CALL statement.

As an external function, you might CALL it from within your own batch file like this:

for /f %%a in ('yesterday') do set yesterday=%%a

Open in new window

As a function added to your own code, you might call it like this:

for /f %%a in ('call :yesterday') do set yesterday=%%a

Open in new window

'%%a' is set to the date given by the function YESTERDAY.BAT, this is then assigned to the variable 'yesterday'.

Output can also be redirected or piped into another command as in the following examples:

call yesterday >file

Open in new window

call yesterday|find . . .

Open in new window

You can take input from the command line rather than DATE itself by replacing the three SET statements in the input section with something like this:

for /f "tokens=1-3 usebackq delims=/" %%a in ('%1') do (
                        set d=%%a
                        set m=%%b
                        set y=%%c
                      )

Open in new window

Note: That would make the function return "The Day Before x" rather than yesterday.


RELATED ARTICLES
Advanced Batch File Programming: TOMORROW.BAT
Advanced Batch File Programming: Validating Dates

EXTERNAL SOURCES
YESTERDAY.BAT
Validating Dates
0
19,090 Views

Comments (2)

Hello Paul,

Thanks for this great article.

When I run "Batch File as Administrator" it is working properly, however, when I normally run it by double clicking .bat file it doesn't come out of loop.

Could you please suggest ?

Looking for your further support.

Best Regards
Bhavik
Error-Cmd.JPG
Correct.JPG

Author

Commented:
Bhavik Talesra

Have you edited the batch file code?

If you intend to run this batch file by double-clicking on it then I would suggest adding a PAUSE command at the end of the batch file like this:

::================================================
:: YESTERDAY.BAT
::
:: Function to return yesterday's date
::================================================
@echo off

set /a d=%date:~0,2%
set /a m=%date:~3,2%
set /a y=%date:~6,4%

:loop
  set /a d-=1

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

    if %m% lss 1 (
      set m=12
      set /a y-=1
    )
  )
xcopy /d:%m%-%d%-%y% /l . .. >nul 2>&1 || goto loop

echo %d%/%m%/%y%

pause

Open in new window

This will pause output to your display and should work with, or without, administrative privileges.

Hope that helps.

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.