This question already has an answer here:
How to generate succesive dates? (add N days to date)
(1 answer)
Closed last month.
I have bat script for loop function
#echo off set /p a="Start Date(yyyymmdd):"%=% set /p b="Finish Date
(yyyymmdd):"%=%
echo %a% echo %b%
echo start loop
FOR /L %%c IN (%a%,1,%b%) DO ( echo %%c
set inputan=%%c
call test_loopong.bat %inputan%
)
I need to run according to the range of start and end date input.
But from the script above, for example the start date is 20221231 and the end date is 20230103
will loop all numbers from 20221231, 20221232, 20221233......20230103
Please someone can help me.
Thanks
#ECHO Off
SETLOCAL
set /p "startdate=Start Date(yyyymmdd):"
set /p "finishdate=Finish Date (yyyymmdd):"
echo %startdate%
echo %finishdate%
IF %finishdate% lss %startdate% ECHO Invalid DATE range&GOTO :eof
echo start loop
FOR /L %%c IN (%startdate%,1,%finishdate%) DO (
FOR /F %%y IN ('set /a inputan^=%%c %% 100') DO IF %%y lss 32 IF %%y gtr 0 (
echo %%c
set /a inputan=%%c
call :test_loopong.bat %%c
)
)
GOTO :EOF
:test_loopong.bat
ECHO IN test_loopong : %%1=%1 inputan=%inputan%
GOTO :eof
I changed the variable names so that they are maintainable, 'though I've no idea what inputan means.
Added invalid date-range check.
Note syntax of set /p
Forget for the moment what for...%%y... does.
I used a set /a since %%c must be numeric.
Use set "var1=value" for setting STRING values - this avoids problems caused by trailing spaces.
I converted test_loopong.bat to an internal subroutine (call :name) for demonstration purposes to avoid having to generate another file.
I'm having that subroutine simply display the value of the variable inputan and the parameter %1. %%c can be delivered as a parameter to the subroutine (be it internal or external) but your syntax would appear to omit the parameter because of the delayed expansion trap - %var% will be replaced by the value of var at the time the outer loop (for...%%c) is encountered.
Now the for...%%y jiggery-pokery.
The command set /a inputan=%%c % 100 would set inputan to %%c mod 100. There's no importance about the variable name - that one's about to be assigned a different value again in a couple of lines.
When used in a for /f, batch will execute the set/a command and echo the result to the metavariable %%y.
However, = and % are special characters and need to be "escaped" (interpreted without their special meaning). Th escape character for most specials is caret (^) but for % is % itself.
The result of the calculation is assigned to %%y and we can then test that %%y is lss 32 - Less than 32, and also it is gtr 0 - Greater than 0. Only then do we call test_loopong.bat. This eliminates most non-dates
If you don't want to skip the non-dates, then remove the for...%%y line and delete one of the ) lines.
--- further thoughts ----
Suppressing the days 32..99 & 00 really only does half the job. Much better if we suppress months 13..99 & 00. The revision then would be (presenting just the main loop, minus the frippery)
FOR /L %%c IN (%startdate%,1,%finishdate%) DO (
FOR /F %%e IN ('set /a inputan^=%%c %% 10000') DO IF %%e lss 1232 IF %%e gtr 100 (
FOR /F %%y IN ('set /a inputan^=%%c %% 100') DO IF %%y lss 32 IF %%y gtr 0 (
echo %%c
set /a inputan=%%c
call :test_loopong.bat %%c
)
)
)
Same principle, just dealing with months in place of days.
One slight problem with this method is that it's as slow as a wet week.
So - a different approach
SET /a yyyy=%startdate:~0,4%
SET /a mm1=1%startdate:~4,2%
SET /a dd1=1%startdate:~-2%
:loop2
SET /a inputan=%yyyy%0000+%mm1%00+dd1-10100
IF %inputan% gtr %finishdate% GOTO :eof
CALL :test_loopong.bat %inputan%
SET /a dd1+=1
IF %dd1% leq 131 GOTO loop2
SET /a dd1=101&SET /a mm1+=1
IF %mm1% leq 112 GOTO loop2
SET /a mm1=101
SET /a yyyy+=1
GOTO loop2
This sets yyyy to the year and mm1/dd1 to 100+(month/day). 100+ needs to be done since batch regards a numeric string that starts 0 as
octal hence August and September cause problems.
So - calculate inputan by tringing 4 0s to yyyy, adding 100*mm1 and dd1, then subtracting 10100 since mm1 is mm+100 and dd1 is dd+100.
If the resultant inputan is greater than the finish date, end the routine.
Test using inputan.
Next day - add 1 to dd1.
If the result is less than or equal to 131, we're fine.
Otherwise set dd1 to 101 and increment the month
Same recipe for mm1, limit is 112 and bump the year if required.
---- Further revision to deal with non-dates 31st Apr, Jun, Sep, Nov and Feb (include leap years) ---
#ECHO Off
SETLOCAL
set /p "startdate=Start Date(yyyymmdd):"
set /p "finishdate=Finish Date (yyyymmdd):"
echo %startdate%
echo %finishdate%
IF %finishdate% lss %startdate% ECHO Invalid DATE range&GOTO :eof
echo start loop
GOTO ver2
FOR /L %%c IN (%startdate%,1,%finishdate%) DO (
FOR /F %%e IN ('set /a inputan^=%%c %% 10000') DO IF %%e lss 1232 IF %%e gtr 100 (
FOR /F %%y IN ('set /a inputan^=%%c %% 100') DO IF %%y lss 32 IF %%y gtr 0 (
echo %%c
set /a inputan=%%c
call :test_loopong.bat %%c
)
)
)
GOTO :EOF
:ver2
SET /a yyyy=%startdate:~0,4%
SET /a mm1=1%startdate:~4,2%
SET /a dd1=1%startdate:~-2%
:loop2
SET /a inputan=%yyyy%0000+%mm1%00+dd1-10100
IF %inputan% gtr %finishdate% GOTO :eof
CALL :test_loopong.bat %inputan%
SET /a dd1+=1
SET /a inputan=yyyy %% 4
IF %mm1%==102 IF %dd1% gtr 129 (GOTO nextmonth) ELSE IF %inputan% neq 0 IF %dd1%==129 GOTO nextmonth
FOR %%e IN (104 106 109 111) DO IF %%e131==%mm1%%dd1% GOTO nextmonth
IF %dd1% leq 131 GOTO loop2
:nextmonth
SET /a dd1=101&SET /a mm1+=1
IF %mm1% leq 112 GOTO loop2
SET /a mm1=101
SET /a yyyy+=1
GOTO loop2
GOTO :eof
:test_loopong.bat
ECHO IN test_loopong : %%1=%1 inputan=%inputan%
GOTO :eof
Related
I've been trying to read line by line from text file. In each line, I do have "starttime" & "endtime" field in 3 & 4 th column as I highlighted below.
File1,110543,2020-07-18T03:09:12.1321687+00:00,2020-07-18T03:10:22.4097433+00:00,000001
File2,210543,2020-07-18T04:19:28.0459100+00:00,2020-07-18T04:26:08.6626472+00:00,000002
I just want to find the difference between "starttime" & "endtime" column using below script.
#Echo off&Setlocal EnableExtensions EnableDelayedExpansion
IF EXIST "%csvFilePath%tempfile.txt" (
( for /f "tokens=1-5 delims=," %%A in (%csvFilePath%tempfile.txt) do (
echo fileRecord %%A,%%B,%%C,%%D,%%E
for /f "tokens=1,2,3,4 delims=T:." %%a in ("%%C") Do (
set starttime=%%b:%%c:%%d
)
for /f "tokens=1,2,3,4 delims=T:." %%a in ("%%D") Do (
set endtime=%%b:%%c:%%d
)
echo !starttime!
echo !endtime!
set options="tokens=1-4 delims=:.,"
for /f %options% %%a in (!starttime!) do set start_h=%%a&set /a start_m=100%%b %% 100&set /a start_s=100%%c %% 100&set /a start_ms=100%%d %% 100
for /f %options% %%a in (!endtime!) do set end_h=%%a&set /a end_m=100%%b %% 100&set /a end_s=100%%c %% 100&set /a end_ms=100%%d %% 1
set /a hours=%end_h%-%start_h%
set /a mins=%end_m%-%start_m%
set /a secs=%end_s%-%start_s%
set /a ms=%end_ms%-%start_ms%
if %ms% lss 0 set /a secs = %secs% - 1 & set /a ms = 100%ms%
if %secs% lss 0 set /a mins = %mins% - 1 & set /a secs = 60%secs%
if %mins% lss 0 set /a hours = %hours% - 1 & set /a mins = 60%mins%
if %hours% lss 0 set /a hours = 24%hours%
if 1%ms% lss 100 set ms=0%ms%
:: Mission accomplished
set /a totalsecs = %hours%*3600 + %mins%*60 + %secs%
echo command took %hours%:%mins%:%secs%.%ms% (%totalsecs%.%ms%s total))))
start(03:09:12) & endtime(03:10:22) value is being printed for line1 as expected when I'm using !starttime! & !endtime!. I'm trying to pass the same variable to calculate the difference in below line.
for /f %options% %%a in (!starttime!) do set start_h=%%a&set /a start_m=100%%b %% 100&set /a start_s=100%%c %% 100&set /a start_ms=100%%d %% 100
for /f %options% %%a in (!endtime!) do set end_h=%%a&set /a end_m=100%%b %% 100&set /a end_s=100%%c %% 100&set /a end_ms=100%%d %% 1
after execution, I'm getting "0 was unexpected at this time". Can you pls help me on this
There are some issues in your code:
don't use :: as a comment. Especially within a code block. It might break your code or lead to unexpected and hard to troubleshoot results.
you need delayed expansion for all variables defined in the code block (you used delayed expansion for a few variables, but not for all.
set /a doesn't need % or ! at all (optional, but here you'd need ! instead of %).
to process a string with for /f, it needs to be quoted, or for tries to find a file with that name.
You had a superfluent pair of parentheses.
%csvFilePath% is not defined.
for /f %options% ... works, but not with delayed variables, so I moved the declaration of %options% out of the loop.
Your code was not properly indented, so the structure was hardly recognizable (I spotted the lack of delayed expansion only after indenting, which made it blatantly obvious)
Your code with all those issues fixed:
#Echo off
Setlocal EnableExtensions EnableDelayedExpansion
set "options=tokens=1-4 delims=:.,"
IF EXIST "%csvFilePath%tempfile.txt" (
for /f "tokens=1-5 delims=," %%A in (%csvFilePath%tempfile.txt) do (
echo fileRecord %%A,%%B,%%C,%%D,%%E
for /f "tokens=1,2,3,4 delims=T:." %%a in ("%%C") Do set starttime=%%b:%%c:%%d
for /f "tokens=1,2,3,4 delims=T:." %%a in ("%%D") Do set endtime=%%b:%%c:%%d
echo !starttime!
echo !endtime!
for /f "%options%" %%a in ("!starttime!") do set start_h=%%a&set /a start_m=100%%b %% 100&set /a start_s=100%%c %% 100&set /a start_ms=100%%d %% 100
for /f "%options%" %%a in ("!endtime!") do set end_h=%%a&set /a end_m=100%%b %% 100&set /a end_s=100%%c %% 100&set /a end_ms=100%%d %% 1
set /a hours=end_h-start_h
set /a mins=end_m-start_m
set /a secs=end_s-start_s
set /a ms=end_ms-start_ms
if !ms! lss 0 set /a secs = secs - 1 & set /a ms = 100!ms!
if !secs! lss 0 set /a mins = mins - 1 & set /a secs = 60!secs!
if !mins! lss 0 set /a hours = hours - 1 & set /a mins = 60!mins!
if !hours! lss 0 set /a hours = 24!hours!
if 1!ms! lss 100 set ms=0!ms!
REM Mission accomplished
set /a totalsecs = hours*3600 + mins*60 + secs
echo command took !hours!:!mins!:!secs!.!ms! (!totalsecs!.!ms!s total^)
)
)
(Note: I didn't check your math - I trust you there, as the results seem plausible)
Output with your example file:
fileRecord File1,110543,2020-07-18T03:09:12.1321687+00:00,2020-07-18T03:10:22.4097433+00:00,000001
03:09:12
03:10:22
command took 0:1:10.00 (70.00s total)
fileRecord File2,210543,2020-07-18T04:19:28.0459100+00:00,2020-07-18T04:26:08.6626472+00:00,000002
04:19:28
04:26:08
command took 0:6:40.00 (400.00s total)
I'm new to batch scripting and don't understand why double digit numbers evaluate as less than single digit?
%weekdayOffPeakEnd% variable is 7 when echo'd.
I'm calling this sleepUntilOffPeak function from within a FOR loop (not shown) but I don't think that has any impact because I don't use any variables from this function anywhere else in the script. This function simply checks the current hour and "sleeps" until electricity rates are low again.
Thx
rem if not currently off-peak hours, wait (timeout) until electricity rates are lowest
:sleepUtilOffPeak
rem set DayofWeek and Hour variables
for /f %%a in ('wmic path win32_localtime get DayOfWeek /format:list ^| findstr "="') do (set %%a)
for /f %%a in ('wmic path win32_localtime get Hour /format:list ^| findstr "="') do (set %%a)
rem echo Day of week^: %DayOfWeek%
echo Hour^: %Hour%
rem set OffPeak variables
set /a weekdayOffPeakEnd=07
echo weekdayOffPeakEnd^: %weekdayOffPeakEnd%
set /a weekdayOffPeakStart=23
set /a weekendOffPeakEnd=15
set /a weekendOffPeakStart=19
set weekday=true
if "%DayOfWeek%" EQU "0" set weekday=false
if "%DayOfWeek%" EQU "6" set weekday=false
rem echo weekday^: %weekday%
if %weekday% equ true (
echo Today is a weekday
if Hour LSS weekdayOffPeakEnd (
echo %Hour% is less than off-peak end^: %weekdayOffPeakEnd%. Returning...
exit /B 0
) else (
if Hour GEQ weekdayOffPeakStart (
echo %Hour% is greater than or equal to off-peak start^: %weekdayOffPeakStart%. Returning...
exit /B 0
) else ( rem Hour is between 07 and 23
rem sleep until offPeak then return
set /a sleepTime=23-%Hour%
set /a sleepSeconds=%sleepTime%*3600
echo Going to sleep for %sleepSeconds% seconds
timeout /t %sleepSeconds%
exit /B 0
)
)
) else ( rem weekday equ false
echo Today is a weekend
if Hour LSS weekendOffPeakEnd (
echo %Hour% is less than off-peak end^: %weekendOffPeakEnd%. Returning...
exit /B 0
) else (
if Hour GEQ weekendOffPeakStart (
echo %Hour% is greater than or equal to off-peak start^: %weekendOffPeakStart%. Returning...
exit /B 0
) else ( rem Hour is between 15 and 19
rem sleep until offPeak then return
set /a sleepHours=%weekendOffPeakStart%-%Hour%
echo sleepHours^: %sleepHours%
set /a sleepSeconds=%sleepHours%*3600
echo Going to sleep for %sleepSeconds% seconds
timeout /t %sleepSeconds%
echo All done sleeping. Returning...
exit /B 0
)
)
)
You have many examples like this:
if Hour LSS weekdayOffPeakEnd (
This compares the literal Hour to the literal weekdayOffPeakEnd
You need
if %Hour% LSS %weekdayOffPeakEnd% (
Further, if you change the value of any variable within a code block (parenthesised code) then you need to retrieve the changed value using !var! having invoked delayed expansion (use search to locate many SO items)
Also, you observe that set /a var=07 will set the variable to 7, not 07. It's important to understand the difference between set /a and set. set /a resolves the value to be assigned and then assigns that value as a string to the variable, suppressing leading zeroes. set assigns the literal including leading zeroes.
This leads to two consequences. First, a value that starts with 0 is assigned by set/a as an OCTAL value, so 08 and 09 will be invalid. And second, if %var% op val will attempt to convert both arguments of the operator to numeric to perform the comparison, and if both conversions are successful, then the comparison is executed as a numeric comparison, otherwise it's executed as a string comparison where the characters are matched serially from the left.
I'm trying to do something like this, but I can't make it to work.
for /F "tokens=1" %%a in (C:\Auxiliar4.txt) do (
if !counter! EQU 3 (set /A failed=%%a)
if !counter! EQU 9 (set /A completed=%%a)
if !counter! EQU 6 (set /A total=%%a)
set /A counter+=1
)
set /A counter=0
set /A failedday=%failedday%+%failed%
if %total% NEQ 0 (set /A success=(%completed%*100)/%total%)
My problem is with these two lines:
set /A failedday=%failedday%+%failed%
if %total% NEQ 0 (set /A success=(%completed%*100)/%total%)
The first issue is with variable "failedday", I need to read numeric values from a txt file, assign them to those variables (failed, completed, total) and then assign the value of "failed" to "failedday". Then another FOR loop starts to read a different txt with same format, assign those numeric values to "failed", "completed", "total" again (losing the previous values), and add new value of "failed" to "failedday" keeping the previous addition (example, filedday=2 after first "for", after second should be failedday=2 + New"Failed"Value).
The second issue is with "IF" structure. I need to calculate the average of completed transactions taking values from "For" loop, only if "total" is not equal to 0 (to avoid divide by zero), but when I add this line my script crashes.
Could anyone help me with this? Thanks!!!
Here's a previous StackOverflow question that asks the same sort of thing.
Here's another reference for doing arithmetic with DOS Batch files.
You need to enable delayed expansion to perform the arithmetic:
#echo off & setlocal EnableDelayedExpansion
set /A failed=0
set /A completed=0
set /A total=0
for /F "tokens=1" %%a in (C:\Temp\test.txt) do (
if !counter! EQU 3 (set /A failed=%%a)
if !counter! EQU 9 (set /A completed=%%a)
if !counter! EQU 6 (set /A total=%%a)
set /A counter+=1
)
echo Failed: %failed%
echo Completed: %completed%
echo Total: %total%
set /A counter=0
set /A failedday=failedday+failed
if total NEQ 0 (set /A success=completed*100/total)
echo Success: %success%
I have a file with this output:
ANS8000I Server command: 'ru FailedReport'
Unnamed[1]
------------
9
Unnamed[1]
------------
110
Unnamed[1]
------------
101
I need to take those numbers, and assign it to three different variables. I made this script, but I can't make it to work... I always got "0" as result.
#echo off
setlocal enableextensions enabledelayedexpansion
set /A counter=0
SET /A failed=0
SET /A completed=0
SET /A total=0
for /F "tokens=1 skip=4" %%a in (C:\Users\Desktop\Aux.txt) do (
if "%counter%" EQU 5 (set /A failed=%%a)
if "%counter%" EQU 9 (set /A completed=%%a)
if "%counter%" EQU 13 (set /A total=%%a)
set /A counter+=1
)
echo "Failed: " %failed% >> C:\Users\Desktop\Result.txt
echo "Completed: " %completed% >> C:\Users\Desktop\Result.txt
echo "Total: " %total% >> C:\Users\Desktop\Result.txt
Could anyone help me with this? I tried a lot of combinations (variables with !, %, %%), but I still got the same result.
Thanks!!!
#ECHO OFF
setlocal enableextensions enabledelayedexpansion
set /A counter=0
SET /A failed=0
SET /A completed=0
SET /A total=0
for /F "tokens=1" %%a in (q24152955.txt) do (
ECHO !counter! %%a
if !counter! EQU 3 (set /A failed=%%a)
if !counter! EQU 9 (set /A completed=%%a)
if !counter! EQU 6 (set /A total=%%a)
set /A counter+=1
)
echo "Failed: " %failed%
echo "Completed: " %completed%
echo "Total: " %total%
GOTO :eof
I used a file named q24152955.txt containing your data for my testing.
In delayedexpansion mode, %var% refers to the original value of var - before the loop began execution and !var! is the dynamic value - as it changes.
"something" is never going to be equal to something because the quotes are significant. Quoted values are often used in this context in case the value itself is empty or contains special characters (especially spaces) - "" is a non-empty string.
for /f ignores empty lines. I've included a superfluous echo command to show which lines the for processes. Note that the value of counter is thus the sequential number of non-empty lines in the file, not the actual line number. Note also that a line containing just one (or more) spaces is not an empty line!
#ECHO off&cls
setlocal enabledelayedexpansion
set "$count=1"
for /f "delims=" %%a in (C:\Users\Desktop\Aux.txt) do (
if !$count!==4 set failed=%%a
if !$count!==7 set completed=%%a
if !$count!==10 set total=%%a
set /a $count+=1
)
(echo Failed : %failed: =%
echo Completed : %completed: =%
echo Total : %total: =%)> C:\Users\Desktop\Result.txt
How I can check the date using a calender , what I want to do is that a user insert a date in this way 2012/07/15 , and i want to check if this date exist in the calender .
for example if he insert 2012/14/13 or even 2012/02/31 , i tried to do that manually but its really hard , so my qustions are :
is there a native function(or even 3d party tools) to check date in calender ?
if the user insert date and hour , I want to give same result with different time zone places ?
There is no simple native batch command that will validate your string.
Here is a batch subroutine that can be used to validate the date string.
#echo off
setlocal
set "dt="
set /p "dt=Enter a date in yyyy/mm/dd format: "
if not defined dt exit /b
call :validateDate dt && (echo date is valid) || (echo ERROR: date is invalid)
exit /b
:validateDate
setlocal enableDelayedExpansion
echo !%~1!|findstr /rx "[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]" >nul || exit /b 1
for /f "tokens=1,2,3 delims=/" %%A in ("!%~1!") do (
set /a "yyyy=10000%%A%%10000, mm=100%%B%%100, dd=100%%C%%100" || exit /b 1
)
if %mm% lss 1 exit /b 1
if %mm% gtr 12 exit /b 1
if %dd% lss 1 exit /b 1
set "months=;1-31;2-28;3-31;4-30;5-31;6-30;7-31;8-31;9-30;10-31;11-30;12-31;"
for /f "delims=;" %%A in ("!months:*;%mm%-=!") do set maxDays=%%A
set /a "divBy4=yyyy%%4, divBy100=yyyy%%100, divBy400=yyyy%%400"
if %mm% equ 2 if %divBy4% equ 0 (
if %divBy100% neq 0 set /a maxDays+=1
if %divBy400% equ 0 set /a maxDays+=1
)
if %dd% gtr %maxDays% exit /b 1
exit /b 0
It will only accept 4 digit years, 2 digit months, and 2 digit days as you have posted in your question. If you want to support 1 digit months or days, then change the FINDSTR to the following:
echo !%~1!|findstr /rx /c:"[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]" ^
/c:"[0-9][0-9][0-9][0-9]/[0-9]/[0-9][0-9]" ^
/c:"[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9]" ^
/c:"[0-9][0-9][0-9][0-9]/[0-9]/[0-9]">nul || exit /b 1
I don't understand what you want to do with the date and time zones.
The subroutine below is comprised of two parts. First it check the date given in 1st parameter and return ERRORLEVEL=1 if the date is bad. You may insert a year valid range if you wish (otherwise, remove the yyOK parts).
Then it takes a base hour and time-zone adjust in 2nd and 3rd parameters and show the adjusted date.
:validateDate result= YYYY/MM/DD [HH HHAdjust]
setlocal EnableDelayedExpansion
set i=0
for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do (
set /A i+=1
set daysPerMonth[!i!]=%%a
)
set result=Invalid date
for /F "tokens=1-3 delims=/" %%a in ("%2") do set yy=%%a& set mm=%%b& set dd=%%c
set /A yy=%yy%, mm=10%mm% %% 100, dd=10%dd% %% 100, yyMOD4=yy%%4 >NUL 2>&1 || goto exit
if %yyMOD4% equ 0 set daysPerMonth[2]=29
set /A yyOK=0, mmOK=0, ddOK=0
rem Modify year limits as you wish (or remove they):
if %yy% geq 1900 if %yy% leq 2015 set yyOK=1
if %mm% geq 1 if %mm% leq 12 set mmOK=1
id %dd% geq 1 if %dd% leq !daysPerMonth[%mm%]! set ddOK=1
set /A dateOK=yyOK*mmOK*ddOK
if %dateOK% neq 1 goto exit
rem Date is correct
set result=%yy%/%mm%/%dd%
rem Adjust the hour to different time zone, if given
rem %3=base hour, %4=adjust with sign (+ or -)
if "%4" equ "" goto exit
set /A newHH=10%3 %% 100 %4
if %newHH% gtr 23 (
rem Pass to next day
set /A newHH-=24, dd+=1
if !dd! gtr !daysPerMonth[%mm%]! (
set /A dd=1, mm+=1
if !mm! gtr 12 (
set /A mm=1, yy+=1
)
)
)
if %newHH% lss 1 (
rem Pass to previous day
set /A newHH+=24, dd-=1
if !dd! lss 1 (
set /A mm-=1
if !mm! lss 1 (
set /A mm=12, yy-=1
)
for %%m in (!mm!) do (
set /A dd=daysPerMonth[%%m]
)
)
)
set result=%yy%/%mm%/%dd% %newHH%
:exit
endlocal & set %1=%result%
exit /B
Test this program and report any problem.
EDIT: I have modified previous program to fit new OP's requirements.
The subroutine no longer returns an ERRORLEVEL value with the result. It must be called now with a new first parameter that indicate the variable that will receive the result, that will be "Invalid date" if original date is bad. If a base and adjustment hours are given, returned value include the adjusted date and hour. For example:
call validate.bat adjusted= 2012/3/5 3 -2
if "%adjusted%" neq "Invalid date" (
echo Adjusted date and hour are: %adjusted%
)
Antonio