0

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!

G. Rab
  • 43
  • 5
  • 1
    We cannot help you without knowing what `echo %TIME%` outputs on your Windows computer with your account. The date/time format depends on the country (region) configured for your account. On my Windows computer with my account is output `18:55:07,22` respectively `5:55:51,16` with a space at beginning for a time before 10 o'clock in the morning. Look on the answers of [Time is set incorrectly after midnight](https://stackoverflow.com/questions/60124351/) for methods to get the current time independent on country/region settings. – Mofi Dec 09 '21 at 17:58
  • 5
    BTW: Running the posted batch file from within a command prompt window results in the error message: `%iter was unexpected at this time.` and showing next the line `for %iter in (1 2 3 4 5) do (`. A loop variable can be only one character like `i`, but not a string like `iter`. The code written by @Aacini works fine on using __delayed__ instead of __immediate__ expansion , i.e. use `set /A "ss=(((1!endTime::=-100)*60+1!-100)-(((1!startTime::=-100)*60+1!-100)"` as long as the time format is suitable (24 hours format) and not run less than 15 seconds before midnight. – Mofi Dec 09 '21 at 18:09
  • @Mofi thanks, I have updated the code accordingly. I have also indicated the time formatting on my computer: HH:MM:SS – G. Rab Dec 09 '21 at 18:46
  • @G.Rab, if you take a look at the first line of your code submission, `set "startTime=%time: =0%"`, that will replace spaces with `0`'s. However if your actual date returned is `HH:MM:SS`, there are no spaces, you'd only get those with `M`, `H`, `m` or `h` _(with `tt`)_. Then `set startTime=%startTime:~0,-3%`, would be removing the last three characters, and if yours was really `HH:MM:SS` you'd be left with `HH:MM`, which I'm fairly sure is not what you wanted. What we specifically wanted to know is the result of `Echo "%TIME%"`, _(replacing the digits with H/HH/h/hh/M/MM/m/mm/SS/ms/tt)_. – Compo Dec 09 '21 at 21:19
  • @Compo Thanks, your comments pointed me towards a solution that works for me. – G. Rab Dec 10 '21 at 11:18

1 Answers1

0

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
G. Rab
  • 43
  • 5
  • Mmm... The _only_ concern in your original code was to use Delayed Expansion in the calculation of `set /A "ss=(((1!endTime::=-100)*60+1!-100)-(((1!startTime::=-100)*60+1!-100)"` (and the _right way_ to adjust for over-midnight intervals via `if !ss! lss 0 set /A ss+=24*60*60`). After that, the original `set /A "hh=ss/3600+100,ss%%=3600,mm=ss/60+100,ss=ss%%60+100"` efficient method to extract individual HH:MM:SS parts (and show they via `!hh:~1!:!mm:~1!:!ss:~1!`) should work... – Aacini Dec 10 '21 at 13:00