45
votes

How can I get the difference between two times in a Batch file? Because I want to print it in an HTML file.

I thought this would be possible, but it isn't.

Set "tijd=%time%"
echo %tijd%
echo %time%-%tijd%

Results:

11:07:48,85
11:16:58,99-11:07:48,85

But what I want is:

00:09:10,14

Or 9 minutes and 10 seconds or 550 seconds

11
While it is possible (just search for date/time math in batch, honestly) you shouldn't do so. And I probably shouldn't even ask why a batch file is involved in serving HTML content, I guess.Joey
Why I shouldn't do so? I do serving HTML because I deploy some plugins and the only way to look if the were succesful is to search through the logfile on the word 'succesful'.. And ofcourse I want feedback because it are more then 100 plugins. So I can see witch were succesful and witch failed. Have you any better method?Danny Gloudemans
Why use PowerShell if it is also Possible in a batch file? I can use a batchfile in Windows 7, Vista, XP without installing anything. Powershell is only 'standard' on Windows 7. On the other OS's I need to install it.. It will cost more time, while it is possible in a batch file..Danny Gloudemans
I agree with Joey, don't write production processes in batch (and I'm a batch fanatic!), it has to much limitations and it's hard to implement complex tasks. I would choose phython/perl or some real language that will work independent of MS (that ensures it will still work in three years) and you can switch even to linuxjeb
I'm using it for testing of the builds where correct. Afterwards I will delete them. It is only a test if they deploy. When they are I will put a Succesful in the HTML file, when it fails I will put a Failed in the HTML file. Then I will delete the plugin. And so for all the plugins. It is not for production or something, it is only to see if it works. And I have now a batch file and it works very nice. So I don't understand why I should go to Powershell or anything other?Danny Gloudemans

11 Answers

69
votes
@echo off

rem Get start time:
for /F "tokens=1-4 delims=:.," %%a in ("%time%") do (
   set /A "start=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100"
)

rem Any process here...

rem Get end time:
for /F "tokens=1-4 delims=:.," %%a in ("%time%") do (
   set /A "end=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100"
)

rem Get elapsed time:
set /A elapsed=end-start

rem Show elapsed time:
set /A hh=elapsed/(60*60*100), rest=elapsed%%(60*60*100), mm=rest/(60*100), rest%%=60*100, ss=rest/100, cc=rest%%100
if %mm% lss 10 set mm=0%mm%
if %ss% lss 10 set ss=0%ss%
if %cc% lss 10 set cc=0%cc%
echo %hh%:%mm%:%ss%,%cc%

EDIT 2017-05-09: Shorter method added

I developed a shorter method to get the same result, so I couldn't resist to post it here. The two for commands used to separate time parts and the three if commands used to insert leading zeros in the result are replaced by two long arithmetic expressions, that could even be combined into a single longer line.

The method consists in directly convert a variable with a time in "HH:MM:SS.CC" format into the formula needed to convert the time to centiseconds, accordingly to the mapping scheme given below:

       HH        :      MM        :      SS        .       CC

(((10  HH  %%100)*60+1  MM  %%100)*60+1  SS  %%100)*100+1  CC  %%100

That is, insert (((10 at beginning, replace the colons by %%100)*60+1, replace the point by %%100)*100+1 and insert %%100 at end; finally, evaluate the resulting string as an arithmetic expression. In the time variable there are two different substrings that needs to be replaced, so the conversion must be completed in two lines. To get an elapsed time, use (endTime)-(startTime) expression and replace both time strings in the same line.

EDIT 2017/06/14: Locale independent adjustment added

EDIT 2020/06/05: Pass-over-midnight adjustment added

@echo off
setlocal EnableDelayedExpansion

set "startTime=%time: =0%"

set /P "=Any process here..."

set "endTime=%time: =0%"



rem Get elapsed time:
set "end=!endTime:%time:~8,1%=%%100)*100+1!"  &  set "start=!startTime:%time:~8,1%=%%100)*100+1!"
set /A "elap=((((10!end:%time:~2,1%=%%100)*60+1!%%100)-((((10!start:%time:~2,1%=%%100)*60+1!%%100), elap-=(elap>>31)*24*60*60*100"

rem Convert elapsed time to HH:MM:SS:CC format:
set /A "cc=elap%%100+100,elap/=100,ss=elap%%60+100,elap/=60,mm=elap%%60+100,hh=elap/60+100"

echo Start:    %startTime%
echo End:      %endTime%
echo Elapsed:  %hh:~1%%time:~2,1%%mm:~1%%time:~2,1%%ss:~1%%time:~8,1%%cc:~1%

You may review a detailed explanation of this method at this answer.

43
votes

As answered here: How can I use a Windows batch file to measure the performance of console application?

Below batch "program" should do what you want. Please note that it outputs the data in centiseconds instead of milliseconds. The precision of the used commands is only centiseconds.

Here is an example output:

STARTTIME: 13:42:52,25
ENDTIME: 13:42:56,51
STARTTIME: 4937225 centiseconds
ENDTIME: 4937651 centiseconds
DURATION: 426 in centiseconds
00:00:04,26

Here is the batch script:

@echo off
setlocal

rem The format of %TIME% is HH:MM:SS,CS for example 23:59:59,99
set STARTTIME=%TIME%

rem here begins the command you want to measure
dir /s > nul
rem here ends the command you want to measure

set ENDTIME=%TIME%

rem output as time
echo STARTTIME: %STARTTIME%
echo ENDTIME: %ENDTIME%

rem convert STARTTIME and ENDTIME 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)
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 we might have measured the time inbetween days
if %ENDTIME% LSS %STARTTIME% set set /A DURATION=%STARTTIME%-%ENDTIME%

rem now break the centiseconds down to hors, 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 some formatting
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
echo STARTTIME: %STARTTIME% centiseconds
echo ENDTIME: %ENDTIME% centiseconds
echo DURATION: %DURATION% in centiseconds
echo %DURATIONH%:%DURATIONM%:%DURATIONS%,%DURATIONHS%

endlocal
goto :EOF
22
votes

A re-hash of Aacini's code because most likely you are going to set the start time as a variable and want to save that data for output:

    @echo off

    rem ******************  MAIN CODE SECTION
    set STARTTIME=%TIME%

    rem Your code goes here (remove the ping line)
    ping -n 4 -w 1 127.0.0.1 >NUL

    set ENDTIME=%TIME%

    rem ******************  END MAIN CODE SECTION


    rem Change formatting for the start and end times
    for /F "tokens=1-4 delims=:.," %%a in ("%STARTTIME%") do (
       set /A "start=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100"
    )

    for /F "tokens=1-4 delims=:.," %%a in ("%ENDTIME%") do ( 
       IF %ENDTIME% GTR %STARTTIME% set /A "end=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100" 
       IF %ENDTIME% LSS %STARTTIME% set /A "end=((((%%a+24)*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100" 
    )

    rem Calculate the elapsed time by subtracting values
    set /A elapsed=end-start

    rem Format the results for output
    set /A hh=elapsed/(60*60*100), rest=elapsed%%(60*60*100), mm=rest/(60*100), rest%%=60*100, ss=rest/100, cc=rest%%100
    if %hh% lss 10 set hh=0%hh%
    if %mm% lss 10 set mm=0%mm%
    if %ss% lss 10 set ss=0%ss%
    if %cc% lss 10 set cc=0%cc%

    set DURATION=%hh%:%mm%:%ss%,%cc%

    echo Start    : %STARTTIME%
    echo Finish   : %ENDTIME%
    echo          ---------------
    echo Duration : %DURATION% 

Output:

    Start    : 11:02:45.92
    Finish   : 11:02:48.98
             ---------------
    Duration : 00:00:03,06
3
votes

If you do not mind using powershell within batch script:

@echo off
set start_date=%date% %time%
:: Simulate some type of processing using ping
ping 127.0.0.1  
set end_date=%date% %time%
powershell -command "&{$start_date1 = [datetime]::parse('%start_date%'); $end_date1 = [datetime]::parse('%date% %time%'); echo (-join('Duration in seconds: ', ($end_date1 - $start_date1).TotalSeconds)); }"
2
votes

Based on previous answers, here are reusable "procedures" and a usage example for calculating the elapsed time:

@echo off
setlocal

set starttime=%TIME%
echo Start Time: %starttime%

REM ---------------------------------------------
REM --- PUT THE CODE YOU WANT TO MEASURE HERE ---
REM ---------------------------------------------

set endtime=%TIME%
echo End Time: %endtime%
call :elapsed_time %starttime% %endtime% duration
echo Duration: %duration%

endlocal
echo on & goto :eof

REM --- HELPER PROCEDURES ---

:time_to_centiseconds
:: %~1 - time
:: %~2 - centiseconds output variable
setlocal
set _time=%~1
for /F "tokens=1-4 delims=:.," %%a in ("%_time%") do (
   set /A "_result=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100"
)
endlocal & set %~2=%_result%
goto :eof

:centiseconds_to_time
:: %~1 - centiseconds
:: %~2 - time output variable
setlocal
set _centiseconds=%~1
rem now break the centiseconds down to hors, minutes, seconds and the remaining centiseconds
set /A _h=%_centiseconds% / 360000
set /A _m=(%_centiseconds% - %_h%*360000) / 6000
set /A _s=(%_centiseconds% - %_h%*360000 - %_m%*6000) / 100
set /A _hs=(%_centiseconds% - %_h%*360000 - %_m%*6000 - %_s%*100)
rem some formatting
if %_h% LSS 10 set _h=0%_h%
if %_m% LSS 10 set _m=0%_m%
if %_s% LSS 10 set _s=0%_s%
if %_hs% LSS 10 set _hs=0%_hs%
set _result=%_h%:%_m%:%_s%.%_hs%
endlocal & set %~2=%_result%
goto :eof

:elapsed_time
:: %~1 - time1 - start time
:: %~2 - time2 - end time
:: %~3 - elapsed time output
setlocal
set _time1=%~1
set _time2=%~2
call :time_to_centiseconds %_time1% _centi1
call :time_to_centiseconds %_time2% _centi2
set /A _duration=%_centi2%-%_centi1%
call :centiseconds_to_time %_duration% _result
endlocal & set %~3=%_result%
goto :eof
2
votes

Fixed Gynnad's leading 0 Issue. I fixed it with the two Lines

SET STARTTIME=%STARTTIME: =0%
SET ENDTIME=%ENDTIME: =0%

Full Script ( CalculateTime.cmd ):

@ECHO OFF

:: F U N C T I O N S

:__START_TIME_MEASURE
SET STARTTIME=%TIME%
SET STARTTIME=%STARTTIME: =0%
EXIT /B 0

:__STOP_TIME_MEASURE
SET ENDTIME=%TIME%
SET ENDTIME=%ENDTIME: =0%
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)
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)
SET /A DURATION=%ENDTIME%-%STARTTIME%
IF %DURATION% == 0 SET TIMEDIFF=00:00:00,00 && EXIT /B 0
IF %ENDTIME% LSS %STARTTIME% SET /A DURATION=%STARTTIME%-%ENDTIME%
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)
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%
SET TIMEDIFF=%DURATIONH%:%DURATIONM%:%DURATIONS%,%DURATIONHS%
EXIT /B 0

:: U S A G E

:: Start Measuring
CALL :__START_TIME_MEASURE

:: Print Message on Screen without Linefeed
ECHO|SET /P=Execute Job... 

:: Some Time pending Jobs here
:: '> NUL 2>&1' Dont show any Messages or Errors on Screen
MyJob.exe > NUL 2>&1

:: Stop Measuring
CALL :__STOP_TIME_MEASURE

:: Finish the Message 'Execute Job...' and print measured Time
ECHO [Done] (%TIMEDIFF%)

:: Possible Result
:: Execute Job... [Done] (00:02:12,31)
:: Between 'Execute Job... ' and '[Done] (00:02:12,31)' the Job will be executed
2
votes

Aacini's latest code showcases an awesome variable substitution method.
It's a shame it's not Regional format proof - it fails on so many levels.
Here's a short fix that keeps the substitution+math method intact:

@echo off
setlocal EnableDelayedExpansion

set "startTime=%time: =0%" & rem AveYo: fix single digit hour

set /P "=Any process here..."

set "endTime=%time: =0%" & rem AveYo: fix single digit hour

rem Aveyo: Regional format fix with just one aditional line
for /f "tokens=1-3 delims=0123456789" %%i in ("%endTime%") do set "COLON=%%i" & set "DOT=%%k" 

rem Get elapsed time:
set "end=!endTime:%DOT%=%%100)*100+1!" & set "start=!startTime:%DOT%=%%100)*100+1!"
set /A "elap=((((10!end:%COLON%=%%100)*60+1!%%100)-((((10!start:%COLON%=%%100)*60+1!%%100)"

rem Aveyo: Fix 24 hours 
set /A "elap=!elap:-=8640000-!"

rem Convert elapsed time to HH:MM:SS:CC format:
set /A "cc=elap%%100+100,elap/=100,ss=elap%%60+100,elap/=60,mm=elap%%60+100,hh=elap/60+100"

echo Start:    %startTime%
echo End:      %endTime%
echo Elapsed:  %hh:~1%%COLON%%mm:~1%%COLON%%ss:~1%%DOT%%cc:~1% & rem AveYo: display as regional
pause

*

"Lean and Mean" TIMER with Regional format, 24h and mixed input support
Adapting Aacini's substitution method body, no IF's, just one FOR (my regional fix)

1: File timer.bat placed somewhere in %PATH% or the current dir

@echo off & rem :AveYo: compact timer function with Regional format, 24-hours and mixed input support
if not defined timer_set (if not "%~1"=="" (call set "timer_set=%~1") else set "timer_set=%TIME: =0%") & goto :eof
(if not "%~1"=="" (call set "timer_end=%~1") else set "timer_end=%TIME: =0%") & setlocal EnableDelayedExpansion
for /f "tokens=1-6 delims=0123456789" %%i in ("%timer_end%%timer_set%") do (set CE=%%i&set DE=%%k&set CS=%%l&set DS=%%n)
set "TE=!timer_end:%DE%=%%100)*100+1!"     & set "TS=!timer_set:%DS%=%%100)*100+1!"
set/A "T=((((10!TE:%CE%=%%100)*60+1!%%100)-((((10!TS:%CS%=%%100)*60+1!%%100)" & set/A "T=!T:-=8640000-!"
set/A "cc=T%%100+100,T/=100,ss=T%%60+100,T/=60,mm=T%%60+100,hh=T/60+100"
set "value=!hh:~1!%CE%!mm:~1!%CE%!ss:~1!%DE%!cc:~1!" & if "%~2"=="" echo/!value!
endlocal & set "timer_end=%value%" & set "timer_set=" & goto :eof

Usage:
timer & echo start_cmds & timeout /t 3 & echo end_cmds & timer
timer & timer "23:23:23,00"
timer "23:23:23,00" & timer
timer "13.23.23,00" & timer "03:03:03.00"
timer & timer "0:00:00.00" no & cmd /v:on /c echo until midnight=!timer_end!
Input can now be mixed, for those unlikely, but possible time format changes during execution

2: Function :timer bundled with the batch script (sample usage below):

@echo off
set "TIMER=call :timer" & rem short macro
echo.
echo EXAMPLE:
call :timer
timeout /t 3 >nul & rem Any process here..
call :timer
echo.
echo SHORT MACRO:
%TIMER% & timeout /t 1 & %TIMER% 
echo.
echo TEST INPUT:
set "start=22:04:04.58"
set "end=04.22.44,22"
echo %start% ~ start & echo %end% ~ end
call :timer "%start%"
call :timer "%end%"
echo.
%TIMER% & %TIMER% "00:00:00.00" no 
echo UNTIL MIDNIGHT: %timer_end%
echo.
pause 
exit /b

:: to test it, copy-paste both above and below code sections

rem :AveYo: compact timer function with Regional format, 24-hours and mixed input support 
:timer Usage " call :timer [input - optional] [no - optional]" :i Result printed on second call, saved to timer_end 
if not defined timer_set (if not "%~1"=="" (call set "timer_set=%~1") else set "timer_set=%TIME: =0%") & goto :eof
(if not "%~1"=="" (call set "timer_end=%~1") else set "timer_end=%TIME: =0%") & setlocal EnableDelayedExpansion
for /f "tokens=1-6 delims=0123456789" %%i in ("%timer_end%%timer_set%") do (set CE=%%i&set DE=%%k&set CS=%%l&set DS=%%n)
set "TE=!timer_end:%DE%=%%100)*100+1!"     & set "TS=!timer_set:%DS%=%%100)*100+1!"
set/A "T=((((10!TE:%CE%=%%100)*60+1!%%100)-((((10!TS:%CS%=%%100)*60+1!%%100)" & set/A "T=!T:-=8640000-!"
set/A "cc=T%%100+100,T/=100,ss=T%%60+100,T/=60,mm=T%%60+100,hh=T/60+100"
set "value=!hh:~1!%CE%!mm:~1!%CE%!ss:~1!%DE%!cc:~1!" & if "%~2"=="" echo/!value!
endlocal & set "timer_end=%value%" & set "timer_set=" & goto :eof
2
votes

Here is my attempt to measure time difference in batch.

It respects the regional format of %TIME% without taking any assumptions on type of characters for time and decimal separators.

The code is commented but I will also describe it here.

It is flexible so it can also be used to normalize non-standard time values as well

The main function :timediff

:: timediff
:: Input and output format is the same format as %TIME%
:: If EndTime is less than StartTime then:
::   EndTime will be treated as a time in the next day
::   in that case, function measures time difference between a maximum distance of 24 hours minus 1 centisecond
::   time elements can have values greater than their standard maximum value ex: 12:247:853.5214
::   provided than the total represented time does not exceed 24*360000 centiseconds
::   otherwise the result will not be meaningful.
:: If EndTime is greater than or equals to StartTime then:
::   No formal limitation applies to the value of elements,
::   except that total represented time can not exceed 2147483647 centiseconds.

:timediff <outDiff> <inStartTime> <inEndTime>
(
    setlocal EnableDelayedExpansion
    set "Input=!%~2! !%~3!"
    for /F "tokens=1,3 delims=0123456789 " %%A in ("!Input!") do set "time.delims=%%A%%B "
)
for /F "tokens=1-8 delims=%time.delims%" %%a in ("%Input%") do (
    for %%A in ("@h1=%%a" "@m1=%%b" "@s1=%%c" "@c1=%%d" "@h2=%%e" "@m2=%%f" "@s2=%%g" "@c2=%%h") do (
        for /F "tokens=1,2 delims==" %%A in ("%%~A") do (
            for /F "tokens=* delims=0" %%B in ("%%B") do set "%%A=%%B"
        )
    )
    set /a "@d=(@h2-@h1)*360000+(@m2-@m1)*6000+(@s2-@s1)*100+(@c2-@c1), @sign=(@d>>31)&1, @d+=(@sign*24*360000), @h=(@d/360000), @d%%=360000, @m=@d/6000, @d%%=6000, @s=@d/100, @c=@d%%100"
)
(
    if %@h% LEQ 9 set "@h=0%@h%"
    if %@m% LEQ 9 set "@m=0%@m%"
    if %@s% LEQ 9 set "@s=0%@s%"
    if %@c% LEQ 9 set "@c=0%@c%"
)
(
    endlocal
    set "%~1=%@h%%time.delims:~0,1%%@m%%time.delims:~0,1%%@s%%time.delims:~1,1%%@c%"
    exit /b
)

Example:

@echo off
setlocal EnableExtensions
set "TIME="

set "Start=%TIME%"
REM Do some stuff here...
set "End=%TIME%"

call :timediff Elapsed Start End
echo Elapsed Time: %Elapsed%

pause
exit /b

:: put the :timediff function here


Explanation of the :timediff function:
function prototype  :timediff <outDiff> <inStartTime> <inEndTime>

Input and output format is the same format as %TIME%

It takes 3 parameters from left to right:

Param1: Name of the environment variable to save the result to.
Param2: Name of the environment variable to be passed to the function containing StartTime string
Param3: Name of the environment variable to be passed to the function containing EndTime string

If EndTime is less than StartTime then:

    EndTime will be treated as a time in the next day
    in that case, the function measures time difference between a maximum distance of 24 hours minus 1 centisecond
    time elements can have values greater than their standard maximum value ex: 12:247:853.5214
    provided than the total represented time does not exceed 24*360000 centiseconds or (24:00:00.00) otherwise the result will not be meaningful.
If EndTime is greater than or equals to StartTime then:
    No formal limitation applies to the value of elements,
    except that total represented time can not exceed 2147483647 centiseconds.


More examples with literal and non-standard time values
    Literal example with EndTime less than StartTime:
@echo off
setlocal EnableExtensions

set "start=23:57:33,12"
set "end=00:02:19,41"

call :timediff dif start end

echo Start Time: %start%
echo End Time:   %end%
echo,
echo Difference: %dif%
echo,

pause
exit /b

:: put the :timediff function here
    Output:
Start Time: 23:57:33,12
End Time:   00:02:19,41

Difference: 00:04:46,29
    Normalize non-standard time:
@echo off
setlocal EnableExtensions

set "start=00:00:00.00"
set "end=27:2457:433.85935"

call :timediff normalized start end

echo,
echo %end% is equivalent to %normalized%
echo,

pause
exit /b

:: put the :timediff function here
    Output:

27:2457:433.85935 is equivalent to 68:18:32.35

    Last bonus example:
@echo off
setlocal EnableExtensions

set "start=00:00:00.00"
set "end=00:00:00.2147483647"

call :timediff normalized start end

echo,
echo 2147483647 centiseconds equals to %normalized%
echo,

pause
exit /b

:: put the :timediff function here
    Output:

2147483647 centiseconds equals to 5965:13:56.47

1
votes

Using a single function with the possibility of custom unit of measure or formatted. Each time the function is called without parameters we restarted the initial time.

@ECHO OFF

ECHO.
ECHO DEMO timer function
ECHO --------------------

SET DELAY=4

:: First we call the function without any parameters to set the starting time
CALL:timer

:: We put some code we want to measure
ECHO.
ECHO Making some delay, please wait...
ECHO.

ping -n %DELAY% -w 1 127.0.0.1 >NUL

:: Now we call the function again with the desired parameters

CALL:timer elapsed_time

ECHO by Default : %elapsed_time%

CALL:timer elapsed_time "s"

ECHO in Seconds : %elapsed_time%

CALL:timer elapsed_time "anything"

ECHO Formatted  : %elapsed_time%  (HH:MM:SS.CS)

ECHO.
PAUSE


:: Elapsed Time Function
:: -----------------------------------------------------------------------
:: The returned value is in centiseconds, unless you enter the parameters 
:: to be in another unit of measure or with formatted
::
::  Parameters:
::             <return>     the returned value
::             [formatted]  s (for seconds), m (for minutes), h (for hours)
::                          anything else for formatted output
:: -----------------------------------------------------------------------
:timer <return> [formatted]
    SetLocal EnableExtensions EnableDelayedExpansion

    SET _t=%time%
    SET _t=%_t::0=: %
    SET _t=%_t:,0=, %
    SET _t=%_t:.0=. %
    SET _t=%_t:~0,2% * 360000 + %_t:~3,2% * 6000 + %_t:~6,2% * 100 + %_t:~9,2%
    SET /A _t=%_t%

    :: If we call the function without parameters is defined initial time
    SET _r=%~1
    IF NOT DEFINED _r (
        EndLocal & SET TIMER_START_TIME=%_t% & GOTO :EOF
    )

    SET /A _t=%_t% - %TIMER_START_TIME%

    :: In the case of wanting a formatted output
    SET _f=%~2
    IF DEFINED _f (

        IF "%_f%" == "s" (

            SET /A "_t=%_t% / 100"

        ) ELSE (
            IF "%_f%" == "m" (

                SET /A "_t=%_t% / 6000"

            ) ELSE (

                IF "%_f%" == "h" (

                    SET /A "_t=%_t% / 360000"

                ) ELSE (

                    SET /A "_h=%_t% / 360000"
                    SET /A "_m=(%_t% - !_h! * 360000) / 6000"
                    SET /A "_s=(%_t% - !_h! * 360000 - !_m! * 6000) / 100"
                    SET /A "_cs=(%_t% - !_h! * 360000 - !_m! * 6000 - !_s! * 100)"

                    IF !_h! LSS 10 SET "_h=0!_h!"
                    IF !_m! LSS 10 SET "_m=0!_m!"
                    IF !_s! LSS 10 SET "_s=0!_s!"
                    IF !_cs! LSS 10 SET "_cs=0!_cs!"
                    SET "_t=!_h!:!_m!:!_s!.!_cs!"
                    SET "_t=!_t:00:=!"

                )
            )
        )
    )

    EndLocal & SET %~1=%_t%
goto :EOF

A test with a delay of 94 sec

DEMO timer function
--------------------

Making some delay, please wait...

by Default : 9404
in Seconds : 94
Formatted  : 01:34.05  (HH:MM:SS.CS)

Presione una tecla para continuar . . .
0
votes

CMD doesn't have time arithmetic. The following code, however gives a workaround:

set vid_time=11:07:48
set srt_time=11:16:58

REM Get time difference
set length=%vid_time%
for /f "tokens=1-3 delims=:" %i in ("%length%") do (
set /a h=%i*3600
set /a m=%j*60
set /a s=%k
)
set /a t1=!h!+!m!+!s!

set length=%srt_time%
for /f "tokens=1-3 delims=:" %i in ("%length%") do (
set /a h=%i*3600
set /a m=%j*60
set /a s=%k
)
set /a t2=!h!+!m!+!s!
cls
set /a diff=!t2!-!t1!

Above code gives difference in seconds. To display in hh:mm:ss format, code below:

set ss=!diff!
set /a hh=!ss!/3600 >nul
set /a mm="(!ss!-3600*!hh!)/60" >nul
set /a ss="(!ss!-3600*!hh!)-!mm!*60" >nul
set "hh=0!hh!" & set "mm=0!mm!" & set "ss=0!ss!"
echo|set /p=!hh:~-2!:!mm:~-2!:!ss:~-2! 
0
votes
@echo off

set START=23:05:15
set END=07:02:05

set options="tokens=1-4 delims=:."
for /f %options% %%a in ("%start%") 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 ("%end%") 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 %% 100
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 %hours% lss 0 set /a hours = 24%hours%
if %mins% lss 0 set /a hours = %hours% - 1 & set /a mins = 60%mins%
if %secs% lss 0 set /a mins = %mins% - 1 & set /a secs = 60%secs%
if %ms% lss 0 set /a secs = %secs% - 1 & set /a ms = 100%ms%
if 1%ms% lss 100 set ms=0%ms%

set hours=0%hours%
set hours=%hours:~-2%
set mins=0%mins%
set mins=%mins:~-2%
set secs=0%secs%
set secs=%secs:~-2%

set /a totalsecs = %hours%*3600 + %mins%*60 + %secs% 

echo Command took %hours%:%mins%:%secs%.%ms% (%totalsecs%.%ms%s total)

echo %date%   %start% - %end% ( %hours%:%mins%:%secs% )

pause