<

Advanced Batch File Programming: YESTERDAY.BAT

Published on
23,177 Points
17,177 Views
Last Modified:
Approved
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
Author:Paul Tomasi
Ask questions about what you read
If you have a question about something within an article, you can receive help directly from the article author. Experts Exchange article authors are available to answer questions and further the discussion.
Get 7 days free