Arithmetic operations with HH:MM:SS times in batch file

@echo off
setlocal

set /p "StartPosition=Start position (HH:MM:SS): "
set /p "EndPosition=End position (HH:MM:SS):   "

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

echo Duration=%hh:~1%:%mm:~1%:%ss:~1%

EDIT: Some explanations added

This program use the usual method to convert a time in HH:MM:SS format into a number of seconds via the standard formula: seconds = (HH*60+MM)*60+SS. However, the set /A command consider the numbers that start with 0 as written in octal base, and hence 08 and 09 would be invalid octal numbers. To avoid this problem, a digit 1 is placed before expand the number and a 100 is subtracted after, so if HH=08 then 1%HH%-100 correctly gives 8; that is:

set /A seconds = ((1%HH%-100)*60+1%MM%-100)*60+1%SS%-100

There are several methods to split a time given in HH:MM:SS format into its three parts. For example, if we take set EndPosition=HH:MM:SS as base, then we may use a for /F command this way:

for /F "tokens=1-3 delims=:" %%a in ("%EndPosition%") do (
   set /A "seconds=((1%%a-100)*60+1%%b-100)*60+1%%c-100"
)

In this program a different method is used. If we match the original EndPosition=HH:MM:SS string with the desired formula, we may construct this mapping scheme:

     HH       :      MM       :      SS

((1  HH  -100)*60+1  MM  -100)*60+1  SS  -100

In other words: if we replace the colons of the original string by -100)*60+1 and insert ((1 at beginning and -100 at end, we obtain the desired formula; that is:

set /A "seconds=((1%EndPosition::=-100)*60+1%-100"

This is a very efficient method that even allows to replace both EndPosition and StartPosition strings in the same formula (enclosing both parts in parentheses) and directly subtract them:

set /A "ss=(((1%EndPosition::=-100)*60+1%-100)-(((1%StartPosition::=-100)*60+1%-100)"

You may cancel the @echo off command and run the program to review the exact formula that is evaluated after the values of the variables are replaced. For example, when StartPosition=00:10:30 and EndPosition=00:10:40, this is the expression that is evaluated:

set /A "ss=(((100-100)*60+110-100)*60+140-100)-(((100-100)*60+110-100)*60+130-100)"

Just to complete this description, this is the “standard” way to evaluate the same formula using a for /F command:

for /F "tokens=1-6 delims=:" %%a in ("%EndPosition%:%StartPosition%") do (
   set /A "ss=(((1%%a-100)*60+1%%b-100)*60+1%%c-100)-(((1%%d-100)*60+1%%e-100)*60+1%%f-100)"
)

The opposite conversion from number of seconds to HH:MM:SS parts is straightforward:

HH=SS/3600, rest=SS%3600, MM=rest/60, SS=rest%60

However, each part in the result must be displayed with two digits, but this formatting may be achieved in a very simple way. Instead of insert three if commands that check if each part is less than 10 and insert a padding zero in such a case, the number 100 is just added to the parts (converting an 8 into 108, for example), and when each part is displayed the first digit is omitted (so just 08 is shown). This is a very efficient method to format numbers that may be performed in the same set /A command used to obtain the parts. For example:

set /A "hh=ss/3600+100,ss%%=3600,mm=ss/60+100,ss=ss%%60+100"

echo Duration=%hh:~1%:%mm:~1%:%ss:~1%

In this way, the conversion of two times into two number of seconds, their subtraction and the opposite conversion and formatting to HH:MM:SS is performed in two SET /A commands, that even may be written in a single, long line.

Output examples:

Start position (HH:MM:SS): 00:10:30
End position (HH:MM:SS):   00:10:40
Duration=00:00:10

Start position (HH:MM:SS): 00:10:45
End position (HH:MM:SS):   00:11:05
Duration=00:00:20

Leave a Comment