2

I am trying to create an arbitrary time using batch files. I am trying to subtract set values (such as 1 day, 1 month, and 2000 years) from my code to display the system time subtracted by the set values stated previously. For the hours and minutes, I am subtracting 10 hours and 10 minutes (shown in code as different values). I am also aware that date and time are variables related to my system. ~ Please ignore

Important - My problem now is with this part:

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

I can't seem to be able to make the minutes reset to 0 and have the hours add 1 when the minute value hits 60, and same with the hour-day, day-month, month-year relationships, other than that, the problems with my code are mostly fixed. When I run the code and wait for the minutes (or add to the time difference) to reach 60, they just pass 60 and don't reset nor add to the hoursb value.

.

My date and time formats are:

  • Short date: M/d/yyyy
  • Long date: dddd, MMMM d, yyyy
  • Short time: h:mm
  • Long time: h:mm:ss

I am using Windows 10.

Please note that the values in the set /a do not match my description, but of course they can be changed around. They are set to the shown numbers for test purposes only.

EDIT:

Code:

@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

Alright, so as you can see in the new edit to the code, I set the values to the stated at the beginning of this question. Subtracting 10 from the hours, subtracting 1 from the days and months, and subtracting 2000 from the years. I added 30 to the minutes to show the problem right now.

So my system time is 4:40, 1/5/2019. Alright?

The displayed time on the clock is 06:70, 04-00-19.

The desired outcome is 07:10, 04-12-18.

This was edited heavily. Thanks in advance.

16
  • Please note that: you should not include This is my second question....... We can learn it our own. Also, never include tag-names in your question titles. Note that rem is the 'official' comment for batch file; :: may cause unexpected behaviour sometimes. Also, you should note that date and time environment variables depend on user regional settings and are changeable. We could not verify your example that way. Please take a look at minimal reproducible example. What is the date-time format you are setting in the first lines of your program? edit your question to include/exclude what I have mentioned. Commented Jan 5, 2019 at 10:41
  • If you subtract the date 01/01/2000 from the time, e.g. 05:32, the resulting time will still be 05:32! Commented Jan 5, 2019 at 10:50
  • What do you need delayed expansion? Commented Jan 5, 2019 at 10:56
  • 2
    I suggest you to review these answers: Calculate time difference, Arithmetic operations with times and Calculate a duration between two dates... Commented Jan 5, 2019 at 11:56
  • double-beep: I have edited most of the post to fix the mistakes pointed out by you. I am aware that date and time are environment variables and I removed delayed expansion. I had delayed expansion there because I first tested it with seconds but after that I removed it because I found it to be harder. I forgot to remove the delayed expansion command but it is now edited out. Compo: I forgot to point out that I also want to subtract a number from the hours and minutes, but have done so in the edit. Commented Jan 5, 2019 at 11:58

2 Answers 2

1

You have a fundamental error in your description. When you subtract a number of days/months/years from a date, you are subtracting a date, not a number! For example, if today date is 05/01/2019 (obviously in DD/MM/YYYY format) and you want to subtract 1 month, the result should be 05/12/2018 because you are subtracting a date (1 month). If you subtract a number 1 from the month part, then the result will be 05/00/2019. For this reason, this problem should be solved via the well-known methods to add and subtract dates.

The problem with these methods is that they are valid just for a certain range of dates, and that ranges usually start in 1583. If you want to subtract 2000 from year 2018 and get 18, then such "year 18" is not a valid year in the usual date management methods. For this reason, besides to use the usual methods to manage dates, you also need to complete a couple small adjustments.

I taken the code segments linked in my comment and modified they slightly in order to solve this problem. I completed some tests and it seems to work correctly, but perhaps the method may fail in certain specific range of values.

@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%

A small example:

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 - I really would like to see a PowerShell solution for this problem. It seems that it would take just a simple and short line of code...

Sign up to request clarification or add additional context in comments.

5 Comments

Changed around parts of the code. Really like the end product now. Thanks for everything.
May I change the title of this question?
Any way to add merīdiem (am/pm)? Because with the results I cannot seem to be able to distinguish between it being day or night.
You can change the title of the question if you want.
PM hours are the values greater or equal 12 hours... You may convert a 24 hour value into AM/PM 12 hours value.
0

A simpler windows batch option is to call a PowerShell command from within your batch script to manipulate past and future dates.

Below, lines 8 and 9 create and format your arbitrary date.

 :: 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%

This will enable your batch script to create the end result you are looking for on your Windows 10 OS.

One of the great things about PowerShell is that it can easily be called from the cmd line and a batch script. To do so, enter

   powershell -command "the powershell command(s)"

If the PowerShell command calls for quotes, you must use a single quote to avoid ending the PowerShell session. To escape characters, follow batch scripting rules. Batch variables can be read in the PowerShell command, but values created in PowerShell must be redirected for later use in your batch script. This can be done as in line 12 above, or by using PowerShell's Set-Content command to write to a file. I frequently use PowerShell in my batch scripts to manipulate file data.

  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'"

In the case of adding or subtracting time, PowerShell makes the task easy. And it doesn't require you to create a different script. You can write everything else as batch, use PowerShell commands you find helpful, and save the windows' script as batch.

For detailed explanations on how Get-Date and addDays work, reference:

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

and

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.