Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 批处理文件中具有HH:MM:SS次的算术运算_Batch File_Cmd - Fatal编程技术网

Batch file 批处理文件中具有HH:MM:SS次的算术运算

Batch file 批处理文件中具有HH:MM:SS次的算术运算,batch-file,cmd,Batch File,Cmd,在我的一个批处理脚本中,我需要计算视频文件中间隔的持续时间。首先,要求用户输入开始和结束时间: set /p StartPosition=Start position (HH:MM:SS): set /p EndPosition=End position (HH:MM:SS): 然后,我想让批处理脚本计算其间的持续时间 如何从%EndPosition%中减去%StartPosition%,例如: set /A "hh=ss/3600+100,ss%%=3600,mm=ss/60+100,ss=

在我的一个批处理脚本中,我需要计算视频文件中间隔的持续时间。首先,要求用户输入开始和结束时间:

set /p StartPosition=Start position (HH:MM:SS):
set /p EndPosition=End position (HH:MM:SS):
然后,我想让批处理脚本计算其间的持续时间

如何从%EndPosition%中减去%StartPosition%,例如:

set /A "hh=ss/3600+100,ss%%=3600,mm=ss/60+100,ss=ss%%60+100"

echo Duration=%hh:~1%:%mm:~1%:%ss:~1%
00:10:40-00:10:30=00:00:10

我不知道怎么做的原因是因为这些数字是用冒号分隔的


编辑:这个问题与问题不同,因为我不需要纸条将数字作为时间值来处理

这可以通过以下方式在纯批次中完成。很多人打电话到其他的程序去做日期计算

以下代码调用PowerShell以使用.NET DateTime类为您执行解析

C:\> set "StartPosition=00:10:30"
C:\> set "EndPosition=00:10:40"
C:\> PowerShell.exe -c "$span=([datetime]'%EndPosition%' - [datetime]'%StartPosition%'); '{0:00}:{1:00}:{2:00}' -f $span.Hours, $span.Minutes, $span.Seconds"
00:00:10

这将执行两行PowerShell代码;一个用于将两个时间转换为DateTime对象并减去它们,另一个用于以指定的格式输出结果。

这是一个工作原型:

@echo off 

set T1=00:10:45
set T2=00:11:05

set HOUR1=%T1:~,2%
set MIN1=%T1:~3,-3%
set SEC1=%T1:~-2%

set HOUR2=%T2:~,2%
set MIN2=%T2:~3,-3%
set SEC2=%T2:~-2%

set /A TOTAL_SEC1=%HOUR1%*3600+%MIN1%*60+SEC1
set /A TOTAL_SEC2=%HOUR2%*3600+%MIN2%*60+SEC2
set /A DIFF=%TOTAL_SEC2%-%TOTAL_SEC1%

echo %DIFF%
输出:

这并不完整,但这是一个合理的开始

@echo off
setlocal

set /p "StartPosition=Start position (HH:MM:SS): "
set /p "EndPosition=End position (HH:MM:SS):   "

set /A "ss=(((1%EndPosition::=-100)*60+1%-100)-(((1%StartPosition::=-100)*60+1%-100)"
set /A "hh=ss/3600+100,ss%%=3600,mm=ss/60+100,ss=ss%%60+100"

echo Duration=%hh:~1%:%mm:~1%:%ss:~1%
编辑:添加了一些解释

该程序使用通常的方法,通过标准公式:秒=HH*60+MM*60+SS,将HH:MM:SS格式的时间转换为秒数。但是,SET/A命令考虑以0开始的数字作为八进制基数,因此08和09将是无效八进制数。为了避免这个问题,在展开数字之前放一个数字1,然后减去100,因此如果HH=08,那么1%HH%-100正确地给出8;即:

set /A seconds = ((1%HH%-100)*60+1%MM%-100)*60+1%SS%-100
set /A "seconds=((1%EndPosition::=-100)*60+1%-100"
有几种方法可以将HH:MM:SS格式的时间分割为三部分。例如,如果我们以set EndPosition=HH:MM:SS为基础,那么我们可以这样使用For/F命令:

for /F "tokens=1-3 delims=:" %%a in ("%EndPosition%") do (
   set /A "seconds=((1%%a-100)*60+1%%b-100)*60+1%%c-100"
)
在这个程序中,使用了不同的方法。如果我们将原始EndPosition=HH:MM:SS字符串与所需的公式匹配,我们可以构造此映射方案:

     HH       :      MM       :      SS

((1  HH  -100)*60+1  MM  -100)*60+1  SS  -100
换言之:如果我们将原始字符串的冒号替换为-100*60+1,并在开始处插入1,在结束处插入-100,则得到所需的公式;即:

set /A seconds = ((1%HH%-100)*60+1%MM%-100)*60+1%SS%-100
set /A "seconds=((1%EndPosition::=-100)*60+1%-100"
这是一种非常有效的方法,它甚至允许替换同一公式中的EndPosition和StartPosition字符串,将这两个部分括在括号中,并直接减去它们:

set /A "ss=(((1%EndPosition::=-100)*60+1%-100)-(((1%StartPosition::=-100)*60+1%-100)"
您可以取消@echo off命令并运行程序,以查看替换变量值后计算的精确公式。例如,当StartPosition=00:10:30和EndPosition=00:10:40时,将计算以下表达式:

set /A "ss=(((100-100)*60+110-100)*60+140-100)-(((100-100)*60+110-100)*60+130-100)"
为了完成此描述,这是使用for/F命令计算同一公式的标准方法:

从秒数到HH:MM:SS零件的相反转换非常简单:

HH=SS/3600, rest=SS%3600, MM=rest/60, SS=rest%60
但是,结果中的每个部分都必须用两位数字显示,但这种格式可以通过非常简单的方式实现。在这种情况下,不是插入三个if命令来检查每个部分是否小于10,而是插入一个填充零,例如,数字100只是添加到将8转换为108的部分,并且当显示每个部分时,省略第一个数字,因此仅显示08。这是一种非常有效的数字格式化方法,可在用于获取零件的同一set/a命令中执行。例如:

set /A "hh=ss/3600+100,ss%%=3600,mm=ss/60+100,ss=ss%%60+100"

echo Duration=%hh:~1%:%mm:~1%:%ss:~1%
这样,两次到两秒的转换、减法以及到HH:MM:SS的相反转换和格式转换都在两个SET/A命令中执行,甚至可以在一条长行中写入

输出示例:

Start position (HH:MM:SS): 00:10:30
End position (HH:MM:SS):   00:10:40
Duration=00:00:10

Start position (HH:MM:SS): 00:10:45
End position (HH:MM:SS):   00:11:05
Duration=00:00:20
我想,@Aacini已经清除了这里的一切。他比我先抓住了你。但是,我想通过使用For循环来简化代码,从而改进他的as-as

注:“REM”之后的所有内容都是注释,以便于理解。。。 您只需将其复制到批处理文件中即可。并且,在主代码中使用它,如下所示:

语法:Call:Time[yourtime1][Operation][yourtime2]

现在,您可以应用任何操作,包括“加法、减法、除法、乘法”; 时间函数 -------复制下面的代码-----

:Time [Start_Time] [Operation] [End_Time]
SetLocal EnableDelayedExpansion
REM Creating a portable Function for your Job. :)

REM Reading Start-time...
For /F "Tokens=1,2,3 Delims=:" %%A in ("%~1") Do (
Set _Start_Hour=%%A
Set _Start_Min=%%B
Set _Start_Sec=%%C
)

REM Reading End-time...
For /F "Tokens=1,2,3 Delims=:" %%A in ("%~3") Do (
Set _End_Hour=%%A
Set _End_Min=%%B
Set _End_Sec=%%C
)

REM Removing leading Zero's - if any... 'CMD assumes it as octal - otherwise'
For %%A In (Hour Min Sec) Do (
    For %%B In (Start End) Do (
        IF /I "!_%%B_%%A:~0,1!" == "0" (Set _%%B_%%A=!_%%B_%%A:~1!)
        )
)

REM Applying Operation on the given times.
For %%A In (Hour Min Sec) Do (Set /A _Final_%%A=!_Start_%%A! %~2 !_End_%%A!)

REM Handling a little Exceptional errors! - due to the nature of time (60 sec for a min.)
SET _Extra_Hour=0
SET _Extra_Min=0

REM Two Cases can arise in each part of time...
:Sec_loop
IF %_Final_Sec% GTR 59 (Set /A _Extra_Min+=1 & Set /A _Final_Sec-=60 & Goto :Sec_loop)
IF %_Final_Sec% LSS 0 (Set /A _Extra_Min-=1 & Set /A _Final_Sec+=60 & Goto :Sec_loop)

Set /A _Final_Min+=%_Extra_Min%

:Min_loop
IF %_Final_Min% GTR 59 (Set /A _Extra_Hour+=1 & Set /A _Final_Min-=60 & Goto :Min_loop)
IF %_Final_Min% LSS 0 (Set /A _Extra_Hour-=1 & Set /A _Final_Min+=60 & Goto :Min_loop)

Set /A _Final_Hour+=%_Extra_Hour%

REM Saving Everything into a Single Variable - string.
Set _Final_Time=%_Final_Hour%:%_Final_Min%:%_Final_Sec%

REM Displaying it on the console. ;)
Echo.%_Final_Time%
Goto :EOF
--------------End OF Code----------------------
你也可以访问我的网站-基于批处理编程。www.thebateam.org你会在那里找到很多帮助你的东西

如果时间是11:05-10:45,可能会重复什么?你希望答案是:20吗?这不是标准的数学。它需要在一分钟内意识到60秒。您必须从每个字段中去掉前导零,以便set命令正确计算。基本上,您需要将整个时间转换为秒,然后使用一个函数将其转换回小时分钟和秒。就我个人而言,我会选择一个带有嵌入式Jscript的混合批处理文件。@Arete你说的“仅批处理”是什么意思?我放在上面的那一行是一个批处理文件命令,它执行您想要的操作。它只是碰巧调用了另一个Windows程序
ram来执行计算。这很有趣!如果解决此问题的极其困难的批处理文件(例如,使用两行进行转换,一行进行格式化),那么此PowerShell解决方案是否非常困难当然,与批处理文件解决方案相比,这个PS解决方案的速度非常慢…@Aacini是的,你非常聪明;您已经批量创建了一些内容。你用不着对这件事那么无礼。我认为这个PowerShell解决方案更具可读性,因为关键位看起来不像线噪声。Re:speed,一旦加载.NET framework,PS就相当不错了。如果速度真的很关键,您需要删除批处理并编写一个.exe。您起初认为批处理文件解决方案非常困难,但后来删除了此类注释。虽然“极其困难”是一个主观术语,但我认为这样一个关于批处理解决方案的观点,可以使用命令的标准在4行中完成,这表明了对批处理文件的了解不足。当我们遇到其他话题时,比如您在建议非请求的PowerShell解决方案时也批评了批处理文件。我同意每种编程语言都有利弊,但PowerShell在客观上几乎在所有方面都优于批处理文件:表现力、可读性、可维护性、互操作性,和学习曲线。我假设并不是所有询问批处理文件问题或稍后访问此问题的人都权衡了操作系统上可用的每种脚本语言的优缺点,而是他们可能使用批处理作为默认的Windows脚本语言。我想让处于这种情况的人明白还有其他选择。如果没有重大改变,比如将开始和结束时间转换为秒,乘法和除法将无法工作。只有这样的改变,乘法和除法才能起作用,尽管语法有些笨拙。00:20:00*00:00:02,20分钟*2?另外,输出应该用零填充。:o这是修复bug的一个很好的提示。而且,用零填充并不是一项困难的任务,我只需要再添加几行来检查最终输出的宽度,如果它们是个位数,则添加零。虽然,@Aacini已经修复了这里的一切。我也会遵循他简短而令人惊讶的解决方案这比我预期的答案要优雅得多。非常感谢!尽管我意识到批处理脚本可能不是此操作的语法。