0

How do I write a batch script, that would search in Dates.txt file of this format:

EventName1 : dd.mm.yyyy

EventName2 : dd.mm.yyyy

...

EventNameN : dd.mm.yyyy

for events with tomorrow's date, and if found, notify the user about them?

I was able to write a script for today's events:

@echo off

setlocal disableDelayedExpansion

IF NOT EXIST Dates.txt GOTO not_found_dates

for /F "usebackq tokens=1,2 delims==" %%i in (`wmic os get LocalDateTime /VALUE 2^>NUL`) do if '.%%i.'=='.LocalDateTime.' set ldt=%%j
set ldt=%ldt:~6,2%.%ldt:~4,2%.%ldt:~0,4%
echo Today: %ldt%



for /f "tokens=1,2 delims=:" %%A in (Dates.txt) do (
    if "%%B"==" %ldt%" echo You have %%Atoday!
)

GOTO:EOF


:not_found_dates
echo Dates.txt not found!
GOTO:EOF

But I can't figure out how to find tomorrow's date to compare it with the dates in file.

Some help would be appreciated!

0lesya
  • 147
  • 15
  • Why do you go to such lengths to get today's date when you can use `echo %date%`? – Klitos Kyriacou May 30 '16 at 21:31
  • `echo %date%` gives different results depending on Date/Time settings. On some PCs it would give the date in **31.05.2016** format, on others it would be **31-May-2016** or **05/31/2016**. I need it to look like **31.05.2016** so that it would always correspond with date format in Dates.txt file. – 0lesya May 30 '16 at 21:37
  • There is no easy way to calculate with dates in batch. See for example [here](http://stackoverflow.com/search?q=%5Bbatch-file%5D+get+yesterdays+date) for different methods and choose what fits your needs. – Stephan May 31 '16 at 17:20

2 Answers2

4

Well, I have finally figured it myself!

@echo off

setlocal DisableDelayedExpansion

if not exist Dates.txt goto not_found_dates

for /F "usebackq tokens=1,2 delims==" %%i in (`wmic os get LocalDateTime /VALUE 2^>NUL`) do if '.%%i.'=='.LocalDateTime.' set ldt=%%j
set d=%ldt:~6,2%
set m=%ldt:~4,2%
set y=%ldt:~0,4%
set ldt=%d%.%m%.%y%

echo ************************
echo * Today:    %ldt% *

:loop
set /a d=1%d%-99

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

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

set td=0%d%
set td=%td:~-2%
set tm=0%m%
set tm=%tm:~-2%
set ty=%y%

set tomorrow=%td%.%tm%.%ty%

echo * Tomorrow: %tomorrow% *
echo ************************

for /f "tokens=1,2 delims=:" %%A in (Dates.txt) do (
    if "%%B"==" %tomorrow%" echo # You have %%Atomorrow!
)

goto :EOF

:not_found_dates
echo Dates.txt not found!
goto :EOF

It works for the Dates.txt file, that uses dates in this format:

EventName1 : 31.05.2016
EventName2 : 30.05.2016
EventName3 : 31.05.2016
EventName4 : 01.06.2016
EventName5 : 31.05.2016
EventName6 : 02.06.2016
EventName7 : 01.06.2016

(Shouldn't forget about single empty spaces before and after colon, and about leading zeros for days and months that are less than 10.)


UPDATE:

At first, set /a d+=1 adds a day.

Then, this line:

xcopy /d:%m%-%d%-%y% /l . .. >nul 2>&1 || goto loop

checks if the date that was formed by set /a d+=1 part, actually exists in the calendar. If the date that was formed doesn't exist, it just "skips" the date, moving to the beginning of the loop to add one more day. This way, the date that doesn't exist can't be set as tomorrow's date.

The if %d% gtr 31 ( part is not doing anything unless it is actually 31st day of month today.

So, despite the if %d% gtr 31 ( part that looks somewhat confusing, this code still works well for months that have less than 31 days in them.

To understand it all better, turn @echo on and trace the changes in the date values.

For example, if we use:

set d=30
set m=04
set y=2016

Output is:

************************
* Today:    30.04.2016 *
* Tomorrow: 01.05.2016 *
************************

Also, for:

set d=28
set m=02
set y=2015

Output:

************************
* Today:    28.02.2015 *
* Tomorrow: 01.03.2015 *
************************
Mofi
  • 46,139
  • 17
  • 80
  • 143
0lesya
  • 147
  • 15
2

Here is a pure batch file solution to calculate tomorrow's date from current date with remarks explaining the code. The lines with remark command rem can be removed for faster processing the batch file by Windows command processor.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if "%~1" == "" (
    rem Get local date and time in a region independent format.
    for /F "skip=1 tokens=1 delims=." %%D in ('%SystemRoot%\System32\wbem\wmic.exe OS get LocalDateTime') do set "LocalDateTime=%%D" & goto GetDate
) else (
    rem This is for fast testing determining the date of tomorrow from any
    rem date specified as parameter in format yyyyMMdd on calling this batch
    rem file from within a command prompt window. The parameter string is
    rem not validated at all as this is just for testing the code below.
    set "LocalDateTime=%~1"
)

rem Get day, month and year from the local date/time string (or parameter).
:GetDate
set "Day=%LocalDateTime:~6,2%"
set "Month=%LocalDateTime:~4,2%"
set "Year=%LocalDateTime:~0,4%"

rem Define a variable with today's date in format dd.MM.yyyy
set "Today=%Day%.%Month%.%Year%"

rem Increase the day in month by 1 in any case.

rem It is necessary to remove leading 0 for the days 08 and 09 as
rem those two days would be otherwise interpreted as invalid octal
rem numbers and increment result would be 1 instead of 9 and 10.
rem if "%Day:~0,1%" == "0" set "Day=%Day:~1%"
rem set /A Day+=1

rem Faster is concatenating character 1 with the day string to string
rem representing 101 to 131 and subtract 99 to increment day by one.
set /A Day=1%Day%-99

rem The tomorrow's date is already valid if the day of month is less than 29.
if %Day% LSS 29 goto BuildTomorrow

rem Tomorrow is next month if day is equal (or greater) 32.
if %Day% GEQ 32 goto NextMonth

rem Day 31 in month is not possible in April, June, September and November.
rem In February it can't occur that day in month increased from 30 to 31
rem except on calling this batch file with invalid date string 20160230.
if %Day% EQU 31 (
    if %Month% == 04 goto NextMonth
    if %Month% == 06 goto NextMonth
    if %Month% == 09 goto NextMonth
    if %Month% == 11 goto NextMonth
)

rem The day 29 and 30 in month is valid for all months except February.
if NOT %Month% == 02 goto BuildTomorrow

rem Determine if this year is a leap year with 29 days in February.
set /A LeapYearRule1=Year %% 400
set /A LeapYearRule2=Year %% 100
set /A LeapYearRule3=Year %% 4

rem The current year is always a leap year if it can be divided by 400
rem with 0 left over (1600, 2000, 2400, ...). Otherwise if the current
rem year can be divided by 100 with 0 left over, the current year is NOT
rem a leap year (1900, 2100, 2200, 2300, 2500, ...). Otherwise the current
rem year is a leap year if the year can be divided by 4 with 0 left over.
rem Well, for the year range 1901 to 2099 just leap year rule 3 would be
rem enough and just last IF condition would be enough for this year range.

set "LastFebruaryDay=28"
if %LeapYearRule1% == 0 (
    set "LastFebruaryDay=29"
) else if NOT %LeapYearRule2% == 0 (
    if %LeapYearRule3% == 0 (
         set "LastFebruaryDay=29"
    )
)
if %Day% LEQ %LastFebruaryDay% goto BuildTomorrow

rem Tomorrow is next month. Therefore set day in month to 1, increase the
rem month by 1 and if now greater than 12, set month to 1 and increase year.
:NextMonth
set "Day=1"
set /A Month=1%Month%-99
if %Month% GTR 12 (
    set "Month=1"
    set /A Year+=1
)

rem The leading 0 on month and day in month could be removed and so both
rem values are defined again as string with a leading 0 added and next just
rem last two characters are kept to get day and month always with two digits.
:BuildTomorrow
set "Day=0%Day%"
set "Day=%Day:~-2%"
set "Month=0%Month%"
set "Month=%Month:~-2%"

rem Define a variable with tomorrow's date in format dd.MM.yyyy
set "Tomorrow=%Day%.%Month%.%Year%"

echo Today is:    %Today%
echo Tomorrow is: %Tomorrow%

endlocal

Please read my answer on Why does %date% produce a different result in batch file executed as scheduled task? It explains in full details the FOR command line using WMIC to get current date in region independent format.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • rem /?
  • set /?
  • setlocal /?
  • wmic OS get /?
Mofi
  • 46,139
  • 17
  • 80
  • 143