5

How is it possible to compare 2 dates in batch files? This:

if %%newdate geq %olddate%  _do smth_

does not work.

In this case I have that
27.05.2013 is greater than 15.07.2013 and
14.07.2013 is less than 15.07.2013

Zhenya

Endoro
  • 37,015
  • 8
  • 50
  • 63
Zheden
  • 583
  • 2
  • 11
  • 36

5 Answers5

9

try this:

set "sdate1=%olddate:~-4%%olddate:~3,2%%olddate:~0,2%"
set "sdate2=%newdate:~-4%%newdate:~3,2%%newdate:~0,2%"
if %sdate1% GTR %sdate2% (goto there)  else echo here
Endoro
  • 37,015
  • 8
  • 50
  • 63
  • I think that when using quotes it then forces an ascii compare so you should use the bare variables `if %sdate1% GTR %sdate2% echo %olddate% is greater than %newdate%` – foxidrive Jul 15 '13 at 10:50
  • @foxidrive yes, you are right with the numeric compare. But I think in this special case this doesn't make a difference. Nevertheless I made an edit. I had not thought much about it before :) and numeric compare is better and safer. – Endoro Jul 15 '13 at 11:00
  • 1
    You are right that it doesn't matter in this case. In fact if the numbers are very large then it's even a benefit to quote them, when the math limit is exceeded. – foxidrive Jul 15 '13 at 11:12
  • This technique depends on date format used dd/MM/yyyy – Ricardo Bohner Jan 07 '22 at 21:21
2

You should always use the ISO format for dates (yyyy-MM-dd HH:mm:ss). This makes it unambiguous, locale agnostic, they sort chronologically and you can easily compare them as strings in CMD files.

For /F "tokens=1,2 delims==" %%i in ('wmic os get LocalDateTime /VALUE') do (if .%%i EQU .LocalDateTime set ldt=%%j)
set CURRENT_DATE=%ldt:~0,4%-%ldt:~4,2%-%ldt:~6,2%
set CURRENT_TIME=%ldt:~8,2%:%ldt:~10,2%:%ldt:~12,2%

This will give you:

CURRENT_DATE in yyyy-MM-dd format
CURRENT_TIME in HH:mm:ss format
SecretAgentMan
  • 2,856
  • 7
  • 21
  • 41
Tim
  • 66
  • 2
1
call :date_to_number %date1% date1
call :date_to_number %date2% date2

if %date1% GEQ %date2% echo date1 is bigger

goto :eof
:date_to_number
setlocal
if "%~1" EQU "" goto :eof
for /f "tokens=1,2,3 delims=." %%D in ("%~1") do (
  set "the_date=%%F%%E%%D"   
)
endlocal & if "%~2" neq "" (set %~2=%the_date%) else echo %the_date%
goto :eof

But this will work only with dates in format DD.MM.YYYY

npocmaka
  • 55,367
  • 18
  • 148
  • 187
0

I had an issue where I wanted to find users who's passwords had expired, or were about to expire.

So for starters, Windows 10 has changed the format of the %date% variable so it looks different than previous versions. therefore, the output of "echo %date%" looks like: "Thu 05/09/19" so I use this one liner to take today's date and convert it to yyyymmdd format.

set today=20%date:~-2%%date:~4,2%%date:~7,2%

(today = 20190509)

this is easy because we know that there is exactly 2 digits for each month and day.

Now, if the "date format" that you are working from does not pad the single digit months and days with a preceding zero, you will have to to pad them yourself. For example, the output of the command: net user %username% /domain looks like "5/9/19", note the missing zeros...

So you can extract this a couple different ways. the simplest way is to grab each field seperately, drop a zero in front of the month and day variables, and then grab only the last two digits of them. that way 5 becomes 05, and 12 becomes 012, and then goes back to 12.

for /f "tokens=3-5 delims=/ " %%a in ('net user %username% /domain ^|find /i "Password expires"') do (
set mm=0%%a& set dd=0%%b& set yyyy=20%%c
set expires=!yyyy!!mm:~-2!!dd:~-2!
if NOT !expires! GTR %today% echo Password has expired and needs to be changed. 
  • the format of the `%date%` variable isn't related to the Windows version. It's a user setting. Better use a [language independent method](https://stackoverflow.com/a/18024049/2152082) to get the date. – Stephan May 10 '19 at 18:19
-1
I create a simple c program i call newest.exe. Below is the source code.

#include <stdio.h>
#include <sys/stat.h>
#include <time.h>

// syntax:  newest file1 file2
//
//   if age1 = age2, prints  0 age1 age2
//   if age1 < age2, prints  1 age1 age2
//   if age1 > age2, prints  2 age1 age2
//   where
//      age1 is age of file1 is seconds.
//      age2 is age of file2 is seconds.
//
//   To capture the output in a DOS bat file use:
//      for /f "tokens=1-3" %%i in ('%srcPath%\newest.exe %src% %des%') do (
//         set newest=%%i
//         set age1=%%j
//         set age2=%%k
//      )


int main(int argc, char **argv)
{
   struct stat fileStat;
   time_t now;
   long age1, age2;

   if(argc != 3)
   {
      printf("syntax: %s File1 File2\n", argv[0]);
      return 1;
   }

   now = time(NULL);

   if(stat(argv[1],&fileStat) < 0) return 1;
   age1 = now - fileStat.st_mtime;

   if(stat(argv[2],&fileStat) < 0) return 1;
   age2 = now - fileStat.st_mtime;

   if( age1 == age2 )
      printf("0 %d %ld\n", age1, age2);
   else if( age1 < age2 )
      printf("1 %d %ld\n", age1, age2);
   else
      printf("2 %d %ld\n", age1, age2);

   return 0;
}