对时间值进行算术运算的循环内延迟扩展
Posted
技术标签:
【中文标题】对时间值进行算术运算的循环内延迟扩展【英文标题】:Delayed Expansion Inside Loop with Arithmetic Operations on Time Values 【发布时间】:2022-01-14 12:23:53 【问题描述】:我对批处理文件比较陌生,我一直在尝试让以下定时例程(灵感来自 Arithmetic operations with HH:MM:SS times in batch file)工作:
set "startTime=%time: =0%"
@rem Removing milliseconds information
set startTime=%startTime:~0,-3%
setlocal EnableDelayedExpansion
for %%i in (1 2 3 4 5) do (
timeout /T 3 /NOBREAK
set endTime=!time: =0!
set endTime=!endTime:~0,-3!
set /A "ss=(((1%endTime::=-100)*60+1%-100)-(((1%startTime::=-100)*60+1%-100)"
set /A "hh=ss/3600+100,ss%%=3600,mm=ss/60+100,ss=ss%%60+100"
@rem Get format in HH:MM:SS (maybe H:MM:SS after midnight.. not tested yet)
echo Start time: %startTime%
echo End time: !endTime!
@rem Issue here: Always get the same output despite delayedExpansion active
echo Diff time: !ss!
echo.
@rem Issue here: Not getting expected values
echo Elapsed time: !hh:~1!:!mm:~1!:!ss:~1!...
echo.
)
endlocal
我不太清楚为什么尽管延迟扩展,时差的输出值总是相同的。此外,格式化的时间并没有给我正确的值。
感谢您的帮助!
【问题讨论】:
如果您不知道echo %TIME%
使用您的帐户在您的 Windows 计算机上输出什么,我们将无法为您提供帮助。日期/时间格式取决于为您的账户配置的国家(地区)。在我的 Windows 计算机上,我的帐户分别输出 18:55:07,22
和 5:55:51,16
,并在早上 10 点之前的一段时间内以空格开头。查看Time is set incorrectly after midnight 的答案以获取独立于国家/地区设置的当前时间。
顺便说一句:从命令提示符窗口中运行发布的批处理文件会导致错误消息:%iter was unexpected at this time.
并在下一行显示for %iter in (1 2 3 4 5) do (
。循环变量只能是i
这样的一个字符,但不能是iter
这样的字符串。 @Aacini 编写的代码可以很好地使用 delayed 而不是 immediate 扩展,即只要时间格式合适(24 小时格式)而不是使用 set /A "ss=(((1!endTime::=-100)*60+1!-100)-(((1!startTime::=-100)*60+1!-100)"
在午夜前不到 15 秒运行。
@Mofi 谢谢,我已经相应地更新了代码。我还指出了我电脑上的时间格式:HH:MM:SS
@G.Rab,如果您查看代码提交的第一行 set "startTime=%time: =0%"
,它将用 0
替换空格。但是,如果您返回的实际日期是HH:MM:SS
,则没有空格,您只会得到带有M
、H
、m
或h
的那些(带有tt
)。然后set startTime=%startTime:~0,-3%
,将删除最后三个字符,如果你的字符真的是HH:MM:SS
,你会留下HH:MM
,我很确定这不是你想要的。我们特别想知道的是Echo "%TIME%"
的结果,(将数字替换为H/HH/h/hh/M/MM/m/mm/SS/ms/tt)。
@Compo 谢谢,您的 cmets 为我指出了适合我的解决方案。
【参考方案1】:
首先,感谢帮助我找到问题解决方案的 cmets。如果它可能对其他人有帮助,我会在此处发布解决方案。
正如 cmets 中所述,关键是确定我的操作系统上使用的格式。
适用于我的代码如下,灵感来自https://www.py4u.net/discuss/2286184:
@rem Check that the format of %TIME% is HH:MM:SS.CS for example 23:59:59.99
echo "%TIME%"
set STARTTIME=%TIME%
@rem convert start time 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)
setlocal EnableDelayedExpansion
for %%i in (1 2 3 4 5) do (
timeout /T 3 /NOBREAK
set ENDTIME=!TIME!
@rem convert ENDTIME to centiseconds
@rem I found that double-quotes with set /A and numbers are needed inside the for loop
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 Adjust for cases where timings over multiple days
if !ENDTIME! LSS %STARTTIME% set set /A DURATION=%STARTTIME%-!ENDTIME!
@rem now break the centiseconds down to hours, 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 Enforce double-digit format
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 timings
echo STARTTIME: %STARTTIME% centiseconds
echo ENDTIME: !ENDTIME! centiseconds
echo DURATION: !DURATION! in centiseconds
echo Elapsed time: !DURATIONH!:!DURATIONM!:!DURATIONS!.!DURATIONHS!
)
endlocal
【讨论】:
嗯...您原始代码中的唯一问题是在set /A "ss=(((1!endTime::=-100)*60+1!-100)-(((1!startTime::=-100)*60+1!-100)"
的计算中使用延迟扩展(以及正确的方法通过if !ss! lss 0 set /A ss+=24*60*60
调整午夜间隔)。之后,原始的set /A "hh=ss/3600+100,ss%%=3600,mm=ss/60+100,ss=ss%%60+100"
提取单个 HH:MM:SS 部分(并通过!hh:~1!:!mm:~1!:!ss:~1!
显示它们)的有效方法应该可以工作......以上是关于对时间值进行算术运算的循环内延迟扩展的主要内容,如果未能解决你的问题,请参考以下文章