What Am I Doing Wrong Comparing Date Text Variables?

I'm trying to compare two date variables but I'm obviously not understanding how to do it.

I've greatly simplified the macro to store the same %ICUDateTime% value to two variables. I then compare the variables and it never says they are equal (I've tried matches, =, is to no avail). Note that when I use Display text in a window, it shows the values as exactly the same. However it never goes through the "If All Conditions" branch as true.

You have errors in this part:

The first field can take the Variable name directly as you have it, (although you should choose Variable rather than environment Variable as the type) but the second field is a text field so, you can't just write the Variable name without telling Keyboard Maestro it is a Variable.

As you have written it at the moment you are comparing whatever value is held in the Variable nextExecutionTime with "currentTime" as a piece of text. It would only match if your first Variable nextExecutionTime was actually storing the text "currentTime"

You need to quote the Variable in the second field like this:


Then Keyboard Maestro will look at the value stored in the Variable currentTime

It might seem odd that it works this way until you consider that this Action is not set up to compare two Variables. It is set up to compare one Variable with a bit of matching text. But by quoting the second Variable you can lever it to compare two Variables.

Also I think you should not use "matches" but instead use "is".

"Matches" is for regular expression matches, not text string equality -- try "is" or "is exactly" (depending on context) instead.

Also, nextExecutionTime is not strictly speaking an environment variable -- it's a KM variable. Even if, as @Zabobon's post suggests, you can access KM variables in that way (I'm not so sure but, after all, KM variables are made available to shell scripts as environment variables) it's a round-about way of doing it and could confuse you later.

Either directly test the variable's contents:
...or compare the two variables as text strings:
...whichever makes more sense to you.

Also, I'll continue my crusade for "variable scoping" -- it's a rule of thumb in programming to scope your variables as tightly as possible to avoid unintended alteration. If you don't need to make a variable available outside of this instance of the macro then make it a Local variable, as above. See the manual for more about scoping.

1 Like

I tried both:


Both still were False.

You are calling your first Variable an environment Variable when it is simply a Variable.

If the Variable is... Not if the environment Variable is...

@Nige_S spotted that before me and I have edited my first reply to mention this error too.

By the way what is environmental variable?

Thank you! That worked when I made that change.

And I had the same question as @RazMastero, so I found this.


Well, maybe I have another problem. The above worked successfully when I set both variables to the same value. However when I modified my intended macro with the same logic, it still fails.
What I'm attempting to do is run this macro only during a certain random time range, starting at a constant time. I want it to run once, then quit for the day. All that shouldn't matter, but it seems like they do, since it made the branch False again every time.

I tried it both ways that @Nige_S recommended, using variable and text comparisons, but that did not seem to matter.

Here is what I have:

Then what you could do is have a single defined trigger time, a randomly-generated number of seconds encompassing your time range, and start the macro with a pause for that number of seconds -- skip those date stamp comparisons altogether!

Otherwise, we're missing important stuff in the image above. Post the macro itself so we can see what's going on -- instructions here.

First off, thanks for taking the time to help me.
From what I understand, the pausing of a macro consumes a considerable number of computer resources, since it does not release back to the OS until it fully completes. That's why I chose this approach.

Anyway, here is my complete but incomplete macro.
Randomize Schedule for Morning - WIP.kmmacros (6.4 KB)

Very little really, if it's a "timed" pause -- a "Pause until" an image was detected on screen would be a another matter, of course. Try it for yourself with Activity Monitor running -- for me it's ~1% of one core in CPU terms and a couple of MB of RAM (though that'll depend on what variables you are storing).

For your macro -- your variables won't ever test as equal because you've got 2 spaces at the start of your currentTime formatting -- % EEE -- which you haven't in your nextExecutionTime format -- %EEE. Not easy to spot, but you can just see a different gap between the "->" and the value at the bottom of each action where it shows how the variable will be set.

The macro will trigger at 09:35 and your RANDOM function will always set the minutes to 35 (it returns from the first number to, but not including, the second -- and the "minute" entry requires an integer so any .nnnn of the real is ignored). So, as it stands, your times will only ever be equal if the macro triggers at exactly 09:35:00 and the currentTime variable is set within one second -- possibly not what you are intending.

How much of a time spread do you want? Any other constraints, eg Keyboard Maestro shouldn't be launched? Those could inform the best way of doing things.

I'll have to investigate the resources...that's a good thought.

As for the EEE, you're right I didn't catch that.

For the Random function, I only have those values so that I can kick it off immediately for the test. Normally I would have it as a 30 minute window -- RANDOM(0,30)

And to check the values, note the Display window I use to show the value of both nextexecutiontime and currenttime. In every "failure" branch, they show as equal. So either it's now showing the full variable, or it's rounding to some difference between the two.

I now understand what you meant by variables never equal except if the nextexecutiontime has an offset of zero. that is a problem. I'll try your other approach to have a pause in the script and watch resources. I got my info on resources from this post.

As an aside, the correct path was taken when I fixed the % EEE you found.


I'll draw you attention to this one line of @peternlewis's:

And while it would certainly be possible for it to be more efficient in the case where it has a single macro running sitting in a timed pause, it is not exactly a typical case.

Although it is our typical case :wink:

It's always going to be a balancing act -- each instantiation of a macro requires resources, so do you take that hit just once then pause, or take it every minute (or even every second)? It'll depend on a lot of things -- number and size of variables, number and type of actions taken before reaching the "do we continue" point, how resource-limited you are in the first place, etc, etc so you'll have to make your own choices.

Given you seem to only want a 1 minute resolution, the approach Peter describes in that post seems quite reasonable. And notice that he's just using "seconds since epoch" and isn't wasting cycles with time stamps -- although you may want them for logging purposes.