chrisjfinlay
chrisjfinlay

Reputation: 82

Windows Batch thinks 2AM is after 5PM

Bit of a weird one. I've been messing around with windows batch and time comparisons to schedule a task. Now I know there's a million better ways to do it, but our work machines are pretty locked down, so a batch script seems like the easiest way to actually achieve what I needed without some crazy workaround. I'm also well aware that the idea behind this is pretty gross. I'm not looking for perfection here, I'm just looking for it to work.

Basically at 17:00 on the 23rd November, I needed to move a file from one place to another. Problem is that I wouldn't actually be physically present at that time due to some other commitments, so I figured a batch script that was stuck in a loop of nothing until a certain date/time would work. So I cobbled together the following quickly the night before:

:dateloop
if %date% LSS 23/11/2019 goto dateloop
:timeloop
if %time% LSS 17:00 goto timeloop
<xcopy operation goes here>

And ran it overnight. So imagine my surprise when I came to my machine the next morning to check my emails and noticed that the file had been moved. Thankfully I was able to revert the file and rescheduled my day to do it manually.

I ran some tests last night, making sure that the script didn't exit upon completion so I could read the echo output. And it turns out that it was all running fine until 2:00, when the script decided "yes, this is after 17:00".

I could test it again tonight, and I do plan to, with the time format written out the long way (17:00:00:00) but I was wondering if anyone could confirm before I do, as that's a good while away, if this is the cause of my problem?

Upvotes: 2

Views: 66

Answers (2)

DodgyCodeException
DodgyCodeException

Reputation: 6123

If you type IF /? at the command prompt, the help text will include this:

If Command Extensions are enabled IF changes as follows:

    IF [/I] string1 compare-op string2 command
    IF CMDEXTVERSION number command
    IF DEFINED variable command

where compare-op may be one of:

    EQU - equal
    NEQ - not equal
    LSS - less than
    LEQ - less than or equal
    GTR - greater than
    GEQ - greater than or equal

and the /I switch, if specified, says to do case insensitive string
compares.  The /I switch can also be used on the string1==string2 form
of IF.  These comparisons are generic, in that if both string1 and
string2 are both comprised of all numeric digits, then the strings are
converted to numbers and a numeric comparison is performed.

As you can see, comparison is on strings unless the strings to compare contain only numeric digits. As time contains the non-numeric characters ":" and ".", the time is treated as a string, and of course "2" comes after the "1" from "17:00".

However, with the command echo [%time%] you'll notice that if the time is less than 10, it adds a space at the front. Therefore, you can get correct results with a string comparison as long as you take the space into account. So replace your problematic statement with the following one:

if "%time%" LSS "17:00" goto timeloop

That should fix it.

Upvotes: 1

npocmaka
npocmaka

Reputation: 57282

If compares strings alphabetically or numbers. You need to rework your code and compare times as numbers. So you also need a reliable way to get date parts as numbers - date and time variables are not suitable because they can be in different formats depending on your settings.

Try this instead:

@echo off
::GOTO comment macro
set "[:=goto :]%%"
::brackets comment macros
set "[=rem/||(" & set "]=)"

for /f %%# in ('wMIC Path Win32_LocalTime Get /Format:value') do @for /f %%@ in ("%%#") do @set %%@

%[:%
    echo %day%
    echo %DayOfWeek%
    echo %hour%
    echo %minute%
    echo %month%
    echo %quarter%
    echo %second%
    echo %weekinmonth%
    echo %year%
%:]%


:dateloop
if %year%%month%%day% LSS 20191132 goto dateloop
:timeloop
if %hour%%minute% LSS 1700 goto :timeloop

Upvotes: 1

Related Questions