The One Man MMO Project
The story of a lone developer's quest to build an online world :: MMO programming, design, and industry commentary
Calculating the Day of the Week
By Robert Basler on 2018-01-27 13:17:57
Homepage: onemanmmo.com email:one at onemanmmo dot com

Figuring out the day of the week from a date is a frickin' nightmare. Back in 2009 I got an algorithm from Wikipedia, and apparently that algorithm was wrong because they've removed it. Since then, the editors for that page have evidently gone insane, because their new page is a mess of incomprehensible tables, messy algorithm descriptions and magic numbers.

Giving up on Wikipedia, I tried code from the first three google results I got - all of them had various problems. I compared a few known dates on a few different "date calculator" websites - they sometimes didn't agree. That all took three hours, so yeah, super frustrating.

Finally I found a clue on StackOverflow. To help anyone else in this situation, here's some code to figure out the day of the week that is readable and relatively fast and seems to be correct. There are more compact algorithms, but after last night's experience, I'm going with this.

`    enum DayOfWeek    {        SUNDAY = 0,        MONDAY,        TUESDAY,        WEDNESDAY,        THURSDAY,        FRIDAY,        SATURDAY    };    bool IsLeapYear( unsigned int year)    {        if ( ( ( year % 4 == 0 ) && ( year % 100 != 0 ) ) || ( year % 400 == 0) )        {            return true;        }        return false;    }    // Returns day of the week for a given date.  Days of the week start with Sunday = 0.  Year is 1-N, month is 1-12, day is 1-M    DayOfWeek CalculateDayOfWeek( unsigned int year, unsigned int month, unsigned int day )    {        // Table of how many days there are in the months prior to current month.        static const unsigned int months[ 12 ] =        {            0,            31,            31 + 28,            31 + 28 + 31,            31 + 28 + 31 + 30,            31 + 28 + 31 + 30 + 31,            31 + 28 + 31 + 30 + 31 + 30,            31 + 28 + 31 + 30 + 31 + 30 + 31,            31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,            31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,            31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,            31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30        };        // Algorithm works for the Gregorian calendar which was first adopted in 1582, although the calendar was adopted in different        // countries in different years. For the UK it was 1752.  Turkey did not adopt this calendar until 1927. Year calculation originally        // from https://stackoverflow.com/questions/478694/what-is-the-easiest-algorithm-to-find-the-day-of-week-of-day-zero-of-a-given-yea        return static_cast< DayOfWeek >( (            year * 365                                         // Days since the first day of year 0 which was a Sunday.            + ( ( year - 1 ) / 4 )                             // Add 1 day for every previous leap year            - ( ( year - 1 ) / 100 )                           // Years divisible by 100 are not leap years            + ( ( year - 1 ) / 400 )                           // Unless year is divisible by 400.            + months[ month - 1 ]                              // Add days from prior months of the year            + ( IsLeapYear( year ) && ( month > 2 ) ? 1 : 0 )  // Add 1 if month is after February and it is a leap year            + day                                              // Add the day            - 1 ) % 7 );                                       // And finally, subtract 1 so result is zero based, then take the remainder to get the day of the week.    }`

This all came about because a player wanted to play Miranda this weekend, but the Login server thought Saturday was Monday and wouldn't let him log in. That's fixed now.