In one of my batch scripts I need to calculate the duration of an interval in a video file. First the user is asked to input the start and end times:
set /p StartPosition=Start position (HH:MM:SS):
set /p EndPosition=End position (HH:MM:SS):
Then, I would like the batch script to calculate the duration in between.
How can I subtract %StartPosition%
from %EndPosition%
like this, for example:
00:10:40 - 00:10:30 = 00:00:10
The reason why I can't figure out how to do this is because these numbers are separated by colons.
Edit: This question is different to this question because I do not need the scrip to treat the numbers as time values.
@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