Вычислить разницу во времени в пакетном файле Windows

Как я могу получить разницу между двумя файлами в пакетном файле? Потому что я хочу напечатать его в HTML файле.

Я думал, что это возможно, но это не так.

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

Результаты:

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

Но я хочу:

00:09:10,14

Или 9 минут и 10 секунд или 550 секунд

Ответы

Ответ 1

Как сказано здесь: Как я могу использовать пакетный файл Windows для измерения производительности консольного приложения?

Ниже пакетная "программа" должна делать то, что вы хотите. Обратите внимание, что он выводит данные в секундах вместо миллисекунд. Точность используемых команд составляет только секунды.

Вот пример вывода:

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

Вот пакет 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

Ответ 2

@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: Добавлен более короткий метод

Я разработал более короткий метод, чтобы получить тот же результат, поэтому я не мог устоять, чтобы опубликовать его здесь. Две команды for, используемые для разделения временных частей и трех команд if, используемых для вставки начальных нулей в результат, заменяются двумя длинными арифметическими выражениями, которые можно даже объединить в одну длинную строку.

Метод состоит в том, чтобы напрямую преобразовать переменную со временем в формате "HH: MM: SS.CC" в формулу, необходимую для преобразования времени в центрифуги, в соответствии с приведенной ниже схемой отображения:

       HH        :      MM        :      SS        .       CC

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

То есть, вставьте (((10 в начале, замените двоеточия на %%100)*60+1, замените точку на %%100)*100+1 и вставьте %%100 в конец; наконец, оцените полученную строку как арифметическое выражение. В переменной времени есть две разные подстроки, которые необходимо заменить, поэтому преобразование должно быть завершено в две строки. Чтобы получить прошедшее время, используйте выражение (endTime)-(startTime) и замените обе строки времени в одной строке.

РЕДАКТИРОВАТЬ 2017/06/14: Добавлена ​​независимая от локали настройка

@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)"

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%

Вы можете просмотреть подробное объяснение этого метода в этом ответе.

Ответ 3

Повторный хэш кода Aacini, потому что, скорее всего, вы собираетесь установить время начала в качестве переменной и хотите сохранить эти данные для вывода:

    @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 (
       set /A "end=(((%%a*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% 

Вывод:

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

Ответ 4

Основываясь на предыдущих ответах, здесь можно использовать многократные "процедуры" и пример использования для вычисления прошедшего времени:

@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

Ответ 5

Исправлена ​​ошибка Gnnad, ведущая 0 Проблема. Я установил его двумя строками

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

Полный 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

Ответ 6

Вот моя попытка измерить разницу во времени в партии.

Он учитывает региональный формат % TIME%, не принимая каких-либо предположений о типе символов для времени и десятичных разделителей.

Код комментируется, но я также опишу его здесь.

Он гибкий, поэтому его также можно использовать для нормализации нестандартных значений времени.

Основная функция: 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=(@[email protected])*360000+(@[email protected])*6000+(@[email protected])*100+(@[email protected]), @sign=(@d>>31)&1, @d+=(@sign*24*360000), @h=(@d/360000), @d%%=360000, @[email protected]/6000, @d%%=6000, @[email protected]/100, @[email protected]%%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
)

Пример:

@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


Объяснение функции: timediff:
function prototype  :timediff <outDiff> <inStartTime> <inEndTime>

Формат ввода и вывода совпадает с форматом % TIME%

Требуется 3 параметра слева направо:

Param1: имя переменной среды для сохранения результата.
Param2: имя переменной среды для передачи в функцию, содержащую строку StartTime
Param3: имя переменной среды для передачи в функцию, содержащую строку EndTime

Если EndTime меньше чем StartTime, тогда:

  • EndTime будет рассматриваться как время на следующий день
    в этом случае функция измеряет разницу во времени между максимальным расстоянием 24 часа минус 1 сантисекунда
    элементы времени могут иметь значения, превышающие их стандартное максимальное значение, например:
12: 247: 853.5214
при условии, что общее отображаемое время не превышает 24 * 360000 центсекунд или (24: 00: 00.00), иначе результат не будет значимым.Если EndTime больше или равен StartTime, то:
  • Формальные ограничения не применяются к стоимости элементов,
    за исключением того, что общее представленное время не может превышать
2147483647 центсекунд


Еще примеры с буквенными и нестандартными значениями времени Литеральный пример с EndTime меньше чем 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
Нормализовать нестандартное время:
@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

Ответ 7

Использование одной функции с возможностью настраиваемой единицы измерения или форматирования. Каждый раз, когда функция вызывается без параметров, мы перезапускаем начальное время.

@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

Тест с задержкой 94 секунды

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 . . .

Ответ 8

Последний код Aacini демонстрирует потрясающий метод подстановки переменных.
Это позор, это не доказательство регионального формата - он терпит неудачу на стольких уровнях.
Здесь короткое исправление, которое сохраняет метод замещения + математический:

@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 с региональным форматом, 24h и поддержкой смешанного ввода
Адаптация тела метода замены Aacini, без IF's, только один FOR (мое региональное исправление)

1: Файл timer.bat размещен где-то в% PATH% или текущем каталоге

@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

Использование:
таймер и echo start_cmds и таймаут /t 3 и echo end_cmds и таймер
таймер и таймер "23: 23: 23,00"
таймер "23: 23: 23,00" и таймер
таймер "13.23.23,00" и таймер "03: 03: 03.00"
таймер и таймер "0: 00: 00.00" no и cmd/v: on/c эхо до полуночи =! timer_end!
Ввод теперь может быть смешанным, для тех маловероятных, но возможных изменений формата времени во время выполнения

2: Функция : таймер в комплекте с пакетом script (пример использования ниже):

@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

:: протестировать его, скопировать-вставить как выше, так и ниже секций кода

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