kccqzy 5 hours ago

I wrote my own date calculation functions a while ago. And during that, I had an aha moment to treat March 1 as the beginning of the year during internal calculations[0]. I thought it was a stroke of genius. It turns out this article says that’s the traditional way.

[0]: https://github.com/kccqzy/smartcal/blob/9cfddf7e85c2c65aa6de...

  • zokier 4 hours ago

    not completely coincidentally, March was also the first month of the year in many historical calendars. Afaik that also explains why the month names have offset to them (sept, oct, nov, dec)

    edit: I just love that there are like 5 different comments pointing out this same thing

    • Mikhail_Edoshin 4 hours ago

      I've read that not only March was the first month, but the number of months was only ten: winter months did not need to be counted because there was no agricultural work to be done (which was the primary purpose of the calendar). So after the tenth month there was a strange unmapped period.

      • _dain_ an hour ago

        >So after the tenth month there was a strange unmapped period.

        this is when time-travelling fugitives hide out

    • Izikiel43 3 hours ago

      > explains why the month names have offset to them (sept, oct, nov, dec)

      Everything now makes sense, I always wondered why September was the nine month with a 7 prefix.

  • silisili 5 hours ago

    At this risk of me feeling stupid, could you briefly explain the benefit of this?

    • kccqzy 5 hours ago

      I just added a link to the code with a brief comment. Basically, it simplifies the leap year date calculation. If February is the last month of the year, then the possibly-existing leap day is the last day of the year. If you do it the normal way your calculations for March through December need to know whether February is a leap year. Now none of that is needed. You don’t even need explicit code to calculate whether a given year is a leap year: it’s implicit in the constants 146097, 36524, and 1461.

      • zamadatix 4 hours ago

        The magic numbers at the end of this explanation are the number of days of each part of the leap year cycle:

        146097 days = 400 year portion of the leap year cycles (including leap years during that)

        36524 days = same for the 100 year portion of the leap year cycles

        1461 days = 4 year cycle + 1 leap day

      • d--b 4 hours ago

        IIRC, it's also why the leap day was set to Feb 29th in the first place. At the time (romans?) the year started March 1st.

        In case someone was wondering why in the world someone said we should add a day to the second month of the year...

        • jcranmer 31 minutes ago

          The calendar was regularized to include a leap day during the reign of Julius Caesar (hence the name "Julian calendar"), which would have been 45 BC.

          The Roman calendar moved to January as the first month of the year in 153 BC, over a hundred years before the leap day was added. The 10-month calendar may not have even existed--we see no contemporary evidence of its existence, only reports of its existence from centuries hence and the change there is attributed to a mythical character.

          • anyfoo 23 minutes ago

            Are you saying that while we do see evidence that September, October, November, December were once the 7th, 8th, 9th, and 10th month, we don't see any evidence that the calendar was ever "10 months long"? (How would that have worked anyway, did they have more days per month?)

        • wizzwizz4 12 minutes ago

          Technically, the leap day (bissextus) was the 24th. (Wikipedia tells me this is because that's when Mercedonius used to be, before the Julian reforms.)

        • variaga 4 hours ago

          That's correct, the Romans had March as the first month of the year, so leap day was the last day of the year and September, October, November and December were the 7th (sept), 8th (oct), ninth (nov) and 10th (dec) months.

          • ljsprague 2 hours ago

            June and July used to be Quintilis and Sextilis.

            • quesera a minute ago

              I think Quintilis and Sextilis were renamed to July and August, in honor of Julius and Augustus, respectively.

        • amenghra 4 hours ago

          And (oct)ober was the 8th month of the year, (nov)ember the ninth, (dec)ember the tenth!

          • sltkr 5 minutes ago

            Weird parenthesization. The latin numbers are septem, octo, novem, decem for 7, 8, 9, 10. And then they all have a -ber suffix.

          • Izikiel43 3 hours ago

            Don't forget (sep)tember being the 7th month

    • zimpenfish 3 hours ago

      As well as the leap year stuff people have mentioned, there was something else that I've got a vague memory of (from an old SciAm article, IIRC, which was about using March as the first month for calculations) which pointed out that if you use March as 0, you can multiple the month number by (I forget exactly what but it was around 30.4ish?) and, if you round the fraction up, you get the day number of the start of that month and it all works out correctly for the right 31-30-31 etc sequence.

    • da_chicken 5 hours ago

      It's easy to know what day of the year it is because leap days are at the end.

    • 3eb7988a1663 4 hours ago

      Not so relevant, but some fun history, the Roman calendar did start in March, so tacking on the leap years was done at the finale. This also meant that the root of the words - the "oct" in october means 8 was also the eighth month of the year.

benjoffe 4 days ago

A write-up of a new Gregorian date conversion algorithm.

It achieves a 30–40% speed improvement on x86-64 and ARM64 (Apple M4 Pro) by reversing the direction of the year count and reducing the operation count (4 multiplications instead of the usual 7+).

Paper-style explanation, benchmarks on multiple architectures, and full open-source C++ implementation.

  • zozbot234 13 minutes ago

    How would this algorithm change on 16-bit or 8-bit devices? Or does some variety of the traditional naïve algorithm turn out to be optimal in that case? There's quite a bit of microcontroller software that might have to do date conversions, where performance might also matter. It's also worth exploring alternative epochs and how they would affect the calculation.

  • sltkr 5 hours ago

    Very cool algorithm and great write-up!

    I was a bit confused initially about what your algorithm actually did, until I got to the pseudo-code. Ideally there would be a high level description of what the algorithm is supposed to do before that.

    Something as simple as: “a date algorithm converts a number of days elapsed since the UNIX epoch (1970-01-01) to a Gregorian calendar date consisting of day, month, and year” would help readers understand what they're about to read.

  • digitalPhonix 5 hours ago

    Very nice writeup!

    > Years are calculated backwards

    How did that insight come about?

swiftcoder 5 hours ago

Nice to see the micro-optimising folks are still making progress on really foundational pieces of the programming stack

juancn 5 hours ago

It took me a while to understand that internally it uses 128bit numbers, that `>> 64` in the pseudocode was super confusing until I saw the C++ code.

Neat code though!

zkmon 5 hours ago

Nice to see that there are still some jewels left to be dug out from the algorithm land.

pyrolistical 2 hours ago

For something this short that is pure math, why not just hand write asm for the most popular platforms? Prevents compiler from deoptimizing in the future.

Have a fallback with this algorithm for all other platforms.

  • flumpcakes 4 minutes ago

    This pretty much is assembly written as C++... there's not much the compiler can ruin.

Findecanor an hour ago

TIL that Unix Time does not count leap seconds. If it did, it wouldn't have been possible to write routines that are this fast.

kittikitti 5 hours ago

Thank you for sharing. This is a great achievement not only in the ability to invent a novel algorithm with significant performance gains but also the presentation of the work. It's very thorough and detailed, and I appreciated reading it.

vladde 5 hours ago

> The algorithm provides accurate results over a period of ±1.89 Trillion years

i'm placing my bets that in a few thousand years we'll have changed calendar system entirely haha

but, really interesting to see the insane methods used to achieve this

  • layer8 4 hours ago

    Maybe not in a few thousand years, but given the deceleration of the Earth’s rotation around its axis, mostly due to tidal friction with the moon, in a couple hundred thousand years our leap-day count will stop making sense. In roughly a million years, day length will have increased such that the year length will be close to 365.0 days.

    I therefore agree that a trillion years of accuracy for broken-down date calculation has little practical relevance. The question is if the calculation could be made even more efficient by reducing to 32 bits, or maybe even just 16 bits.

  • hugmynutus 3 hours ago

    > i'm placing my bets that in a few thousand years we'll have changed calendar system entirely haha

    Given the chronostrife will occur in around 40_000 years (give or take 2_000) I somewhat doubt that </humor>

  • ____tom____ 4 hours ago

    The calendar system already changed. So this won't get correct dates, meaning the dates actually used, past that date. Well, those dates, as different countries changed at different times.

  • fnordsensei 5 hours ago

    Wouldn’t it be accurate for that as well? Unless we change to base 10 time units or something. Then we all have a lot of work to do.

    But if it’s just about starting over from 0 being the AI apocalypse or something, I’m sure it’ll be more manageable, and the fix could hopefully be done on a cave wall using a flint spear tip.

    • jandrese 5 hours ago

      Or set 0 to be the Big Bang and make the type unsigned. Do it the same time we convert all temperature readings to Kelvin.

wood_spirit 5 hours ago

Admittedly in a different league speed wise but also scope wise is my very fast timestamp library for Java https://github.com/williame/TimeMillis

This focuses on string <-> timestamp and a few other utilities that are super common in data processing and where the native Java date functions are infamously slow.

I wrote it for some hot paths in some pipelines but was super pleased my employer let me share it. Hope it helps others.