Zeller congruence in 176 bytes
published: 12 December 2020 / updated 12 December 2020
Zeller congruence
These formulas are based on the observation that the day of the week progresses in a predictable manner based upon each subpart of that date. Each term within the formula is used to calculate the offset needed to obtain the correct day of the week.
The formula for the Julian calendar:
The formula for the Gregorian calendar. It is this formula which will be processed in FORTH language:
where:
- h is the day of the week (0 = Saturday, 1 = Sunday, 2 = Monday, ...)
- q is the day of the month
- m is the month
- J is the century (actually year / 100)
- and K the year of the century (year mod 100).
January and February are counted as month 13 and 14 of the previous year.
The formula for gForth
\ Zeller's Congruence : zeller ( m -- days since March 1 ) 9 + 12 mod 1- 26 10 */ 3 + ; : weekday ( d m y -- 0..6 ) \ Monday..Sunday over 3 < if 1- then dup 4 / over 100 / - over 400 / + + swap zeller + + 1+ 7 mod ;
With gForth, the compilation of this formula will occupy 240 bytes in the Forth dictionary.
To test the formula, all you have to do is precede the word weekday
with numbers
of the day, month and year. Example:
12 12 2020 weekday \ display 5
The order of the parameters is: day month year.
The days are numbered from 0 to 6, the week starting with Monday and ending with Sunday.
The value 5 therefore indicates Saturday.
The formula for FlashForth
It is exactly the same as for gForth, but you must first compile these definitions that will complete the FlashForth arithmetic function set:
: m* ( n1 n2 -- d ) 2dup xor >r abs swap abs um* r> ?dnegate ; : sm/rem ( d1 n1 -- n2 n3 ) 2dup xor >r over >r abs >r dabs r> um/mod swap r> ?negate swap r> ?negate ; : /mod ( n1 n2 -- n3 n4 ) >r s>d r> sm/rem ; : mod ( n1 n2 -- n3 ) /mod drop ; : */ ( n1 n2 n3 -- n4 ) >r m* r> sm/rem nip ;
On FlashForth, the formula contained in the words zeller
and weekday
occupies only 176 bytes. This difference is explained by the fact that gForth manages the data and
32-bit execution codes, compared to 16 bits for FlashForth.
Day of the week decoding
For gForth:
: str-table ( comp: n -- | exec: n -- str len) create 0 do , loop does> swap cells + @ count ; here ," Sunday" here ," Saturday" here ," Friday" here ," Thursday" here ," Wednesday" here ," Tuesday" here ," Monday" 7 str-table weekdays
Example of use:
12 12 2020 weekday weekdays type \ display Saturday
For FlashForth:
\ get real addr2 and u length form addr1 : count ( addr1 --- addr2 u) dup c@ \ push real length swap 1+ swap \ push start address of datas ; : str-table ( comp: n -- | exec: n -- str len) create for , next does> swap cells + @ count ; flash here ," Sunday" here ," Saturday" here ," Friday" here ," Thursday" here ," Wednesday" here ," Tuesday" here ," Monday" 7 str-table weekdays ram
Good programming...