1

I write a batch script and I want to verify that the user enters a date in correct format like DD-MM-YYYY.

But I have a problem with a variable. I can display its value with the command echo, but the further processing of the variable´s value does not work as expected and so the if condition doesn't work, too. I don't understand where the problem is!

Here is my batch script:

@echo off
cls

:A
echo.
set /p date=Quelle date souhaitez vous enregistrer (JJ-MM-AAAA) ?

for /f "tokens=1,2,3 delims=-" %%a in ("%date%") do (
    set day=%%a
    set month=%%b 
    set year=%%c
)

echo %day%
set date1 = %day%
echo %date1%
echo %month%
echo %year%
echo %date%

if "%date%" == %day%-%month%-%year%(echo yes) else (echo no)

goto :A

Here is the output of my batch file on execution:

Quelle date souhaitez vous enregistrer (JJ-MM-AAAA) ?09-09-09999
09
Commande ECHO désactivée.
09
0999
09-09-0999

Quelle date souhaitez vous enregistrer (JJ-MM-AAAA) ?

You can see that the if doesn't work. I don't understand why %day%-%month%-%year% is null.

Donald Duck
  • 8,409
  • 22
  • 75
  • 99
  • 1
    You didn't define the `%date1%` variable. You defined `%date1 %` instead. Remove any spaces around the `=` with the `set` command. And add a space between `%year%` and `(`. – Stephan Jun 16 '22 at 08:10
  • Oh thanks you so much !! I don't use batch very often and I have forget that this programmation was case sensitive ... And I made also a mistake with the comparison for my if with the spaces around `==`. –  Jun 16 '22 at 10:33
  • 1
    in fact the spaces around `==` with `if` is correct. When you omit them, the parser does some extra work to insert them again. (Hey - nobody claims, `cmd` syntax is consistent...) – Stephan Jun 16 '22 at 10:44
  • I make the test with `==` and indeed it's working. Thanks you for this precision ! –  Jun 16 '22 at 11:24
  • 1
    Fascinating. `if "%date%" == %day%-%month%-%year% (echo yes) else (echo no)` should **always** report `no` since the `if` statement requires an *exact* match, and thus **both** sides should be `"quoted"`. Please don't use `date` as a variable name, as it is set by the system to the current date. If you `set` it, then the user-setting overrides the system setting. If you set it to *nothing* (`set "date="`) then it will once again "contain" the system date. – Magoo Jun 16 '22 at 15:04
  • @Magoo I wondered myself also why `if "%date%" == %day%-%month%-%year%(echo yes) else (echo no)` does not result in any message on running the batch file, not even an error message. The reason for not getting displayed any message is described in my answer in the chapters __1.4__ and __1.6__ resulting finally in execution of `if "09-09-0999" == 09-09 -0999(echo yes) else (echo no)`. Note the space after the month. – Mofi Jun 17 '22 at 13:33

1 Answers1

0

1. Errors in batch file code

1.1 Usage of echo. to output an empty line

Please read the DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/ and use in future echo( as that is the only available method always outputting an empty line without additional file system accesses.

1.2 No validation of user input string before further processing

Please read the chapter Usage of SET /P for user prompts in my answer on How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?

1.3 Definition of an environment variable with name of a dynamic variable

Please open a command prompt, run set /? and read the output usage help. There is explained briefly also the dynamic variable DATE of which current value can be accessed using the syntax for accessing environment variables.

The following command line results in the definition of the environment variable date on user really inputs a string at all making it impossible to access the value of the dynamic variable DATE after the execution of that command line and user input a string.

set /p date=Quelle date souhaitez vous enregistrer (JJ-MM-AAAA) ?

Do not use the name of a dynamic variable for an environment variable.

See also: Difference between Dynamic Environment Variables and Normal Environment Variables in CMD

1.4 Spaces around equal sign on environment variable definition

The space character is a very important character for the Windows Command Processor cmd.exe processing batch files. Therefore the author of a batch file must take care on using spaces in a command line in the batch file.

set date1 = %day% is not correct to define an environment variable with name date1 with the string value of the environment variable day as explained in full details by my answer on
Why is no string output with 'echo %var%' after using 'set var = text' on command line?

The referenced answer describes also very detailed why it is advisable to use the syntax set "variable=value" to prevent the definition of an environment variable with a trailing whitespace appended unwanted to the string value as done by the command line set month=%%b inside the for /f loop.

1.5 String comparison with just one string enclosed in double quotes

The condition if "%date%" == %day%-%month%-%year% is never true because of the double quotes are taken into account on comparing the string left to the string comparison operator == with the string right to the comparison operator.

Please see my answer on Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files for full details about how a string comparison is done by the command IF respectively cmd.exe.

1.6 Missing space character after second string in IF condition

The following command line is syntactically wrong because of a missing space:

if "%date%" == %day%-%month%-%year%(echo yes) else (echo no)

There are not only missing the double quotes around %day%-%month%-%year%, but there is also missing the space character left to (echo which would result in interpreting %day%-%month%-%year%(echo as second string to compare with "%date%" and the rest of the line as command to execute.

But this command line results in the execution of:

if "09-09-0999" == 09-09 -0999(echo yes) else (echo no)

The trailing space on the command line set month=%%b is responsible for comparing the string "09-09-0999" with the string 09-09 and interpreting -0999(echo yes) else (echo no) as the command to execute on positive comparison as it can be seen on debugging the batch file. The condition is never true and for that reason the "command" is never executed which would otherwise result in an error message.

2. Batch file for validation of input date

Here is a commented batch file to prompt a user for entering a date as long as not entering a valid date. The input date is verified by the batch file in a fail-safe and secure manner.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
cls
echo(
goto DatePrompt

:InvalidDate
echo(
setlocal EnableDelayedExpansion
echo ERROR: !DateInput! is not a valid date string (%ErrorInfo%).
endlocal
echo(

:DatePrompt
set "DateInput="
set /P "DateInput=Quelle date souhaitez vous enregistrer (JJ-MM-AAAA)? " || goto DatePrompt
rem Remove all double quotes from the user input string.
set "UserDate=%DateInput:"=%"
rem Was there nothing else than one or more double quotes entered by the user?
if not defined UserDate set "ErrorInfo=no date string" & goto InvalidDate

rem The input date is invalid on third character not being a hyphen.
if not "%UserDate:~2,1%" == "-" set "ErrorInfo=invalid third character" & goto InvalidDate
rem The input date is invalid on fifth character not being a hyphen.
if not "%UserDate:~5,1%" == "-" set "ErrorInfo=invalid fifth character" & goto InvalidDate
rem The input date is invalid on having more than 10 characters.
if not "%UserDate:~10%" == "" set "ErrorInfo=too many characters" & goto InvalidDate
rem The input date is invalid on containing any other character than digits and hyphens.
for /F delims^=0123456789-^ eol^= %%I in ("%UserDate%") do set "ErrorInfo=invalid character" & goto InvalidDate

rem Split up the date into day, month and year.
for /F "tokens=1-3 delims=-" %%G in ("%UserDate%") do set "Day=%%G" & set "Month=%%H" & set "Year=%%I"
rem The input date is invalid on day having less than two digits.
if "%Day:~1%" == "" set "ErrorInfo=no two digit day" & goto InvalidDate
rem The input date is invalid on month having less than two digits.
if "%Month:~1%" == "" set "ErrorInfo=no two digit month" & goto InvalidDate
rem The input date is invalid on year having less than four digits.
if "%Year:~3%" == "" set "ErrorInfo=no four digit year" &  goto InvalidDate

rem The year is valid now with a four digit value between 0000 and 9999.

rem Convert the day value from string to integer and back to string
rem with taking into account that a number with a leading zero would
rem be interpreted as an octal number which is avoided by prependig
rem the day string by the character 1 to change 00 to 99 to 100 to 199
rem and subtracting 100 to get as result a string in range 0 to 99.
set /A "DayValue=1%Day%-100"
rem The input date is invalid on day is zero.
if %DayValue% == 0 set "ErrorInfo=day is zero" & goto InvalidDate

rem Do the same as above for the month.
set /A "MonthValue=1%Month%-100"
rem The input date is invalid on month is zero.
if %MonthValue% == 0 set "ErrorInfo=month is zero" & goto InvalidDate
rem The input date is invalid on month greater than 12.
if %MonthValue% GTR 12 set "ErrorInfo=month greater 12" & goto InvalidDate

rem A standard year has 28 days in February.
set "February=28"
rem Is the month not February, verify day in month.
if not %MonthValue% == 2 goto VerifyDay

rem Find out now if the year is a leep year.
set /A "YearValue=1%Year%-10000"
rem Get the remainder of the division of the year by four.
set /A Result=YearValue %% 4
rem If the remainder is not zero, the year is not a leap year.
if not %Result% == 0 goto VerifyDay
rem Get the remainder of the division of the year by four hundred.
set /A Result=YearValue %% 400
rem If the remainder is zero, the year is a leap year.
if %Result% == 0 set "February=29" & goto VerifyDay
rem Get the remainder of the division of the year by one hundred.
set /A Result=YearValue %% 100
rem If the remainder is zero, the year is not a leap year.
if %Result% == 0 goto VerifyDay
rem The year is a leap year.
set "February=29"

:VerifyDay
for /F "tokens=%MonthValue%" %%I in ("31 %February% 31 30 31 30 31 31 30 31 30 31") do if %DayValue% GTR %%I  set "ErrorInfo=day greater %%I" & goto InvalidDate

echo(
echo Congratulations: %UserDate% is a valid date.
echo(
pause
endlocal

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

  • cls /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • rem /?
  • set /?
  • setlocal /?

See also single line with multiple commands using Windows batch file for an explanation of the operators || and &.

Mofi
  • 46,139
  • 17
  • 80
  • 143