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 valuesLiteral 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
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
27:2457:433.85935 is equivalent to 68:18:32.35
@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
2147483647 centiseconds equals to 5965:13:56.47