←back to thread

420 points gnabgib | 3 comments | | HN request time: 1.197s | source
Show context
divbzero ◴[] No.44001929[source]
> Note that modern compilers like gcc or clang will produce something like is_leap_year2 from is_leap_year1, so there is not much point in doing this in C source, but it might be useful in other programming languages.

The optimizations that compilers can achieve kind of amaze me.

Indeed, the latest version of cal from util-linux keeps it simple in the C source:

  return ( !(year % 4) && (year % 100) ) || !(year % 400);
https://github.com/util-linux/util-linux/blob/v2.41/misc-uti...
replies(2): >>44002936 #>>44003470 #
cookiengineer ◴[] No.44003470[source]
But this is wrong and can only represent dates after the specific year when they switched from the Julian to Gregorian calendar!

For more on this, I recommend reading and implementing a function that calculates the day of the week [1]. Then you can join me in the special insanity hell of people that were trying to deal with human calendars.

And then you should implement a test case for the dates between Thursday 4 October 1582 and Friday 15 October 1582 :)

[1] https://en.m.wikipedia.org/wiki/Determination_of_the_day_of_...

replies(4): >>44007037 #>>44007095 #>>44007164 #>>44007379 #
1. voxic11 ◴[] No.44007164[source]
The full code is

   static int leap_year(const struct cal_control *ctl, int32_t year)
   {
    if (year <= ctl->reform_year)
     return !(year % 4);

    return ( !(year % 4) && (year % 100) ) || !(year % 400);
   }
Where reform_year is the year the Gregorian calendar was adopted in the specific context specified (defaults to 1752 which is the year it was adopted by GB and therefore also the US).

So it does account for Julian dates.

replies(1): >>44007508 #
2. divbzero ◴[] No.44007508[source]
cal doesn’t offer an option to use the 1582 reform date, but looks like it does handle the 1752 adoption in Great Britain correctly:

  $ cal 9 1752
     September 1752
  Su Mo Tu We Th Fr Sa
         1  2 14 15 16
  17 18 19 20 21 22 23
  24 25 26 27 28 29 30
replies(1): >>44008369 #
3. madcaptenor ◴[] No.44008369[source]
But `ncal` does offer that option. Here's October 1582 in "Italy", which didn't exist back then:

  $ ncal -sIT 10 1582
      October 1582      
  Mo  1 18 25         
  Tu  2 19 26         
  We  3 20 27         
  Th  4 21 28         
  Fr 15 22 29         
  Sa 16 23 30         
  Su 17 24 31
France apparently took a couple months to get on board (or maybe just to find out):

  $ncal -sFR 12 1582
      December 1582     
  Mo     3 20 27      
  Tu     4 21 28      
  We     5 22 29      
  Th     6 23 30      
  Fr     7 24 31      
  Sa  1  8 25         
  Su  2  9 26         
 
`ncal -p` gives a list of the country codes it accepts. (These are current countries so it's a bit ahistorical for, say, Germany.)

Sadly they don't implement the weird thing Sweden did in the early 18th century: https://en.wikipedia.org/wiki/Swedish_calendar