Most recent posts


Calculating the date of Easter for a particular year

A long time ago, in a galaxy far, far away – OK, it was in London in 1993 – I added a DateEaster function to my personal Dates unit, written in Borland Pascal 7. So: 16-bit DOS for all you oldies. For a bit of fun, I shall present it here with some commentary.

At the time I was really proud of this unit: the majority of it was written in assembly for speed reasons (it was used in a swaps trading app I was writing) and it could calculate things like days between two dates (including on a 360-day basis), adding/subtracting number of days, parsing date strings (including things like t+3d for “today plus 3 days”). All routines worked with dates from 1-Jan-1980 to 31-Dec-2099 (by the way, once of the reasons for stopping there is that 2100 is not a leap year, so by not including it meant that many calculations were simpler).

I even devised a packed format for the date type I was using, a longint that stored the day, month, year, and number of days since 1-Jan-1980 such that typecasting it back to a longint would ensure that date comparisons were valid and calculating text representations of dates was instantaneous.

{=Notes===============================================================

The TDate has the internal format:
   bits  0- 4 : day in month (1..31)
   bits  5- 8 : month (1..12)
   bits  9-15 : years since 1980 (0..119)
   bits 16-31 : days since 01-Jan-1980 less 22,000

This format ensures date comparisons can be made by typecasting to
longint.
=====================================================================}

At some point, I had to maintain a list of bank holiday dates as well, since no trading would occur on those days. The usual culprits: Christmas, New Year, the May and August bank holidays? No sweat, easy peasy. Easter on the other hand? Oh wow.

So I did some research on how Easter dates were calculated. These days this would be simple: Google “calculate date of Easter” and you’ll get to a wikipedia page on Computus. To be honest though, at this remove I cannot remember which reference book I used. Anyway, Easter Sunday is defined as the first Sunday that follows the first full moon that follows the Spring Equinox. Since the Spring Equinox falls on March 21, Easter Sunday can be any date between March 22 and April 25 in the Gregorian calendar. It so happens that, since the calculation of Easter is determined by both the lunar and the solar cycles, the dates of Easter repeat every 19 years, especially given the date range I was using. The variance in this lunar/solar cycle is given by so-called Golden Numbers (see the wikipedia article for details). This resulted in this routine:

{=DateEaster==========================================================
Calculates the date for Easter Sunday for a given year.
01Mar93 JMB
======================================================================}
function DateEaster(Y : word) : TDate;
  const
    _Mar = $60; _Apr = $80; {ie 3 and 4 in the top 3 bits }
    GoldenNumberToFullMoon : array [0..18] of byte =
       (14+_Apr,  3+_Apr, 23+_Mar, 11+_Apr, 31+_Mar, 18+_Apr,  8+_Apr,
        28+_Mar, 16+_Apr,  5+_Apr, 25+_Mar, 13+_Apr,  2+_Apr, 22+_Mar,
        10+_Apr, 30+_Mar, 17+_Apr,  7+_Apr, 27+_Mar);
    DaysToSunday : array [DayOfWeek] of byte = (6, 5, 4, 3, 2, 1, 7);
  var
    FullMoon : TDate;
    FullMMDD : byte;
  begin
    if (Y > 99) and ((Y < FirstYear) or (Y > LastYear)) then
      DateEaster := BadDate
    else
      begin
        FullMMDD := GoldenNumberToFullMoon[Y mod 19];
        FullMoon := DateFromYMD(Y, ((FullMMDD and $E0) shr 5), FullMMDD and $1F);
        DateEaster := DateAddDays(FullMoon, DaysToSunday[DateDOW(FullMoon)]);
      end;
  end;

I think I was so enamored with this code that I just left it as that. This Julian from 2016, on the other hand, would have used it in a throw-away program to calculate all the dates of Easter Sunday in the date range I allowed and added them as an fixed array to the unit. There’s only 120 of them, after all, so a mere 480 bytes to store them; for even more efficiency, I could have halved that by just storing the YMD values as a word.

The other thing that reminded me of this particular set of units is someone mentioning on some thread I was reading that you should be able to read and use code that you wrote 30 years ago. Personally I disagree with this viewpoint – this particular code is 23 years old and is fairly unusable now because it uses 16-bit DOS assembly language. An example:

{=DateToday===========================================================
Interrogates DOS for the system date and returns it as a TDate.
01Mar93 JMB
======================================================================}
function DateToday : TDate;
assembler;
  asm
    mov ax, 2A00h                   { Ask DOS for date                }
    int 21h                         { dd/mm/yy = dl / dh / cx         }
    push cx                         { Push year                       }
    xor ax, ax                      { Clear ax to get month           }
    xchg al, dh                     { Put month in ax                 }
    push ax                         { Push month                      }
    push dx                         { Push day                        }
    call DateFromYMD                { Convert to TDate                }
  end;

(And that’s the easiest bit of assembly in there.) Although I was inordinately proud of this code at the time, and it’s fun to see what kind of gyrations I used to go through to try and wrest every CPU cycle from Pascal code I could, there is no way I’d ever use it again. The world has moved on from these simpler early days. DOS is dead. Borland Pascal 7, although a great compiler/IDE, is dead. There are different ways of programming now, different methodologies to tame complexity (generic collections, functional programming, lambdas, etc). This code is an exemplar of its time, but that’s about it.

Painting the bedroom

Album cover for ElectrifiedNow playing:
Boris Blank - Future Past
(from Electrified)


Using Node to run JavaScript from Sublime Text

A quick one, more for my benefit next time I have to set this up in the future. Sometimes, I’m writing some JavaScript that can be divorced from a web page. Maybe it’s a weird bit of code, maybe I’m experimenting with (say) functional programming, maybe it’s just a small self-contained function, but I’d really like to test it right there and then, rather than copy/paste it and use the developer tools in my browser. For Sublime Text, we can set up a “ build system ” to do this. First install node...

READ MORE

Professional theme? Sure, except for these bits…

Back in January , I pulled the trigger on a new theme for this blog. I recognized some time ago that I am not a very good web designer (I can do small tweaks to CSS but not comprehensive composition) and it would be far better to buy something that’s well designed and then spend the time wrapping the output from the blog engine to this new look and feel. And that, pretty much, is what happened. I bought a professionally designed theme (making sure it was responsive), and hacked away at the templates...

READ MORE

Script from my very first appearance on stage

In a week where I am about to tread the boards again for the first time in over a year, my sister was sorting out some of our parents’ documents, found this page and scanned/sent it to me this morning. It is nothing less than the “script” – if I may call it that – of what I had to learn as announcer (or perhaps, more accurately, narrator?) for a production of Snow White and the Seven Dwarves that our school was putting on. The wrinkle is, we were living in France at the time so it’s in French. Even...

READ MORE

SlySoft is dead, long live RedFox!

A week or so ago, the SlySoft website was suddenly replaced by a terse announcement that “[d]ue to recent regulatory requirements we have had to cease all activities.” I’m willing to bet that most of my readers haven’t heard of SlySoft or their main product, AnyDVD. In essence, AnyDVD is an app that circumvents the DRM present in all DVDs and Blu-ray discs, at the driver level. There are two reasons for doing this. The first is to circumvent the region encoding used by DVDs, and this was the initial...

READ MORE

Don’t configure Windows 10 with your Microsoft account unless you want a five letter name

A bit abrupt a headline, no? Well, it cost me a couple of hours by doing so. The scenario is this: you’ve just bought /acquired/factory reset a laptop with Windows 10 installed. The first thing you have to do then is configure it: you know, define the language to be used, the timezone, connect to the WiFi, set up an account on the machine, and so on. It’s this latter part that’s the problem. Windows would love you to use your Microsoft account to do so. It gives you a lot of benefits, such as sharing...

READ MORE

Goodbye Dell XPS 13, hello Dell XPS 13

Last year, having tried out a Surface Pro 3 and disliking it, I bought a Dell XPS 13 ultrabook as my “travel” computer. This year? Well, Dell refreshed the range, added more memory and and a bigger SSD and suddenly I was looking at my 5-year-old Dell XPS 15z and thinking it was time to replace that. And what better way to replace it by having a single laptop that I used all the time? The other consideration that factored into the calculation was that the new XPS 13 not only has more “space” but it...

READ MORE

Thinking functionally in JavaScript – a fun interlude

I’ve been talking about functional JavaScript for a few posts, but, to be honest, it’s nice to put the theory aside and just practice thinking and writing functionally. With that in mind, let see what we can do about fixing some “copy-n-paste” code. I bought a theme for this site a month or so back – you’re looking at it. As part of the theme, you get some HTML showing what various types of pages look like, the CSS to render it all, and some JavaScript. Usually the HTML/CSS is fine, but then I take...

READ MORE

Thinking functionally in JavaScript (part three)

In continuing this series of posts about functional JavaScript ( one , two ), I whimsically wondered if we could apply the SOLID principles of object-oriented programming . We took a look at S last time (the Single Responsibility Principle), and were fairly successful. The principle I introduced there was not only that the functions we write should do one thing and do it well. If we can embrace global immutability, so much the better (in other words, the function should not have side effects ). Small...

READ MORE

Web development is not as much fun as it’s cracked up to be

Today so far has been a comedy of errors with some web programming I wanted to do. A confederacy of dunce issues, one after the other. URL Shortener It started with some work I’d been doing yesterday with the URL shortener code I use for my jmbk.nl links. The web hosting I have for the domain on GoDaddy is a couple of months from its renewal date, but, to be honest, what I’m paying for it (about $7 a month) is not worth it. I’ll move it to Azure, I thought to myself. Let’s see what amount of work...

READ MORE