I’m doing a project using a Parallax Propeller microcontroller at the moment. It’s like a normal microcontroller, but psychedelic. Eight cores, peripherals defined almost entirely in software, and primarily programmed in a cunning language called Spin. Spin is a very efficient interpreted language and makes it possible to squeeze a lot into the Propeller’s meagre 32K of RAM.
The project has a real-time clock maintained by an off-the-shelf clock chip, but this application needs to know the day of the week as well. Of course, I can get the user to set the day of the week when they set the clock, but it’s unintuitive to have to set it manually, and this thing is supposed to be easy to use.
I looked in to algorithms for calculating the day of the week given a year, month and date. There are loads of them. The Wikipedia page has lots, and this Stackoverflow page has a load of useful suggestions. There was one particularly simple one which appeared in both places, credited to Tomohiko Sakamoto on the comp.lang.c Usenet newsgroup in 1993. I don’t care about the theory behind the algorithm, I just want it to work and to be simple to program in Spin. The original is in C and looks like this:
dayofweek(y, m, d) /* 1 <= m <= 12, y > 1752 (in the U.K.) */ { static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; y -= m < 3; return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7; }
My Spin version looks like this:
DAT dayTable BYTE 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 PRI decFromBCD(n) return (n&$f)+10*((n&$f0)>>4) PRI calcDayFromDate | y y := decFromBCD(year) + 2000 if month < 3 y-- day := (y + (y/4) - (y/100) + (y/400) + dayTable[decFromBCD(month)-1] + decFromBCD(date)) // 7
Mine looks more complex, and the one reason for that is that the clock chip maintains its counts in BCD (binary-coded decimal) rather than straight decimal. There might be a cunning way to modify the algorithm to take BCD values directly, but I took the easy route of implementing a function which converts an 8-bit BCD value into decimal.
The code assumes the presence of three variables: year (0 to 99, starting at the year 2000), month (1 to 12) and date (1 to 31) and sets a variable day in the range 0 to 6, where 0 is Sunday.
When implementing the clock in your project, don’t forget to compensate for the leap second tonight.
Yay!