Hi, Kevin.
Yes. There’s plenty of slack for it to work with any month. But the idea takes a little getting used to! It works with any number of seconds between 28 days and about 29.5 days. 2500000 is a number in that range that happens to be easy to remember.
I actually explained the principle of this method last week in the bottom (fifth) post of this thread. The double negative is a bit confusing. It’s to get round a bug that existed in AppleScript’s internal date math routines before OS X Tiger. (It may have been fixed in Panther, but I didn’t get that, so I don’t know.) The bug was that if you subtracted one date from another, and they were both earlier than 1904, then the system threw an error. (Obviously, this bug wasn’t encountered very often!) However, it didn’t occur if a later pre-1904 date was subtracted from an earlier one ” only if the earlier one was subtracted from the later, or if the dates were the same.
Richard Hartman’s version of Emmanuel’s “French Vanilla” method looked like this:
copy theDate to b
set b's month to January
set m to 1 + (theDate - b) div 2500000
The logic of the last line is easier to follow here:
- Subtract the January date from the date being tested. Since the two dates have the same year, day, and time, the result is exactly the same as the number of seconds from the beginning of the year to the beginning of the month whose number we want.
- Divide the result by a number in the range that works and discard the remainder. There’s enough headroom and floor-room to ensure that the result is the same as the number of calendar months that precede the tested month in the year and that any inaccuracies are discarded with the remainder.
- Add 1 to get the number of the tested month itself.
This works well enough for most reasonable purposes, but will error on earlier systems if the test date is earlier than 1904. Obviously, this is because the January date will also be earlier than 1904 and will be earlier than, or the same as, the test date. My own last line is a rearrangement of the maths to get round the bug.
set m to (b - 2500000 - theDate) div -2500000
Subtracting 2500000 before a division by -2500000 adds an extra 1 to the result and so is equivalent to the added 1 in the original last line. Here, it’s subtracted from the January date first, so that even if theDate is a January date itself, it’ll be subtracted from a date that’s earlier than it, thus avoiding the bug. This leaves a negative number of seconds which, when divided by a negative divisor, gives a positive result.
The object of the exercise when these routines were written was to get them to be as fast as possible by keeping the number of operations to a minimum. My last line has the same number of mathematical steps as Richard’s original, but is two date subtractions and an integer division, as opposed to the original’s one date subtraction and two integer operations. Mine is therefore probably a nanosecond or two slower.