How many Thursdays?
October 20, 2021 at 11:51 PM by Dr. Drang
A couple of weeks ago, this question from ldebritto appeared in the Automators forum:
I was looking for a way to have Shortcuts peek into last month’s calendar and count how many Thursdays were that month (4 or 5).
Any ideas on how to make it?
Stephen Millard, who posts there under the name sylumer, answered the question with a straightforward shortcut that loops through the days of last month, counting the Thursdays it meets along the way. It’s the kind of solution I employ often: a brute force approach that can be written quickly and uses looping instead of excessive cleverness. And in this case, since there can’t be more than 31 trips around the loop, it will run extremely fast. It’s a good solution.
But it nagged at me. This blog has a long history of showing calendrical calculations, and I had written a post on a similar problem (finding months with five Fridays, Saturdays, and Sundays) eleven years ago. The scripts in that post had some brute force aspects, but they also took advantage of how months are structured to filter the loops. I wanted to do something similar for the “how many Thursdays” problem.
As ldebritto said in his question, every month has either four or five Thursdays (indeed, four or five of any weekday). Whether it’s four or five depends on the number of days in the month and the date of the first Thursday of the month. We’ll consider each of these pieces of information and how they affect the answer.
Since every month has 28–31 days, we know that each month has four weeks plus 0–3 “extra” days. If the date of the first Thursday is less than or equal to the number of extra days, there will be five Thursdays in that month. For example:
- The first Thursday of September 2021 was on the 2nd, and there are 2 extra days in September. Since 2 ≤ 2, there were five Thursdays that month.
- The first Thursday of August 2021 was on the 5th, and there are 3 extra days in August. Since 5 ≰ 2, there were four Thursdays that month.
The logic is simple, but implementing it in Shortcuts takes a little effort because there’s no “date of the first Thursday” function. Instead, we’ll figure out how many days from the first of the month to the first Thursday. And because this is one less than the date of the first Thursday the “less than or equal to” comparison we used above will turn into a simple “less than” comparison.
So how do we get the number of days from the first of the month to its first Thursday? We’ll need to use custom date formatting codes and do a little modulo arithmetic. Here’s the whole shortcut:
Step | Action | Comment |
---|---|---|
1 | Get the current date | |
2 | Move to the start of this month. We call this magic variable StartOfThisMonth . |
|
3 | Go back one month. We call this magic variable StartOfLastMonth . |
|
4 | Get the number of days between StartOfLastMonth and StartOfThisMonth , which is the length of last month. |
|
5 | Get the number of days over 4 weeks in last month. We call this magic variable ExtraDaysInMonth . |
|
6 | Format StartOfLastMonth with the c code, which gives the day of the week as a number from 1 (Sunday in my locale) to 7 (Saturday). |
|
7 | This is where we do the modulo arithmetic to get the number of days from the start of last month to last month’s first Thursday. We call this magic variable DaysToFirstThursday . |
|
8 | If this is true… | |
9 | Return 5. | |
10 | Otherwise… | |
11 | Return 4. | |
12 | End If block. | |
13 | Show the answer. |
The only tricky parts here are Steps 6 and 7. Custom date formatting patterns in Shortcuts follow Unicode Technical Standard #35, where c
will give the day of the week as a digit from 1 to 7. In my locale Day 1 is Sunday and Day 7 is Saturday; it may be different where you live.
Step 7 uses the number we got in Step 6 and calculates the number of days from the start of the month to the first Thursday. This involves modulo 7 arithmetic, so the first thing we have to do is subtract 1 from the Step 6 result. Numbers in mod 7 go from 0 to 6, not 1 to 7. After subtraction, we’re in a day numbering system where Thursday is 4. To get the number of days from the start of the month to the first Thursday, we subtract the weekday number from 4, add 7 (to force a positive result), and then get the remainder (mod
) after dividing by 7.
Let’s do a couple of examples. If I run the shortcut today, last month is September 2021, which started on a Wednesday. Step 6 returns 4, and Step 7 returns
(4 - (4 - 1) + 7) mod 7 = (4 - 3 + 7) mod 7 = 8 mod 7 = 1
which makes sense, as there’s one day from the start of September 2021 to the first Thursday of the month.
If you’re wondering why we bothered adding 7 and doing the mod
stuff—why not just do 4 - (4 - 1) = 1?—think of what happens when we run the shortcut next month. October 2021 starts on a Friday. Step 6 returns 6, and Step 7 returns
(4 - (6 - 1) + 7) mod 7 = (4 - 5 + 7) mod 7 = 6 mod 7 = 6
and there are, in fact, 6 days from the start of October 2021 to the first Thursday of the month. Here, without the + 7
we would have gotten a result of -1 which is not the number of days from the start of October to its first Thursday. By including the + 7
and mod 7
terms, we have an equation that handles all cases.
This is not nearly as easy to understand as Stephen Millard’s solution, so I didn’t post it to the forum. On the other hand, his solution didn’t exercise my modulo muscles.
By the way, it didn’t take me two weeks to work this out. I had the shortcut written the day of the question, but I soon learned that my splitflow
script for creating the table of Shortcuts steps you see above was broken. The Shortcuts team changed the look of the app, and the computer vision functions that splitflow
uses weren’t able to figure out the top and bottom boundaries of the steps. So I put this post on ice until I had energy to update splitflow
. It still needs some work—the padding above the steps shouldn’t be wider than the padding below—but it’s passable.