Delayed Expansion Inside Loop with Arithmetic Operations on Time Values

192 Views Asked by At

I am relatively new to batch files, and I have been trying to get the following timing routine (inspired from Arithmetic operations with HH:MM:SS times in batch file) to work:

set "startTime=%time: =0%"

@rem Removing milliseconds information
set startTime=%startTime:~0,-3%

setlocal EnableDelayedExpansion

for %%i in (1 2 3 4 5) do (

   timeout /T 3 /NOBREAK

   set endTime=!time: =0!
   set endTime=!endTime:~0,-3!

   set /A "ss=(((1%endTime::=-100)*60+1%-100)-(((1%startTime::=-100)*60+1%-100)"
   set /A "hh=ss/3600+100,ss%%=3600,mm=ss/60+100,ss=ss%%60+100"

   @rem Get format in HH:MM:SS (maybe H:MM:SS after midnight.. not tested yet)
   echo Start time: %startTime%
   echo End time: !endTime!

   @rem Issue here: Always get the same output despite delayedExpansion active
   echo Diff time: !ss!

   echo.

   @rem Issue here: Not getting expected values
   echo Elapsed time: !hh:~1!:!mm:~1!:!ss:~1!...
   echo.

)
endlocal

I am not quite sure why the output value for the time difference is always the same despite the delayed expansion. Also, the formatted time does not give me the correct values.

Thanks for your help!

1

There are 1 best solutions below

1
G. Rab On BEST ANSWER

First, thanks for the helpful comments which helped me find a solution to my question. In case it might help someone else, I am posting the solution here.

As mentioned in the comments, the key was to determine the formatting used on my operating system.

The code that works for me is below, inspired from https://www.py4u.net/discuss/2286184:

@rem Check that the format of %TIME% is HH:MM:SS.CS for example 23:59:59.99
echo "%TIME%"


set STARTTIME=%TIME%

@rem convert start time to centiseconds
set /A STARTTIME=(1%STARTTIME:~0,2%-100)*360000 + (1%STARTTIME:~3,2%-100)*6000 + (1%STARTTIME:~6,2%-100)*100 + (1%STARTTIME:~9,2%-100)

setlocal EnableDelayedExpansion

for %%i in (1 2 3 4 5) do (

   timeout /T 3 /NOBREAK
   
   set ENDTIME=!TIME!

   @rem convert ENDTIME to centiseconds
   @rem I found that double-quotes with set /A and numbers are needed inside the for loop
   set /A "ENDTIME=(1!ENDTIME:~0,2!-100)*360000 + (1!ENDTIME:~3,2!-100)*6000 + (1!ENDTIME:~6,2!-100)*100 + (1!ENDTIME:~9,2!-100)"
   
   @rem calculating the duratyion is easy
   set /A DURATION=!ENDTIME!-%STARTTIME%
   
   @rem Adjust for cases where timings over multiple days
   if !ENDTIME! LSS %STARTTIME% set set /A DURATION=%STARTTIME%-!ENDTIME!
   
   @rem now break the centiseconds down to hours, minutes, seconds and the remaining centiseconds
   set /A "DURATIONH=!DURATION! / 360000"
   set /A "DURATIONM=(!DURATION! - !DURATIONH!*360000) / 6000"
   set /A "DURATIONS=(!DURATION! - !DURATIONH!*360000 - !DURATIONM!*6000) / 100"
   set /A "DURATIONHS=(!DURATION! - !DURATIONH!*360000 - !DURATIONM!*6000 - !DURATIONS!*100)"
   
   @rem Enforce double-digit format
   if !DURATIONH! LSS 10 set DURATIONH=0!DURATIONH!
   if !DURATIONM! LSS 10 set DURATIONM=0!DURATIONM!
   if !DURATIONS! LSS 10 set DURATIONS=0!DURATIONS!
   if !DURATIONHS! LSS 10 set DURATIONHS=0!DURATIONHS!
   
   @rem Outputing timings
   echo STARTTIME: %STARTTIME% centiseconds
   echo ENDTIME: !ENDTIME! centiseconds
   echo DURATION: !DURATION! in centiseconds
   echo Elapsed time: !DURATIONH!:!DURATIONM!:!DURATIONS!.!DURATIONHS!

  
)
endlocal