对时间值进行算术运算的循环内延迟扩展

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,225: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,则没有空格,您只会得到带有MHmh 的那些(带有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! 显示它们)的有效方法应该可以工作......

以上是关于对时间值进行算术运算的循环内延迟扩展的主要内容,如果未能解决你的问题,请参考以下文章

使用默认值声明 Thymeleaf 变量后如何对其进行算术运算?

如何对char类型进行安全算术运算

在python中有多少种运算符?解释一下算术运算符

算术和关系运算符

JavaScript日常学习6

在 SQL 中对别名进行算术运算