How to solve Time in loop context in CMD

I did my own code to try to calculate a delay when I execute a program within FOR loop. The weakness is that the value %time% is evaluated at the same moment. So I want to ask you, is it possible to change the code to move the 2 blocks of calculations (using SET /A) to separate subroutines. I searched web to this solution with goto, but it is not clear to me how to return back to loop. As the examples which I have found, referred on end of file.

@echo off 
Setlocal EnableDelayedExpansion

FOR /F "tokens=*" %%A IN ('DATE/T') DO FOR %%B IN (%%A) DO SET Today=%%B
ECHO It's %Today% today

CHCP 1250 > NUL

SET tpath=TEMP

for /f "delims=" %%x in (delimiter.ini) do set TAB=%%x

if not exist proxies.ini (
  echo Proxies not Found!
  pause 
exit
)

REM Set array of proxies
FOR /F "eol= tokens=1,2 delims=%TAB%" %%A IN (proxies.ini) DO (
  if "%%A"=="*" (
    SET asterisk=1
    SET http_proxy=%%B
    SET t0=%time%
    wget.exe http://www.nasa.gov/images/content/297522main_image_1244_946-710.jpg 
    SET t1=%time%
    REM FOR /F %%A IN ('TIME/T') DO SET t1=%%A

    echo !t0!
    SET /a s = !t0:~6,2!*100
    SET /a c = !t0:~9,2!
    SET /a c = "!c!-(!c!/10)*4"
    SET /a d1 = !s!+!c!
    echo !s!+!c! = !d1!
    echo !d1!

    echo !t1!
    SET /a s = !t1:~6,2!*100
    SET /a c = !t1:~9,2!
    SET /a c = "!c!-(!c!/10)*4"
    SET /a d2 = !s!+!c!
    echo !s!+!c! = !d2!
    SET /a delay = !d1!-!d2!   
    echo Delay:!delay!

   pause
   Echo Working proxy ... !proxy!     
  )
)


pause

Edit This is the second test, before dBenham posted his much more better solution:

@echo off 
Setlocal EnableDelayedExpansion

FOR /F "tokens=*" %%A IN ('DATE/T') DO FOR %%B IN (%%A) DO SET Today=%%B
ECHO It's %Today% today

CHCP 1250 > NUL

SET tpath=TEMP

for /f "delims=" %%x in (delimiter.ini) do set TAB=%%x

if not exist proxies.ini (
  echo Proxies not found. 
  pause 
exit
)

REM Set array of proxies
FOR /F "eol= tokens=1,2 delims=%TAB%" %%A IN (proxies.ini) DO (
  if "%%A"=="*" (
    SET asterisk=1
    SET http_proxy=%%B
    SET t0=!time!
    wget.exe http://www.nasa.gov/images/content/297522main_image_1244_946-710.jpg 
    call :setTime !t0! !time!
    SET t1=!time!

:setTime
   Setlocal EnableDelayedExpansion
    SET t0=%1
    SET t1=%2
    echo !t0! !t1!
    pause
    SET /a m1 = !t0:~3,2!
    SET /a s1 = !t0:~6,2!
    SET /a s = !s1!*100
    SET /a c = !t0:~9,2!
    SET /a c = "!c!-((!c!/10)*4)"
    SET /a d1 = !s!+!c!
    echo !s!+!c! = !d1!
    echo !d1!

    echo !t1!
    SET /a m2 = !t1:~3,2!
    SET /a s2 = !t1:~6,2!
    if "!m2!" GTR "!m1!" (
      IF "!s2!" LSS "!s1!" (
          REM e.g. s1=20, s2=04 => 
          SET /a s2_cor = 60-!s1!+!s2!
          echo Correction: s2: !s2!
          SET /a s2_cor = "!s2!+60*(!m2!-!m1!)" 
      ) ELSE (
          SET /a s2_cor = "!s2!+60*(!m2!-!m1!-1)"
      )

      SET /a s2 = "!s2!+!s2_cor!"
    )

    SET /a s = !s2!*100    
    echo s2:!s2! , s:!s!    
    SET /a c = !t1:~9,2!
    SET /a c = "!c!-((!c!/10)*4)"
    SET /a d2 = !s!+!c!
    echo !s!+!c! = !d2!
    SET /a delay = !d2!-!d1!   
    echo Delay:!delay!
   pause
   endlocal
exit /b

   Echo Working proxy ... !proxy!     
  )
)

if NOT !asterisk!==1 (
 echo .
 echo Asterix not set
 echo .
 exit
)
pause

Answers


Joey diagnosed one of your problems. But your computation of the elapsed time has many problems.

  • As Joey pointed out, you need to use delayed expansion within your loop

  • You should subtract Time1 from Time2. You are doing the opposite.

  • Your handling of the fractional seconds is simply wrong.

  • You assume the elapsed time will be less than one minute. That may or may not be true. But you erroneously assume you only need to look at the seconds portion of the time. What if T0=09:59:59.99 and T1=10:00:00.00? The correct result should be 0.01 seconds. The only way to get the correct result is to look at all of the time components. The simplest way to compute the value is to convert each time into the number of centiseconds (1/100 second) past midnight prior to doing any substraction.

  • What if T0=23:59:59.99 and T1=00:00:00.00? The correct result should again be 0.01 seconds. But if you convert both values into centiseconds and then subtract T0 from T1 you will get a negative number. The trick is to add 1 day (24*60*60*100) to the result if the result is negative. That allows the technique to compute any time interval less than 24 hours at any time of day.

  • SET /A interprets any number that starts with 0 as octal notation. So any number greater than 7 is being interpreted incorrectly in your code. Plus values like 08 and 09 are raising errors because 8 and 9 are not valid octal digits. The solution below uses some math tricks to add a 1 digit before each time component to force SET /A to use decimal notation, and then subtracts out the extra time at the end.

Other issues:

  • Most of the time when using SET /A you do not need to expand the variables. For example, if you want to add one to a numeric variable, you can simply use set /A var=var+1, or more concisely set var+=1.

  • I don't think your FOR /F options "eol= tokens=1,2 delims=%TAB%" are doing what you want. I suspect you are attempting to disable the EOL option, but in reality you are setting EOL to a <space> character. The proper way to disable it is to set EOL to one of your DELIM values: "eol=%TAB% tokens=1,2 delims=%TAB%".

Here is the relevent section of your code using some working batch subroutines to compute the elapsed time. The algorithms I used for dealing with the time computations are derived from code found here: http://www.dostips.com/DtCodeFunctions.php#_Toc128586395

There are a lot of advanced batch techniques in the code below. Don't feel bad if much of it doesn't make sense. But you should be able to copy the subroutines into any script you want and compute the elapsed time with ease.

setlocal enableDelayedExpansion
FOR /F "eol= tokens=1,2 delims=%TAB%" %%A IN (proxies.ini) DO (
  if "%%A"=="*" (
    SET asterisk=1
    SET http_proxy=%%B
    SET t0=!time!
    wget.exe http://www.nasa.gov/images/content/297522main_image_1244_946-710.jpg
    SET t1=!time!

    call :diffTime t0 t1 Delay
    call :diffTime /f t0 t1 FormattedDelay
    echo Delay=!Delay!
    echo FormattedDelay=!FormattedDelay!

    pause
    Echo Working proxy ... !proxy!
  )
)
exit /b

:diffTime  [/F]  StartTimeVar  EndTimeVar  [ReturnVar]
::
:: Compute the elapsed time between the time values stored in
:: variables StartTimeVar and EndTimeVar. The value is returned
:: in units of centiseconds (1/100 second). If the /F option is
:: specified then the result is formatted as HH:MM:SS.DD
::
:: The result is returned in variable ReturnVar.
::
:: If ReturnVar is not specified then simply echo the result.
::
  setlocal enableDelayedExpansion
  set "diffTime.formatTime="
  if /i "%~1"=="/F" (
    set diffTime.formatTime=1
    shift /1
  )
  call :parseTime %1 diffTime.t1
  call :parseTime %2 diffTime.t2
  set /a "diff=diffTime.t2-diffTime.t1"
  if %diff% lss 0 set /a "diff+=24*60*60*100"
  if defined diffTime.formatTime (
    set /a "DD=diff, HH=DD/360000, DD-=HH*360000, MM=DD/6000, DD-=MM*6000, SS=DD/100, DD-=SS*100"%\n%
    if "!HH:~1!"=="" set "HH=0!HH!"
    if "!MM:~1!"=="" set "MM=0!MM!"
    if "!SS:~1!"=="" set "SS=0!SS!"
    if "!DD:~1!"=="" set "DD=0!DD!"
    set diff=!HH!:!MM!:!SS!.!DD!
  )
  endlocal & if "%~3"=="" (echo %diff%) else set "%~3=%diff%"
exit /b


:parseTime  TimeVar  ReturnVar
::
:: Parse the time value stored in TimeVar and compute the number of centiseconds (1/100 second) past midnight.
:: The result is returned in variable ReturnVar
::
  for /f "tokens=1-4 delims=:.," %%A in ("!%~1: =0!") do set /a "%~2=(((1%%A*60)+1%%B)*60+1%%C)*100+1%%D-36610100"
exit /b

Actually use delayed expansion. Use !time! instead of %time% within the loop. And likewise for all other variables you set and use within the loop.


Need Your Help

How to convert specific NTSTATUS value to the Hresult?

c# winapi

I am know NTSTATUS that i will get in case of specific error, but i got hresult, not ntstatus from pinvoke. So how to convert specific NTSTATUS value to the Hresult.

Generating Javascript from PHP?

php javascript

Are there any libraries or tools specifically designed to help PHP programmers write Javascript? Essentially, converting the PHP logic into Javascript logic. For instance: