Арифметические операции с HH: MM: SS раз в пакетном файле
В одном из моих пакетных скриптов мне нужно рассчитать продолжительность интервала в видеофайле. Сначала пользователю предлагается ввести время начала и окончания:
set /p StartPosition=Start position (HH:MM:SS):
set /p EndPosition=End position (HH:MM:SS):
Затем я хотел бы, чтобы пакет script вычислял продолжительность между ними.
Как я могу вычесть %StartPosition%
из %EndPosition%
следующим образом, например:
00:10:40 - 00:10:30 = 00:00:10
Причина, по которой я не могу понять, как это сделать, состоит в том, что эти числа разделены двоеточиями.
Изменить: этот вопрос отличается от этого вопроса, потому что мне не нужен скрипт для обработки чисел как значений времени.
Ответы
Ответ 1
@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: добавлены некоторые пояснения
Эта программа использует обычный метод для преобразования времени в формате HH: MM: SS на несколько секунд по стандартной формуле: seconds = (HH*60+MM)*60+SS
. Однако команда set /A
рассматривает числа, начинающиеся с 0
, как написано в восьмеричной базе, и, следовательно, 08
и 09
будут недопустимыми восьмеричными числами. Чтобы избежать этой проблемы, перед тем, как развернуть число, помечается цифра 1
, а затем 100
вычитается, поэтому, если HH=08
, то 1%HH%-100
правильно дает 8
; то есть:
set /A seconds = ((1%HH%-100)*60+1%MM%-100)*60+1%SS%-100
Существует несколько способов разделить время, указанное в формате HH: MM: SS, на три части. Например, если мы берем set EndPosition=HH:MM:SS
в качестве базы, то мы можем использовать команду for /F
следующим образом:
for /F "tokens=1-3 delims=:" %%a in ("%EndPosition%") do (
set /A "seconds=((1%%a-100)*60+1%%b-100)*60+1%%c-100"
)
В этой программе используется другой метод. Если мы сопоставим исходную строку EndPosition=HH:MM:SS
с требуемой формулой, мы можем построить эту схему отображения:
HH : MM : SS
((1 HH -100)*60+1 MM -100)*60+1 SS -100
Другими словами: если мы заменим двоеточия исходной строки на -100)*60+1
и вставим ((1
в начале и -100
в конец, мы получим искомую формулу; то есть:
set /A "seconds=((1%EndPosition::=-100)*60+1%-100"
Это очень эффективный метод, который позволяет даже заменять строки EndPosition и StartPosition в той же формуле (включая обе части в круглых скобках) и прямо вычитать их:
set /A "ss=(((1%EndPosition::=-100)*60+1%-100)-(((1%StartPosition::=-100)*60+1%-100)"
Вы можете отменить команду @echo off
и запустить программу для просмотра точной формулы, которая оценивается после замены значений переменных. Например, когда StartPosition=00:10:30
и EndPosition=00:10:40
, это выражение, которое оценивается:
set /A "ss=(((100-100)*60+110-100)*60+140-100)-(((100-100)*60+110-100)*60+130-100)"
Чтобы завершить это описание, это "стандартный" способ оценить ту же формулу с помощью команды for /F
:
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)"
)
Противоположное преобразование из числа секунд в части ЧЧ: ММ: СС является простым:
HH=SS/3600, rest=SS%3600, MM=rest/60, SS=rest%60
Однако каждая часть результата должна отображаться с двумя цифрами, но это форматирование может быть достигнуто очень простым способом. Вместо того, чтобы вставлять три команды if
, которые проверяют, если каждая часть меньше 10 и вставляют нулевой пробел в таком случае, число 100
просто добавляется к частям (преобразование 8
в 108
, для пример), и когда каждая часть отображается, первая цифра опускается (так отображается только 08
). Это очень эффективный способ форматирования чисел, которые могут выполняться в той же команде set /A
, которая используется для получения деталей. Например:
set /A "hh=ss/3600+100,ss%%=3600,mm=ss/60+100,ss=ss%%60+100"
echo Duration=%hh:~1%:%mm:~1%:%ss:~1%
Таким образом, преобразование двух раз в два числа секунд, их вычитание и обратное преобразование и форматирование в HH: MM: SS выполняется в двух командах SET/A, которые даже могут быть записаны в одном, длинная строка.
Примеры вывода:
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
Ответ 2
Это можно сделать в чистой партии анализировать каждое поле как независимую строку, а затем делать арифметику на них. Многие практические решения заходят в какую-то другую программу, чтобы выполнить математику по дате.
Следующий код вызывает PowerShell для использования класса .NET DateTime
для синтаксического анализа для вас.
C:\> set "StartPosition=00:10:30"
C:\> set "EndPosition=00:10:40"
C:\> PowerShell.exe -c "$span=([datetime]'%EndPosition%' - [datetime]'%StartPosition%'); '{0:00}:{1:00}:{2:00}' -f $span.Hours, $span.Minutes, $span.Seconds"
00:00:10
Это выполняет две строки кода PowerShell; один, чтобы преобразовать оба раза в объекты DateTime
и вычесть их, а другой - для вывода результата в указанном вами формате.
Ответ 3
Здесь рабочий прототип:
@echo off
set T1=00:10:45
set T2=00:11:05
set HOUR1=%T1:~,2%
set MIN1=%T1:~3,-3%
set SEC1=%T1:~-2%
set HOUR2=%T2:~,2%
set MIN2=%T2:~3,-3%
set SEC2=%T2:~-2%
set /A TOTAL_SEC1=%HOUR1%*3600+%MIN1%*60+SEC1
set /A TOTAL_SEC2=%HOUR2%*3600+%MIN2%*60+SEC2
set /A DIFF=%TOTAL_SEC2%-%TOTAL_SEC1%
echo %DIFF%
Вывод:
20
Это не полный, но разумный старт.
Ответ 4
Я думаю, @Aacini очистил все здесь. Он достал тебя, прежде чем я сделаю. Но я хочу улучшить его как - используя Для цикла, чтобы сделать код проще.
Примечание: Все после < REM "- комментарий для понимания легко...
Все, что вам нужно сделать, это скопировать его в ваш пакетный файл. И используйте его следующим образом (в вашем основном коде):
Синтаксис: Вызов: время [ваше время 1] [операция] [ваше время 2]
И теперь вы можете применить - любую операцию - в том числе "Добавление, подделка, разделение, умножение";) Функция времени
-------------- Скопировать код ниже ----------
:Time [Start_Time] [Operation] [End_Time]
SetLocal EnableDelayedExpansion
REM Creating a portable Function for your Job. :)
REM Reading Start-time...
For /F "Tokens=1,2,3 Delims=:" %%A in ("%~1") Do (
Set _Start_Hour=%%A
Set _Start_Min=%%B
Set _Start_Sec=%%C
)
REM Reading End-time...
For /F "Tokens=1,2,3 Delims=:" %%A in ("%~3") Do (
Set _End_Hour=%%A
Set _End_Min=%%B
Set _End_Sec=%%C
)
REM Removing leading Zero - if any... 'CMD assumes it as octal - otherwise'
For %%A In (Hour Min Sec) Do (
For %%B In (Start End) Do (
IF /I "!_%%B_%%A:~0,1!" == "0" (Set _%%B_%%A=!_%%B_%%A:~1!)
)
)
REM Applying Operation on the given times.
For %%A In (Hour Min Sec) Do (Set /A _Final_%%A=!_Start_%%A! %~2 !_End_%%A!)
REM Handling a little Exceptional errors! - due to the nature of time (60 sec for a min.)
SET _Extra_Hour=0
SET _Extra_Min=0
REM Two Cases can arise in each part of time...
:Sec_loop
IF %_Final_Sec% GTR 59 (Set /A _Extra_Min+=1 & Set /A _Final_Sec-=60 & Goto :Sec_loop)
IF %_Final_Sec% LSS 0 (Set /A _Extra_Min-=1 & Set /A _Final_Sec+=60 & Goto :Sec_loop)
Set /A _Final_Min+=%_Extra_Min%
:Min_loop
IF %_Final_Min% GTR 59 (Set /A _Extra_Hour+=1 & Set /A _Final_Min-=60 & Goto :Min_loop)
IF %_Final_Min% LSS 0 (Set /A _Extra_Hour-=1 & Set /A _Final_Min+=60 & Goto :Min_loop)
Set /A _Final_Hour+=%_Extra_Hour%
REM Saving Everything into a Single Variable - string.
Set _Final_Time=%_Final_Hour%:%_Final_Min%:%_Final_Sec%
REM Displaying it on the console. ;)
Echo.%_Final_Time%
Goto :EOF
--------------End OF Code----------------------
Вы также можете посетить мой сайт, основанный на пакетном программировании. (www.thebateam.org) Вы найдете много всего там - чтобы помочь вам.:)
Здесь Конечный вывод - Когда я сохранил код в файле ответа .bat