计算 Windows 批处理文件中的时间差

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9922498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 09:24:34  来源:igfitidea点击:

Calculate time difference in Windows batch file

windowsbatch-filetime

提问by Danny Gloudemans

How can I get the difference between two times in a Batch file? Because I want to print it in an HTML file.

如何获得批处理文件中两次之间的差异?因为我想将其打印在 HTML 文件中。

I thought this would be possible, but it isn't.

我以为这是可能的,但事实并非如此。

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

Results:

结果:

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

But what I want is:

但我想要的是:

00:09:10,14

Or 9 minutes and 10 seconds or 550 seconds

或 9 分 10 秒或 550 秒

回答by Aacini

@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:Shorter method added

编辑 2017-05-09:添加了更短的方法

I developed a shorter method to get the same result, so I couldn't resist to post it here. The two forcommands used to separate time parts and the three ifcommands used to insert leading zeros in the result are replaced by two long arithmetic expressions, that could even be combined into a single longer line.

我开发了一个更短的方法来获得相同的结果,所以我忍不住把它贴在这里。for用于分隔时间部分的两个命令和if用于在结果中插入前导零的三个命令被两个长算术表达式替换,它们甚至可以组合成一个更长的行。

The method consists in directly convert a variable with a time in "HH:MM:SS.CC" format into the formula needed to convert the time to centiseconds, accordingly to the mapping scheme given below:

该方法包括将“HH:MM:SS.CC”格式的时间变量直接转换为将时间转换为厘秒所需的公式,对应于下面给出的映射方案:

       HH        :      MM        :      SS        .       CC

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

That is, insert (((10at beginning, replace the colons by %%100)*60+1, replace the point by %%100)*100+1and insert %%100at end; finally, evaluate the resulting string as an arithmetic expression. In the time variable there are two different substrings that needs to be replaced, so the conversion must be completed in two lines. To get an elapsed time, use (endTime)-(startTime)expression and replace both time strings in the same line.

(((10开头插入,冒号%%100)*60+1替换,点替换,结尾%%100)*100+1插入%%100;最后,将结果字符串评估为算术表达式。在时间变量中有两个不同的子串需要替换,所以转换必须分两行完成。要获得经过的时间,请使用(endTime)-(startTime)表达式并替换同一行中的两个时间字符串。

EDIT 2017/06/14:Locale independent adjustment added

编辑 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%

You may review a detailed explanation of this method at this answer.

您可以在此答案中查看此方法的详细说明。

回答by Danny Gloudemans

As answered here: How can I use a Windows batch file to measure the performance of console application?

如此处所回答: 如何使用 Windows 批处理文件来衡量控制台应用程序的性能?

Below batch "program" should do what you want. Please note that it outputs the data in centiseconds instead of milliseconds. The precision of the used commands is only centiseconds.

下面的批处理“程序”应该做你想做的。请注意,它以厘秒而不是毫秒为单位输出数据。使用的命令的精度只有厘秒。

Here is an example output:

这是一个示例输出:

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

Here is the batch 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

回答by Mike Q

A re-hash of Aacini's code because most likely you are going to set the start time as a variable and want to save that data for output:

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 ( 
       IF %ENDTIME% GTR %STARTTIME% set /A "end=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100" 
       IF %ENDTIME% LSS %STARTTIME% set /A "end=((((%%a+24)*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% 

Output:

输出:

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

回答by yinon

Based on previous answers, here are reusable "procedures" and a usage example for calculating the elapsed time:

根据以前的答案,这里是可重用的“程序”和用于计算经过时间的用法示例:

@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

回答by Dirk Schiller

Fixed Gynnad's leading 0Issue. I fixed it with the two Lines

修复了 Gynnad 的主要0问题。我用两条线修好了

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

Full Script ( CalculateTime.cmd):

完整脚本 ( 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

回答by AveYo

Aacini's latest code showcases an awesome variable substitution method.
It's a shame it's not Regional format proof - it fails on so many levels.
Here's a short fix that keeps the substitution+math method intact:

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 with Regional format, 24h and mixed input support
Adapting Aacini'ssubstitution method body, no IF's, just one FOR (my regional fix)

具有区域格式、24 小时和混合输入支持的“精益和平均”计时器
适应Aacini 的替换方法主体,没有 IF,只有一个 FOR(我的区域修复)

1: File timer.batplaced somewhere in %PATH% or the current dir

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

Usage:
timer& echo start_cmds & timeout /t 3 & echo end_cmds &timer
timer& timer"23:23:23,00"
timer"23:23:23,00" & timer
timer"13.23.23,00" & timer"03:03:03.00"
timer& timer"0:00:00.00" no & cmd /v:on /c echo until midnight=!timer_end!
Input can now be mixed, for those unlikely, but possible time format changes during execution

用法:
计时器&回波start_cmds&超时/吨3回波end_cmds&定时器
定时器计时器“23:23:23,00”
计时器“23:23:23,00” &定时器
定时器“13.23.23,00” &计时器"03:03:03.00"
timer& timer"0:00:00.00" no & cmd /v:on /c echo 直到午夜=!timer_end!
现在可以混合输入,用于那些不太可能但在执行过程中可能发生的时间格式更改

2: Function :timerbundled with the batch script (sample usage below):

2:函数:timer与批处理脚本捆绑在一起(示例用法如下):

@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

:: to test it, copy-paste both above and below code sections

:: 要测试它,复制粘贴上面和下面的代码部分

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

回答by sst

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.

它尊重%TIME%的区域格式,而不对时间和小数分隔符的字符类型做任何假设。

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

:: 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::timediff 函数的解释:

function prototype  :timediff <outDiff> <inStartTime> <inEndTime>

Input and output format is the same format as %TIME%

输入输出格式与%TIME%格式相同

It takes 3 parameters from left to right:

从左到右需要3个参数:

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

Param1:保存结果的环境变量的名称。
Param2:要传递给包含 StartTime 字符串的函数的环境变量的名称
Param3:要传递给包含 EndTime 字符串的函数的环境变量的名称

If EndTime is less than StartTime then:

如果 EndTime 小于 StartTime,则:

    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*360000centiseconds or (24:00:00.00)otherwise the result will not be meaningful.

    在这种情况下,EndTime 将被视为第二天的时间,该函数测量 24 小时的最大距离减去 1 厘秒
    时间元素之间的时间差可以具有大于其标准最大值的值,例如:12:247:853.5214
    提供比总表示时间不超过24*360000厘秒或(24:00:00.00)否则结果将没有意义。
If EndTime is greater than or equals to StartTime then:
如果 EndTime 大于或等于 StartTime,则:
    No formal limitation applies to the value of elements,
    except that total represented time can not exceed 2147483647centiseconds.
    元素的值没有正式的限制,
    除了总表示时间不能超过2147483647厘秒。



More examples with literal and non-standard time values更多带有文字和非标准时间值的示例

    Literal example with EndTime less than StartTime:
    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
    Output:
    输出:
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
    Output:
    输出:
27:2457:433.85935 is equivalent to 68:18:32.35

    Last bonus example:
    最后的奖金示例:
@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
    Output:
    输出:
2147483647 centiseconds equals to 5965:13:56.47

回答by PHC

Using a single function with the possibility of custom unit of measure or formatted. Each time the function is called without parameters we restarted the initial time.

使用具有自定义度量单位或格式化可能性的单个函数。每次在没有参数的情况下调用该函数时,我们都会重新启动初始时间。

@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

A test with a delay of 94 sec

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

回答by Zimba

CMD doesn't have time arithmetic. The following code, however gives a workaround:

CMD 没有时间算法。但是,以下代码提供了一种解决方法:

set vid_time=11:07:48
set srt_time=11:16:58

REM Get time difference
set length=%vid_time%
for /f "tokens=1-3 delims=:" %i in ("%length%") do (
set /a h=%i*3600
set /a m=%j*60
set /a s=%k
)
set /a t1=!h!+!m!+!s!

set length=%srt_time%
for /f "tokens=1-3 delims=:" %i in ("%length%") do (
set /a h=%i*3600
set /a m=%j*60
set /a s=%k
)
set /a t2=!h!+!m!+!s!
cls
set /a diff=!t2!-!t1!

Above code gives difference in seconds. To display in hh:mm:ss format, code below:

上面的代码给出了以秒为单位的差异。要以 hh:mm:ss 格式显示,代码如下:

set ss=!diff!
set /a hh=!ss!/3600 >nul
set /a mm="(!ss!-3600*!hh!)/60" >nul
set /a ss="(!ss!-3600*!hh!)-!mm!*60" >nul
set "hh=0!hh!" & set "mm=0!mm!" & set "ss=0!ss!"
echo|set /p=!hh:~-2!:!mm:~-2!:!ss:~-2!