.bat バッチファイル で実行時間を測定する。ただし24H未満に限る


これは何?

Windows バッチファイルで時間測定をする方法を紹介します。

想定読者

  • どうしても powershell や python を使いたくない人
  • 計測区間が 24時間未満ので十分な人
  • できるだけ環境変数を汚染したくない人

結論

下記バッチファイルを呼び出してください。
第一引数に測定開始の %TIME% の値
第二引数に測定終了の %TIME% の値
を与えます。
戻り値(%errorlevel%)は、測定区間のセンチ秒です。
第二引数を指定しない場合、第一引数に指定した %TIME% をセンチ秒に変換した値を返します。
第三引数に何か指定した場合は、時間表示が抑制されます。
戻り値が負の値はエラーです
動作は Windows 10 1903 で行っています。 Windows 8 以降なら動くと思います。

duration.bat
@echo off
@setlocal

if "%~1"=="" exit /b -1

call :time2centiseconds %1
set startcs=%errorlevel%
if "%~2"=="" exit /b %startcs%

call :time2centiseconds %2
set endcs=%errorlevel%

call :duration_centiseconds %startcs% %endcs%
set dur=%errorlevel%

if "%~3"=="" call :centiseconds2time %dur%
exit /b %dur%

:time2centiseconds
if "%~1"=="" exit /b 0
for /f "tokens=1-4 delims=:.," %%a in ("%~1") do set /a cs=%%a*360000+(1%%b %% 100)*6000+(1%%c %% 100)*100+1%%d %% 100
exit /b %cs%

:duration_centiseconds
if "%~1"=="" exit /b 0
if "%~2"=="" exit /b 0
set /a dur=%2 - %1
rem we might have measured the time inbetween days
if %dur% lss 0 set /a dur=%dur%+8640000
exit /b %dur%

:centiseconds2time
if "%~1"=="" exit /b -1
set /a h=%1 / 360000
set /a m=(%1 - %h% * 360000) / 6000
set /a s=(%1 - %h% * 360000 - %m% * 6000) / 100
set /a cs=(%1 - %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%

for /f "tokens=1-2 delims=," %%a in ( "%time%" ) do (
  if "%%b"=="" (
    echo %h%:%m%:%s%.%cs%
  ) else (
    echo %h%:%m%:%s%,%cs%
  )
)
exit /b 0

呼び出し例

set basetime=%time%
何か処理をつらつら行う
duration.bat %basetime% %time%

実行例

時刻からセンチ秒を得る

C:\>duration.bat 00:22:25.95
C:\>echo %errorlevel%
134595

時間をセンチ秒で得る

  • echo あり

    C:\>duration.bat 00:22:25.95 00:02:25.95
    23:40:00.00
    C:\>echo %errorlevel%
    8520000
    
  • echo なし

    C:\>duration.bat 00:22:25.95 00:02:25.95 noprint
    C:\>echo %errorlevel%
    8520000
    

雑談

参考文献を見ていて、環境変数を汚すことが気になった。
なんとか汚さずにすむ方法ないかなと考えてたら %errorlevel% でセンチ秒を返せばいいことに気づいた。
で、そのルーチンで、実行時間のセンチ秒を表示しようと思ったんだけど、センチ秒じゃ直感的じゃないので、差分をとって表示するルーチンも組み込みました。

%TIME% の値が、ロケールによって ,. の違いがあるというのを知ったのが、今回の収穫かな。
表示の時は、ロケールに従うようになっているハズ。

参考文献

https://qiita.com/koryuohproject/items/815a1621bc34a223e4b9
https://stackoverflow.com/questions/605522/print-time-in-a-batch-file-milliseconds
http://futuraso.hatenablog.com/entry/2016/09/09/095406