The Daily Parker

Politics, Weather, Photography, and the Dog

Olé, olé olé olé!

Oh, I love these stories. On today's Daily WTF, editor Remy Porter describes the world I grew up in, where dates were dates and 30 December 1899 ruled them all:

If you wanted to set a landmark, you could pick any date, but a nice round number seems reasonable. Let's say, for example, January 1st, 1900. From there, it's easy to just add and subtract numbers of days to produce new dates. Oh, but you do have to think about leap years. Leap years are more complicated- a year is a leap year if it's divisible by four, but not if it's divisible by 100, unless it's also divisible by 400. That's a lot of math to do if you're trying to fit a thousand rows in a spreadsheet on a computer with less horsepower than your average 2019 thermostat.

So you cheat. Checking if a number is divisible by four doesn't require a modulus operation—you can check that with a bitmask, which is super fast. Unfortunately, it means your code is wrong, because you think 1900 is a leap year. Now all your dates after February 28th are off-by-one. Then again, you're the one counting. Speaking of being the one counting, while arrays might start at zero, normal humans start counting at one, so January 1st should be 1, which makes December 31st, 1899 your "zero" date.

Our macro language is off-by-one for the first few months of 1900, but that discrepancy is acceptable, and no one at Microsoft, including Bill Gates who signed off on it, cares.

The Basic-derived macro language is successful enough inside of Excel that it grows up to be Visual Basic. It is "the" Microsoft language, and when they start extending it with features like COM for handling library linking and cross-process communication, it lays the model. Which means when they're figuring out how to do dates in COM… they use the Visual Basic date model. And COM was the whole banana, as far as Windows was concerned- everything on Windows touched COM or its successors in some fashion. It wasn't until .NET that the rule of December 30th, 1899 was finally broken, but it still crops up in Office products and SQL Server from time to time.

The .NET epoch began 1 January 2000. Except for DateTimeOffset values, whose epoch began on the non-existent date 1 January 0. Or DateTime values (now deprecated) which start at the beginning of the Gregorian calendar in 1753. (Same with SQL Server datetime types.)

The bottom line: dates are hard.

Comments (3) -

  • David Harper

    2/6/2019 9:21:18 AM +00:00 |

    "Or DateTime values (now deprecated) which start at the beginning of the Gregorian calendar in 1753."

    Only in the English-speaking world.  Most of the rest of Europe switched to the Gregorian calendar in 1582 or soon afterwards.

  • The Daily Parker

    2/6/2019 5:10:26 PM +00:00 |

    Yes, exactly. Which is why George Washington has two birthdates, depending on which calendar you mean.

  • David Harper

    2/7/2019 6:39:19 AM +00:00 |

    There's also the fact that 1 January was not always New Year's Day in the English-speaking world.  That custom was only adopted in 1752, along with the Gregorian calendar.  Before that, the year changed on 25 March, so, for example,  the day after 24 March 1710 was 25 March 1711.  The old practice lives on in the English tax year, which starts on 6 April.  That's 25 March, adjusted by 11 days for the Gregorian calendar in the 18th century, plus another day for 1800, which would have been a leap year if Britain had continued to use the old calendar.

Comments are closed