>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.
I definitely thought the conclusion was going to be something like: "We need to loop over every day to count Thursdays, because of calendar shenanigans in August 1632 in Russia and February 1295 in the Holy Roman Empire, which caused there to be 0 and 21 Thursdays, respectively." Maybe I've read too many "Falsehoods Programmers Believe about X" articles.
(The exceptions mentioned are made up. I don't know of any month that had a number of Thursdays other than 4 or 5.)
In Britain and the (then-future) USA, September 1752 had three Thursdays - Wednesday, September 2 (Julian) was followed by Thursday, September 14 (Gregorian), and then there was Thursday the 21st and 28th. That month had only two Sundays and two Mondays. Other countries that made the Julian-Gregorian transition at other times will have similarly short months somewhere else in their history.
There might be an instance of six of the same weekday in a month, if some area repeated the right day while moving from the Asian side of the international date line to the American side. Alaska's the only example I can find, but they also switched from Julian to Gregorian at the same time, so they had Friday, October 6, 1867 (Julian) followed by Friday, October 18, 1867 (Gregorian).
Samoa skipped a Friday in December 2011 [1]. There were 4 Fridays left so "4 or 5" still holds, but using arithmetic to calculate the number of Fridays would have yielded a wrong answer.
This is pretty uncommon with whole days so maybe less important, but thinking in this way (how can I optimize this annoying code) often leads to wrong arithmetic around hours (daylight savings and time zone changes) or seconds (leap seconds).
I generally tend to (perhaps superstitiously) do things the "slow way" like this, for exactly this reason.
This kind of thing is also generally why I don't understand people who don't like "dependencies" in general. If something requires specialized knowledge, I would much rather let the specialists work on it, than arrogantly assume I know enough to do it myself correctly.
1. Complex libraries and mechanisms that you couldn't (or are complex enough that you wouldn't) make on your own.
2. leftpad.
The former is worth using in many situations. I would not make any kind of network protocol implementation myself in most cases because, while I can, I don't have time to do it correctly (vice hiring a proper expert or purchasing/using an expert made implementation).
The latter is the garbage that causes problems, for various reasons. The ubiquity, for instance, of this totally trivial package broke a lot of other systems when they could have been replaced with a very small (and easily shown correct) bit of your own code. The other problem is that they are opportunities for corruption of your system. The more dependencies you have (direct or indirect via transitive dependencies) the more attack surface area (poor code permitting an attack) or potential for others to insert attacking code (the code isn't just insecure, but it's actually the attack itself).
The problem with dependencies is that you start relying on Other People's Support, and that can vary from package to package.
The support you get from the Apache Foundation is going to be a lot different than the support you get from, say, a React community-maintained fork of an originally JQuery component that builds some oddly specific finicky frontend paradigm.
This seems to be very much the point. I suspect there's actually disagreement about whether the thing actually requires specialized knowledge. If there were actually 700 days of February 1295 in the Holy Roman Empire, what are the chances that month would be handled correctly by any layer of my Thursday-counting Saas platform? A lot of times the "specialists" are just as likely to say something like "Dates before 1900 are not supported because they're too hard". And your app probably didn't care about those cases anyway.
My first solution in shell would have been horribly unportable across locales (though perhaps adding LC_ALL=C would fix that):
echo $(($(cal -3|cut -c13-14|grep -cv ' ')-2))
+ cal -3 will print 3 months spanning the current date(default horizontal on most modern cal implementations).
+ Grab characters 13,14 (the Thursday column of the first month).
+ grep to eliminate blank entries
+ There is no English language month+4 digit year that will not have at least 1 character in the Thursday column, and of course the "Th" header is also there, so subtract 2 from the result
336 bytes. Even 168 bytes because half byte is 16 values and we need only 7, so pack two answers in one byte. Even 126 bytes if we pack blocks of 3 bits. Seem reasonable even for embedded.
There's a very quick way to figure out the day of the week for a given date (dd/mm/yyyy) using Zeller's Congruence[0]. By figuring out the day of the week for the first of the month and knowing how many days in the month (with an allowance for leap years), it's easy to then calculate the number of Thursdays.
This uses the GNU version of sed and the BSD versions of everything else. Roughly: print the calendar, transpose the data, get the line with only Thursdays, count the spaces between the dates fo the Thursdays. Just realized I have a picket fence error. You can fix that. Also it's the wrong month. Also it's horribly unportable. Also it rocks.
cal | sed 1d | rs -T | grep Th | sed -e 's/\( \+$\|^Th \+\)//g' -e 's/ \+/_/g' -e 's/[^_]//g' | wc -c
Hmm, thinking about this, you get the day of the week w plus the day number d of the last day of the month. If d=28, then return 4. Otherwise, assuming w=0 is Monday,¹ we'll then calculate wʹ = w - (d - 29). Rebase everything mod 7 and if dʹ ≤ 3 ≤ d, there are 5 Sundays, otherwise there are four.
⸻⸻⸻
1. If w=0 is Sunday, we'll add 6 ≡ -1 (mod 7) to w to rebase our modulo arithmetic.
Funny enough - in SQL you could just write a query if you have a standard date calendar, and I think it would be almost as fast as any solution - and really flexible for however you wanted to format.
>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.