Tomohiko Sakamoto’s Day-Of-Week Algorithm

June 17, 2016

Here is Sakamoto’s algorithm for calculating the day of the week, taken from the comment that introduces the code:

Jan 1st 1 AD is a Monday in Gregorian calendar.
So Jan 0th 1 AD is a Sunday [It does not exist technically].

Every 4 years we have a leap year. But xy00 cannot be a leap unless xy divides 4 with reminder 0.

y/4 – y/100 + y/400 : this gives the number of leap years from 1AD to the given year. As each year has 365 days (divdes 7 with reminder 1), unless it is a leap year or the date is in Jan or Feb, the day of a given date changes by 1 each year. In other case it increases by 2.

y -= m So y + y/4 – y/100 + y/400 gives the day of Jan 0th (Dec 31st of prev year) of the year. (This gives the reminder with 7 of the number of days passed before the given year began.)

Array t: Number of days passed before the month ‘m+1’ begins.

So t[m-1]+d is the number of days passed in year ‘y’ upto the given date.

(y + y/4 – y/100 + y/400 + t[m-1] + d) % 7 is reminder of the number of days from Jan 0 1AD to the given date which will be the day (0=Sunday,6=Saturday).

int dow(int y, int m, int d) {
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;
}

Another description is given here.

Your task is to write a program that implements the day-of-week algorithm shown above. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

One Response to “Tomohiko Sakamoto’s Day-Of-Week Algorithm”

  1. Globules said

    A Haskell version, with a variant (dow’) that provides a little more type safety.

    import Data.Vector
    
    t :: Vector Int
    t = fromList [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4];
    
    -- Given a year, month (1-12) and day of month return the day of the week (0-6).
    dow :: Int -> Int -> Int -> Int
    dow y m d =
      let y' = if m < 3 then y - 1 else y
      in (y' + y' `div` 4 - y' `div` 100 + y' `div` 400 + t ! (m-1) + d) `mod` 7
    
    
    -- A slightly more typesafe variant.
    
    data Month = Jan | Feb | Mar | Apr | May | Jun |
                 Jul | Aug | Sep | Oct | Nov | Dec
      deriving (Enum, Show)
    
    data Day = Sun | Mon | Tue | Wed | Thu | Fri | Sat
      deriving (Enum, Show)
    
    -- Given a year, month and day of month return the day of the week.
    dow' :: Int -> Month -> Int -> Day
    dow' y m d = toEnum $ dow y (fromEnum m + 1) d
    
    main :: IO ()
    main = do
      print $ dow  2016   6 18
      print $ dow' 2016 Jun 18
    
    $ ./dow 
    6
    Sat
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: