如何在两个日期和时间时间戳之间执行算术运算(加,减)?

时间:2019-01-05 10:01:17

标签: windows batch-file

我正在尝试使用批处理文件创建任意时间。我试图从我的代码中减去设置值(例如1天,1个月和2000年),以显示系统时间减去前面所述的设置值。对于小时和分钟,我要减去10小时和10分钟(在代码中显示为不同的值)。我也知道日期和时间是与我的系统有关的变量。 〜请忽略

重要- 我现在的问题是这部分:

if %minb% EQU 60 set /a minb=%minb%-60 & set /a hourb=%hourb%+1
if %hourb% EQU 24 set /a hourb=%hourb%-24 & set /a dayb=%dayb%+1
if %dayb% EQU 30 set /a dayb=%dayb%-30 & set /a monthb=%monthb%+1
if %monthb% EQU 12 set /a monthb=%monthb%-12 & set /a yearb=%yearb%+1

我似乎无法将分钟重置为0,并在分钟值达到60时使小时加1 ,与小时,日,月,月,每月的关系,除此之外,我的代码中的问题大部分是已修复。当我运行代码并等待分钟数(或增加时差)达到60时,它们仅超过60,并且不重置也不添加到hoursb值。

我的日期和时间格式为:

  • 短日期:M / d / yyyy
  • 长日期:dddd,MMMM d,yyyy
  • 短时间:h:mm
  • 长时间:h:mm:ss

我正在使用Windows 10。

请注意,集合/ a中的值与我的描述不匹配,但是当然可以更改它们。将它们设置为显示的数字仅出于测试目的。

编辑:

代码:

@echo off
:start
set day=%date:~-7,2%
set month=%date:~-10,2%
set year=%date:~-4,4%
set hour=%time:~0,2%
set min=%time:~3,2%

set /a "hourb=%hour%-10"
set /a "minb=%min%+30"
set /a "dayb=%day%-1"
set /a "monthb=%month%-1"
set /a "yearb=%year%-2000"

if %minb% lss 10 set minb=0%minb%
if %hourb% lss 10 set hourb=0%hourb%
if %dayb% lss 10 set dayb=0%dayb%
if %monthb% lss 10 set monthb=0%monthb%

if %minb% EQU 60 set /a minb=%minb%-60 & set /a hourb=%hourb%+1
if %hourb% EQU 24 set /a hourb=%hourb%-24 & set /a dayb=%dayb%+1
if %dayb% EQU 30 set /a dayb=%dayb%-30 & set /a monthb=%monthb%+1
if %monthb% EQU 12 set /a monthb=%monthb%-12 & set /a yearb=%yearb%+1

cls
:: ———————————————————————–
@mode con cols=20 lines=6
title Arbitrary Clock

:time    
echo.     
echo.    %hourb%:%minb%
echo.    
echo.    %dayb%-%monthb%-%yearb%  
echo.      
ping -n 2 0.0.0.0 >nul
cls
goto :start

好的,正如您在对代码的新编辑中所看到的那样,我将值设置为此问题开始处所述的值。从小时中减去10,从日期和月份中减去1,然后从年份中减去2000。我在分钟数上加了30,以立即显示问题。

所以我的系统时间是 2019年1月5日4:40。好吗?

时钟上显示的时间是 06:70,04-00-19。

期望的结果是 07:10,04-12-18。

对此进行了大量编辑。预先感谢。

2 个答案:

答案 0 :(得分:0)

您的描述中有一个基本错误。当您从日期中减去天/月/年的数量时,就是在减去日期,而不是不是!例如,如果今天日期是05/01/2019(显然是DD / MM / YYYY格式),而您要减去1个月,则结果应为05/12/2018,因为您要减去日期(1个月)。如果从月份部分中减去数字1 ,则结果将为05/00/2019。因此,应通过众所周知的添加和减去日期的方法来解决此问题。

这些方法的问题在于它们仅对特定日期范围有效,范围通常从1583年开始。如果要从2018年减去2000并得到18,则这样的“ 18年”是<在通常的日期管理方法中,em>不是有效年份。因此,除了使用通常的方法来管理日期外,您还需要完成一些小的调整。

我使用了注释中链接的代码段,并对其进行了一些修改,以解决此问题。我完成了一些测试,并且似乎可以正常工作,但也许该方法在某些特定的值范围内可能会失败。

@echo off
setlocal EnableDelayedExpansion

rem Subtract a number of Days/Months/Years @ Hours:Minutes:Seconds from a datetime stamp
rem Antonio Perez Ayala aka Aacini

rem Define the "Date in DDMMYYYY format" To "Julian Day Number" conversion "function"
set "DateToJDN(Date)=( a=1Date, y=a%%10000, a/=10000, m=a%%100, d=a/100-100, a=(m-14)/12, (1461*(y+4800+a))/4+(367*(m-2-12*a))/12-(3*((y+4900+a)/100))/4+d-32075 )"

set /P "stamp1=Enter base timestamp as DD/MM/YYYY HH:MM:SS  "
set /P "stamp2=Enter timestamp to subtract in same format:  "

set "adjust=0"
for /F "tokens=1-4" %%a in ("%stamp1% %stamp2%") do set "date1=%%a" & set "time1=%%b" & set "date2=%%c" & set "time2=%%d"
if 1%date2:~-4% lss 11600 (
   set /A "adjust=1%date2:~-4%+1600"
   set "date2=%date2:~0,-4%!adjust:~1!"
   set "adjust=1600"
)
set /A "days=!DateToJDN(Date):Date=%date1:/=%! - !DateToJDN(Date):Date=%date2:/=%!, days1600=%DateToJDN(Date):Date=00001600%"
set /A "ss=(((1%time1::=-100)*60+1%-100) - (((1%time2::=-100)*60+1%-100)"
if %ss% lss 0 set /A "ss+=60*60*24, days-=1"
set /A "hh=ss/3600+100, ss%%=3600, mm=ss/60+100, ss=ss%%60+100"
if %days% lss %days1600% set /A days+=days1600, days1600=0
set /A "l=days+68569,n=(4*l)/146097,l=l-(146097*n+3)/4,i=(4000*(l+1))/1461001,l=l-(1461*i)/4+31,j=(80*l)/2447,D=l-(2447*j)/80+100,l=j/11,M=j+2-(12*l)+100,Y=100*(n-49)+i+l+10000+adjust"
if %days1600% equ 0 set /A Y-=1600

echo                                            -----------------------
echo                                     Result:  %D:~1%/%M:~1%/%Y:~1% %hh:~1%:%mm:~1%:%ss:~1%

一个小例子:

Enter base timestamp as DD/MM/YYYY HH:MM:SS  05/01/2019 10:53:45
Enter timestamp to subtract in same format:  01/01/2000 10:10:00
                                           -----------------------
                                    Result:  04/12/0018 00:43:45

PS-我真的希望看到用于此问题的PowerShell解决方案。似乎只需要一小段代码即可。

答案 1 :(得分:0)

一个更简单的Windows批处理选项是从批处理脚本中调用PowerShell命令以操纵过去和将来的日期。

下面,第8和9行创建并格式化您的任意日期。

 :: Set the below 3 variables to generate an Arbitrary Clock
 :: Use a negative number to subtract (-7), positive number to add (7)
 set Altered_Days=-7
 set Altered_Months=-10
 set Altered_Years=-4

 :: The script will merge days and years to determine the arbitrary date and print the Arbitrary date to the screen
 set /a Altered_Days=(%Altered_Years%*356)+%Altered_Days%
 powershell -command "(((Get-date).AddDays(%Altered_Days%)).AddMonths(%Altered_Months%)).ToString('HH:mm, MM-dd-yyyy')" 

 :: If you want to capture the value in a variable, use the below line
 powershell -command "(((Get-date).AddDays(%Altered_Days%)).AddMonths(%Altered_Months%)).ToString('HH:mm, MM-dd-yyyy')">captureVar && set /p Arbitrary_Clock=<captureVar
 echo Arbitrary Clock Prediction && echo %Arbitrary_Clock%

这将使您的批处理脚本能够在Windows 10操作系统上创建所需的最终结果。

PowerShell的一大优点是可以轻松地从cmd行和批处理脚本中调用它。为此,请输入

   powershell -command "the powershell command(s)"

如果PowerShell命令要求使用引号,则必须使用单引号,以避免结束PowerShell会话。要转义字符,请遵循批处理脚本规则。可以在PowerShell命令中读取批处理变量,但是必须重定向在PowerShell中创建的值,以便以后在批处理脚本中使用。可以按照上面第12行中的方法完成,也可以使用PowerShell的Set-Content命令将其写入文件。我经常在批处理脚本中使用PowerShell来操纵文件数据。

  powershell -command "(Get-Content 'file.txt') -replace 'string','' | Select-String -Pattern 'keep lines with string' -SimpleMatch) -replace 'another string','to somthing different' | Set-Content 'file.txt'"

在增加或减少时间的情况下,PowerShell使任务变得容易。而且不需要您创建其他脚本。您可以将其他所有内容批量编写,使用对您有用的PowerShell命令,并将Windows脚本批量保存。

有关Get-Date和addDays如何工作的详细说明,请参考:

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-date?view=powershell-6

https://devblogs.microsoft.com/scripting/adding-and-subtracting-dates-with-powershell/