1

If I enter echo %date% in cmd I will get the date it is today. Let us say that today is Wednesday, 21/11/2018. If I type echo %date% cmd will print Wed 11/21/2018. Yesterday, it would have returned Tue 11/20/2018. The difference between these two dates (in days) is 1.

Is there any way I can do this kind of subtraction in command prompt? Something like:

set previous_date=Tue 11/20/2018
echo %date% - %previous_date%

I know this should be very easy to do in a programming language like python or VBScript, but I don't want to use any of those, unless it is absolutely necessary. I can download and use custom command line tools, but I want to do this with a batch file.

Anyone who knows how?

double-beep
  • 3,889
  • 12
  • 24
  • 35
Asif Ali
  • 261
  • 3
  • 11
  • Is there any maximum number of days? Or it could be any number? – Aacini Nov 21 '18 at 13:37
  • @Aacini any number. Even if you don't have the complete answer, just an idea on how this might be done, please share. You might point me in the right direction. – Asif Ali Nov 21 '18 at 13:39
  • It is relatively simple to get a difference when both dates are separated by a max of one month. Otherwise the method is more complex... I will post a partial answer soon. – Aacini Nov 21 '18 at 13:42
  • @Aacini thanks waiting – Asif Ali Nov 21 '18 at 13:43
  • @Aacini since you are involved I might as well tell you why I need this. I have a bat file in my Startup folder that runs a process once a week. It does this by checking the current day and running the process if its monday `if %date:~0,1%==M ()`. Problem is I need this process to launch `AT LEAST` once every 7 days. But if say I forget to open my laptop on a particular monday this it doesn't launch the process until the next monday. So now I simply want to change the logic to `launch the process if it hasn't been launched for at least 7 days`. regardless of what day it is. – Asif Ali Nov 21 '18 at 13:56
  • Now you might be wondering how do I even fetch the previous date. I mean you can't connect a bat file to a database can you? Well I did manage to discover a clever way to do this without any database. Will tell you if you wanna know. This question is the only missing piece in the logic. – Asif Ali Nov 21 '18 at 14:01
  • Batch scripting is not well suited for date maths, because there is actually no such data type; you could however borrow from other languages, like PowerShell, JavaScript, VBScript, for instance, and do the difference computation there; in pure batch programming, you had to implement it on your own, handling locale-dependent date formats, leap years, etc.... – aschipfl Nov 21 '18 at 14:16
  • Related: [Date time difference in batch script](https://stackoverflow.com/q/47532900). – aschipfl Nov 21 '18 at 14:18
  • @aschipfl I do want to "implement it on my own". I am not here for the answer so much as I am here for the right direction. – Asif Ali Nov 21 '18 at 14:19
  • I suggest thr following: When your job actually runs (i.e. when the 7-day condition is met), create or update a file by running something like `echo 1 >"c:\some\file.txt"`. Then to test if it is time to run again by using `robocopy /minage:7 "c:\some\file.txt" "c:\some\test.txt"`. This will only copy the file if it is at least 7 days old. Check if it exists with `if exist "c:\some\test.txt" goto TIME_HAS_COME`. Don't forget to `del /y "c:\some\test.txt"` afterwards. – Jack White Nov 21 '18 at 20:55
  • @JackWhite that might be it thanks – Asif Ali Nov 22 '18 at 07:37
  • @JackWhite your solution works! – Asif Ali Nov 22 '18 at 08:08
  • @aschipfl please unmark this question as duplicate. I got the answer which is nothing like the question with which you have marked MY question as duplicate. – Asif Ali Nov 22 '18 at 08:10
  • Also related: [Calculate time difference in Windows batch file](https://stackoverflow.com/q/9922498). – aschipfl Nov 22 '18 at 08:58
  • @AsifAli, I unmarked it, because the linked question is about time but not date difference (although it is almost the same). Anyway, I am curious about your solution... – aschipfl Nov 22 '18 at 09:00
  • @aschipfl thanks for understanding – Asif Ali Nov 23 '18 at 16:11

2 Answers2

3

In one of your comments you say:

I have a bat file in my Startup folder that runs a process once a week. It does this by checking the current day and running the process if its monday if %date:~0,1%==M (). Problem is I need this process to launch AT LEAST once every 7 days. But if say I forget to open my laptop on a particular monday this it doesn't launch the process until the next monday. So now I simply want to change the logic to launch the process if it hasn't been launched for at least 7 days

That's what TaskScheduler is built to take care of. No need to mess with date calculations or even language dependend formats of %date%.

Start TaskScheduler
"Create Task" (do not "Create Basic Task")
in "Triggers" set to "Weekly", "Recure every 1 weeks on: Monday
in "Settings" check "Run task as soon as possible after a scheduled start is missed"
Fill also the "General", "Actions" and "Conditions" tabs to your needs.

Stephan
  • 47,723
  • 10
  • 50
  • 81
  • thanks for your answer, although I used Jack White's way of doing it, yours probably also works. Hopefully it will help someone else reading this question in the future. – Asif Ali Nov 23 '18 at 16:10
1

(I have previously posted this in the comments because the question was locked. Since it is now unlocked I am submitting this as an answer)

Batch scripting language does not have any built-in means to calculate time difference. This problem may be solved through various means such as:

  • Write it using other scripting languages such as VBS, AutoIt, PowerShell, etc.
  • Download existing external program such as unix date utility from gnuwin32 coreutils (manual, recipe). Use for to get output of date "+%%s" into a variable, then use set /a to calculate the difference.
  • Parse output from built-in date command or %date% variable. This is discussed in great detail elsewhere (A, B, C, D, E) but be aware that it may be affected by OS locale time/date representation, and it is also hard to take leap years into account properly if you need precision.

I'd like to share another trick: using file creation date difference. It is still a somewhat of a hack, but is arguably more portable than parsing %date% by hand.

Here is an example, explanation below:

if not exist "c:\some\marker.txt" goto RunTheJob
robocopy /minage:7 "c:\some\marker.txt" "c:\some\test.txt"
if exist "c:\some\test.txt" goto RunTheJob
goto SkipTheJob

:RunTheJob
del /y "c:\some\test.txt"
echo 1 >"c:\some\marker.txt"
rem ... THIS RUNS ONCE IN 7 DAYS ...

:SkipTheJob

Whenever we run the job (i.e. once in 7 days) we also create (or update) a "marker" file (c:\some\marker.txt in the example). Contents and location of this file do not matter, only date of its modification does, so I just write character 1 into it with echo 1 >YOUR_FILENAME

This also neatly solves the problem of storing date information somewhere.

Now to test if at least 7 days passed since the job last ran you need to check if the file is at least 7 days old. Easiest way is with robocopy utility - its /minage:NNN parameter only copies the file if it is at least NNN days old.

So we periodically try to copy the file and see if it succeeds. We do this by checking if copied file (c:\some\test.txt) exists like this: if exist YOUR_FILENAME goto YOUR_LABEL

Finally, if the file was copied it is no longer needed and we need to delete it with del /y YOUR_FILENAME. /y overrides confirmations just in case and may normally be omitted.

If the marker file is ever deleted for any reason, the first line in the example makes sure that job (I'm assuming some kind of backup or something like that) is started right away. If it wasn't there, the file would never be copied because the original would not exist in the first place, so the job would never run in this situation.

Quirks:

If some program updates the modification date of a "marker" file for some reason, the job will be delayed. If this is undesired you should put this file somewhere out of reach, such as %AppData%\Roaming\YOUR_SCRIPT_NAME folder. Same thing may happen if the file gets restored from a backup.

To work around such a problem you may consider compressing the marker file into an archive such as zip, but this also requires external programs, VBS or PowerShell. It might be possible to somehow abuse built-in Windows Backup utility (sdclt) instead but I have not found a way.

Jack White
  • 849
  • 4
  • 7
  • thanks for the detailed info. Thanks to you I got what I wanted when I posted my question on stackoverflow. File age! so simple, yet genius. – Asif Ali Nov 23 '18 at 16:08