【问题标题】:Calculate time difference in Windows batch file计算 Windows 批处理文件中的时间差
【发布时间】:2012-04-12 22:19:08
【问题描述】:

如何获得批处理文件中两次之间的差异?因为我想在 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 秒

【问题讨论】:

  • 虽然有可能(老实说,只是批量搜索日期/时间数学),但您不应该这样做。而且我想我什至不应该问为什么批处理文件涉及提供 HTML 内容。
  • 为什么我不应该这样做?我提供 HTML 服务是因为我部署了一些插件,而查看是否成功的唯一方法是在日志文件中搜索“成功”一词。当然我需要反馈,因为它有 100 多个插件。所以我可以看到女巫成功而女巫失败。你有更好的方法吗?
  • 如果在批处理文件中也可以使用 PowerShell,为什么还要使用它?我可以在 Windows 7、Vista、XP 中使用批处理文件,而无需安装任何东西。 Powershell 在 Windows 7 上只是“标准”。在其他操作系统上,我需要安装它。它会花费更多时间,而在批处理文件中是可能的。
  • 我同意 Joey 的观点,不要批量编写生产流程(而且我是一个批处理狂热者!),它有很多限制,而且很难执行复杂的任务。我会选择 phython/perl 或一些独立于 MS 的真实语言(确保它在三年内仍然可以工作),你甚至可以切换到 linux
  • 我用它来测试正确的构建。之后我会删除它们。如果他们部署,这只是一个测试。当它们出现时,我将在 HTML 文件中放置一个成功,当它失败时,我将在 HTML 文件中放置一个失败。然后我将删除该插件。对于所有插件也是如此。它不是为了生产什么的,它只是为了看看它是否有效。我现在有一个批处理文件,效果很好。所以我不明白为什么我应该去 Powershell 或其他任何东西?

标签: windows batch-file time


【解决方案1】:
set START=23:05:15
set END=07:02:05

set options="tokens=1-4 delims=:."
for /f %options% %%a in ("%start%") do set start_h=%%a&set /a start_m=100%%b %% 100&set /a start_s=100%%c %% 100&set /a start_ms=100%%d %% 100
for /f %options% %%a in ("%end%") do set end_h=%%a&set /a end_m=100%%b %% 100&set /a end_s=100%%c %% 100&set /a end_ms=100%%d %% 100

set /a hours=%end_h%-%start_h%
set /a mins=%end_m%-%start_m%
set /a secs=%end_s%-%start_s%
set /a ms=%end_ms%-%start_ms%

if 1%ms% lss 100 set ms=0%ms%
if %ms% lss 0 set /a secs = %secs% - 1 & set /a ms = 100%ms%
if %secs% lss 0 set /a mins = %mins% - 1 & set /a secs = 60%secs%
if %mins% lss 0 set /a hours = %hours% - 1 & set /a mins = 60%mins%
if %hours% lss 0 set /a hours = 24%hours%

set hours=0%hours%
set hours=%hours:~-2%
set mins=0%mins%
set mins=%mins:~-2%
set secs=0%secs%
set secs=%secs:~-2%

set /a totalsecs = %hours%*3600 + %mins%*60 + %secs% 

echo Command took %hours%:%mins%:%secs%.%ms% (%totalsecs%.%ms%s total)

echo %date%   %start% - %end% ( %hours%:%mins%:%secs% )

pause

【讨论】:

  • 虽然这段代码 sn-p 可以解决问题,但它没有解释为什么或如何回答这个问题。请include an explanation for your code,因为这确实有助于提高您的帖子质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。您可以使用edit 按钮改进此答案以获得更多选票和声誉!
  • 顺便说一句,至少有 7 个其他答案或多或少相同的解决方案,接受的一个是 9 岁。我看不出你的答案在哪里增加了一些新的或更好的方法。它看起来比其他的更复杂,更容易出错
【解决方案2】:

如果您不介意在批处理脚本中使用 powershell:

@echo off
set start_date=%date% %time%
:: Simulate some type of processing using ping
ping 127.0.0.1  
set end_date=%date% %time%
powershell -command "&{$start_date1 = [datetime]::parse('%start_date%'); $end_date1 = [datetime]::parse('%date% %time%'); echo (-join('Duration in seconds: ', ($end_date1 - $start_date1).TotalSeconds)); }"

【讨论】:

  • 我之所以选择这种方法,是因为它只需要在我现有的批处理文件中添加两行代码,所有这些文件都在安装了 PowerShell 的环境中运行。亲吻
【解决方案3】:
@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%

编辑 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) 表达式并替换同一行中的两个时间字符串。

EDIT 2017/06/14: 添加了区域独立调整

EDIT 2020/06/05: 增加了午夜调整

@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), elap-=(elap>>31)*24*60*60*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%

您可以在this answer查看此方法的详细说明。

【讨论】:

  • 干得好,我非常喜欢这个。我只会说,很可能人们在脚本中更早地设置了开始时间,所以我会在开始/结束值中设置变量,而不是实际获取它并在记录时对其进行格式化。我将在下面发布您的重新散列。
  • 这对我有用——它确实做出了特定于语言环境的假设——“,”在输出中用作小数分隔符(应该很容易检测到这一点,因为您正在解析 %time%无论如何...),但是通过代码更改的那一个字符,它对我有用,并且看起来正确(在我的语言环境中)。
  • 对于更新的答案,如果你有','作为小数点分隔符,你必须用[...]Time:,替换[...]Time:.(语言环境很糟糕)。
  • @Arsenal:是的,但是语言环境独立调整很简单。查看我的第二次编辑...
  • 谢谢。由于我不理解的原因,依赖于语言环境的解决方案今天停止工作。因此,非常感谢更新。
【解决方案4】:

重新散列 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% 

输出:

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

【讨论】:

  • ...你们知道批处理文件有类似 GOSUB 的行为,对吧? (通过CALL 语句——你可以CALL 一个标签,传递它的参数,它可以传回返回值......你可以谷歌语法,但它不是太难)。
  • 是的,当我在我的脚本中使用它时,我把它当作一个函数来调用。
  • 考虑到午夜后结束,我会将第二个 for 循环更改为: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" )
  • 如何在 FOR 循环中使用你的脚本?
  • @David 谢谢大卫,我更新了代码。似乎可以工作,但我还没有完全测试。
【解决方案5】:

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!

以上代码以秒为单位给出差异。要以 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! 

【讨论】:

    【解决方案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=(@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
    )
    

    示例:

    @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
    
      输出:
    开始时间:23:57:33,12 结束时间:00:02:19,41 差异: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 相当于 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 厘秒等于 5965:13:56.47

    【讨论】:

      【解决方案7】:

      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
      

      *

      具有区域格式、24 小时制和混合输入支持的“精益和平均”计时器
      调整Aacini's 替换方法体,没有 IF,只有一个 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
      

      用法:
      timer & echo start_cmds & timeout /t 3 & echo end_cmds & timer
      timer & timer "23:23:23,00"
      timer "23:23:23,00" & timer
      定时器“13.23.23,00”和定时器“03:03:03.00”
      定时器 timer "0:00:00.00" no & cmd /v:on /c echo until深夜=!timer_end!
      现在可以混合输入,因为那些不太可能但可能的时间格式在执行

      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
      

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

      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
      

      【讨论】:

        【解决方案8】:

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

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

        完整脚本(<strong>CalculateTime.cmd</strong>):

        @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
        

        【讨论】:

          【解决方案9】:

          使用具有自定义度量单位或格式化的可能性的单个函数。 每次调用不带参数的函数时,我们都会重新开始初始时间。

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

          【讨论】:

          • 如果我们想要替代输出格式的小更新,而不是 hh:mm:ss,cs 将格式更改为 00h 00m 00s 我们需要更改行:SET "_t=!_h!:!_m!:!_s!.!_cs!" SET "_t=!_t:00:=!" 并将它们替换为以下代码: IF "%_f%" == "hms" ( SET "_t=!_h!h !_m!m !_s!s" &amp; SET "_t=!_t:00h=!" &amp; SET "_t=!_t:00m=!" &amp; SET "_t=!_t: =!" ) ELSE ( SET "_t=!_h!:!_m!:!_s!.!_cs!" &amp; SET "_t=!_t:00:=!" ) 现在我们可以使用句子“hms”作为格式化参数,以便输出格式为 00h 00m 00s
          【解决方案10】:

          根据之前的答案,这里有可重复使用的“程序”和计算经过时间的使用示例:

          @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
          

          【讨论】:

          • 如果centiseconds 是负数,:centiseconds_to_time 可以检查并在前面加上一个减号。 set "_n=" 后跟 if %_centiseconds% lss 0 set "_n=-" &amp; set /A _centiseconds*=-1 然后在最后:set _result=%_n%%_h%:%_m%:%_s%.%_hs% 以便 call :centiseconds_to_time -3000 test_neg 给出 test_neg = -00:00:30.00
          • 此示例脚本中不需要,因为持续时间始终为非负数。
          【解决方案11】:

          在这里回答: How can I use a Windows batch file to measure the performance of console application?

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

          这是一个示例输出:

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

          这是批处理脚本:

          @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
          

          【讨论】:

          • Aacini 的下面我认为更好,因为它更直接。此外,您的脚本会在我的系统上吐出错误,并且并不总是执行数学运算。有时,我不确定问题出在哪里,但现在没有这样做..
          • 不错,但仍然存在一个重大错误,正如迈克已经说过的那样。算法必须解决(至少:-)两种特殊行为:1.第一个是Batches认为以零为前缀的数字是八进制数。此处通过以“1”为前缀并再次减去 100 来正确解决此问题。 2. 但另一个问题是,小时有时由一个数字组成(“2:”),有时由两个数字组成(“12:”)。也许这是特定于语言环境的,但我认为不是。所以 ":~02,2%" 在这里失败了。然而,这并不总是有效,Aacini 的解决方案似乎效果更好。
          • 当然,区域设置适用于此处,因此您最好了解可能运行此脚本的任何其他用户是如何设置的...例如:我,例如:上午 01:35,我的“小时”变为:“1:”(而不是“01”,这很好),这将使上述脚本失败。最好添加一些逻辑来覆盖它!
          • 第 25 行:if %ENDTIME% LSS %STARTTIME% set set /A DURATION=%STARTTIME%-%ENDTIME% - 我不明白它应该如何工作!?认为应该是if %ENDTIME% LSS %STARTTIME% set set /A DURATION=%DURATION%+8640000。常量8640000 是一天中的厘秒数。
          猜你喜欢
          • 1970-01-01
          • 2021-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-13
          • 1970-01-01
          • 2020-04-13
          相关资源
          最近更新 更多