In today’s Programming Praxis exercise, our goal is to implement a function created by Christian Zeller to determine the day of the week for a given date. Let’s get started.

First, we need to import an existing date library to test Zeller’s algorithm against.

import Data.Time.Calendar
import Data.Time.Calendar.WeekDate

Next, a quick data type for the days of week.

data Weekday = Su | Mo | Tu | We | Th | Fr | Sa deriving (Enum, Eq, Show)

The algorithm itself is virtually identical to the Scheme implementation.

zeller :: Int -> Int -> Int -> Weekday
zeller year month day = toEnum $ mod (day + div (13 * m - 1) 5 +
d + div d 4 + div c 4 - 2 * c) 7 where
y = if month < 3 then year - 1 else year
m = if month < 3 then month + 10 else month - 2
(c, d) = divMod y 100

To test if the algorithm works correctly, we write a convenience function to test if a given date is correct.

test :: Day -> Bool
test date = zeller (fromEnum y) m d == toEnum (mod w 7) where
(y, m, d) = toGregorian date
(_, _, w) = toWeekDate date

Like the given solution, we test whether today is indeed Friday and whether it produces the correct results for a thousand years starting from January 1st, 1753.

main :: IO ()
main = do print $ zeller 2010 10 8 == Fr
print $ all test [fromGregorian 1753 1 1..fromGregorian 2753 1 1]

Indeed it does. Looks like Zeller’s algorithm works correctly.

### Like this:

Like Loading...

*Related*

Tags: algorithm, bonsai, code, congruence, date, Haskell, kata, praxis, programming, zeller

This entry was posted on October 8, 2010 at 2:10 pm and is filed under Programming Praxis. You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.

## Leave a Reply