A date calculation Keyboard Maestro subroutine

The release of Keyboard Maestro 10, with its addition of subroutines, and a couple of recent questions on the Keyboard Maestro forum regarding date calculations got me thinking that I should make a subroutine that calculates how many days it will be until the next Monday, Tuesday, Wednesday, or whatever weekday. And while I’m at it, I should do the same for the most recent Monday, Tuesday, etc. The calculations could be done in the same subroutine, with the difference being that upcoming days return a positive number and previous days return a negative number.

There are two reasons I decided to have the subroutine return a number instead of a date:

Date calculations of this type (when is the next/previous weekday?) are typically done using modulo arithmetic, which is basically division where you return only the remainder. Ideally, the language you’re programming in assigns the numbers 0 through 6 to the days of the week (which weekday is Day 0 doesn’t matter as long as you know what it is) and you add or subtract days mod 7 to get the weekday of interest.

Keyboard Maestro has a DOW() function which, if given no argument, returns an integer representation of today’s day of the week. The return value ranges from 1 (Sunday) to 7 (Saturday) instead of 0 to 6, but we can work around that.

Let’s say the number of the target weekday is stored in the variable LocalTargetWeekday. Then if we’re looking for the next target weekday, we do this calculation,

(LocalTargetWeekday - DOW() + 7) MOD 7

and if we’re looking for the previous target weekday, we do this

(LocalTargetWeekday - DOW() - 7) MOD 7

The important thing to know here is that Keyboard Maestro’s MOD operator returns a positive number if the number before MOD is positive and a negative number if the number before MOD is negative. This is why I add 7 in the “next weekday” formula and subtract 7 in the “previous weekday” formula. By doing so, I force the value before MOD to be positive or negative as needed. And adding or subtracting multiples of 7 doesn’t change the remainder.

Let’s show how the calculation works. If it’s Thursday (5) and I want to know how many days until the next Monday (2), the calculation is

\[(2 - 5 + 7) \bmod 7 = 4 \bmod 7 = 4\]

The number of days until next Saturday (7) is

\[(7 - 5 + 7) \bmod 7 = 9 \bmod 7 = 2\]

Similarly, to get the number of days until the previous Monday, it’s

\[(2 - 5 - 7) \bmod 7 = -10 \bmod 7 = -3\]

And the number of days until the previous Saturday is

\[(7 - 5 - 7) \bmod 7 = -5 \bmod 7 = -5\]

All of which are the answers we expect, including the signs.

There is still one ambiguity left. Suppose we want the number of days until the next Thursday. The formula gives

\[(5 - 5 + 7) \bmod 7 = 7 \bmod 7 = 0\]

Is this what we want? Maybe, maybe not. I can certainly anticipate some situations in which you want next to mean strictly next, in which case the correct answer is 7, and others in which you want it to mean today or next, in which case 0 is correct. So the subroutine should handle both of those situations.

Here it is.

KM Days Until Weekday

Instead of building the subroutine yourself, you can just download it.

As you can see, the subroutine is called with three arguments:

As you can see, any word that starts with “b” will make the subroutine look for the previous weekday, and any word that starts with “n” will make the search not strict. Also, Keyboard Maestro’s way of matching strings with the “starts with” option is not case-sensitive, so you can use “B” and “N,” too.

The subroutine would be used in a macro like this:

KM Next Monday

For more on Keyboard Maestro’s new features, you can go to the link I gave above or listen to the most recent Automators podcast episode.

I used to end a lot of my posts with music videos in which the lyrics matched up with something I wrote about. I should go back to doing that.