Zeller’s Congruence

Do not miss this exclusive book on Binary Tree Problems. Get it now for free.

Introduction:

Zeller's Congruence is a mathematical algorithm devised by Christian Zeller to calculate the day of the week for any date in both the Julian and Gregorian calendars. It provides a systematic approach for finding the day of the week, offering a valuable tool for programmers, historians, and anyone interested in calendar systems. In this blog post, we'll explore the intricacies of Zeller's Congruence, dissect its formulae, and provide insights into its implementation.

The Algorithm:

Zeller's Congruence involves two variations, one for the Gregorian calendar and another for the Julian calendar.

Let's start with the formula for the Gregorian calendar:

Here,

  • h represents the day of the week (0 = Saturday, 1 = Sunday, ..., 6 = Friday).
  • q is the day of the month.
  • m is the month, with January and February counted as months 13 and 14 of the previous year.
  • K is the year of the century (year % 100).
  • J is the zero-based century (year / 100).

For the Julian calendar, the formula is slightly modified:

ISO Week Date Adjustment:

To convert the obtained h to ISO week date Day-of-Week (d), where Monday is considered the first day (1 = Monday, ..., 7 = Sunday), the following formula is applied:

d=((h+5)mod7)+1

Now, let's dive into a practical implementation of the algorithm in C++.

Break Down of the Formula:

Adjust the month and year:

If the month is January or February, increase the month by 12 and decrease the year by 1. This step is done to treat January and February as months 13 and 14 of the previous year.

Calculate K and J:

  • K is the year of the century (Year mod 100).
  • J is the zero-based century (Year/100)

Calculate the expression:

13(m+1)/5:
This term represents the contribution of the month to the day of the week. It is essentially an adjustment for the month, and the floor function ensures that we consider only the whole number part.

K/4:
This term accounts for the contribution of the year to the day of the week. It considers the leap years and adds an extra day for each leap year.

J/4:
Similar to the previous term, this adjusts for the century. It adds an extra day for each leap century.

−2J:
This term is a correction factor for the century. Subtracting 2J is done to account for a centennial drift. It prevents the calendar from drifting too far ahead over the centuries.

Sum up the components:

Add up all the terms:

q + [13(m+1)/5] + K + [K/4] + [J/4] - 2J

Take the modulus 7:

The entire sum is then taken modulo 7 (mod 7). This step is crucial because it brings the result back into the range of days of the week (0 to 6).

Adjust the result:

If the result is negative, add 7 to it to bring it into the range [0, 6].

Map to the day of the week:

The final result h corresponds to the day of the week, where 0 might represent Saturday, 1 for Sunday, and so on.

C++ Implementation:

The C++ code provided illustrates a simple implementation of Zeller's Congruence for the Gregorian calendar. It takes a date (day, month, and year) as input and outputs the corresponding day of the week.

// C++ program to Find the Day for a Date
#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;

int Zellercongruence(int day, int month, int year) {
    if (month == 1) {
        month = 13;
        year--;
    }
    if (month == 2) {
        month = 14;
        year--;
    }
    int q = day;
    int m = month;
    int k = year % 100;
    int j = year / 100;
    int h = q + 13 * (m + 1) / 5 + k + k / 4 + j / 4 + 5 * j;
    h = h % 7;
    switch (h) {
    case 0:
        cout << "Saturday \n";
        break;
    case 1:
        cout << "Sunday \n";
        break;
    case 2:
        cout << "Monday \n";
        break;
    case 3:
        cout << "Tuesday \n";
        break;
    case 4:
        cout << "Wednesday \n";
        break;
    case 5:
        cout << "Thursday \n";
        break;
    case 6:
        cout << "Friday \n";
        break;
    }
    return 0;
}

// Driver code
int main() {
    Zellercongruence(22, 10, 2017); // date (dd/mm/yyyy)
    return 0;
}

Output

Sunday 

Variation of Zeller's Congruence:

Here,

  • c represents the century
  • y is the year within the century
  • d is the day of the month.

This variation offers an alternative approach to finding the day of the week.

#include <bits/stdc++.h>
using namespace std;
string Zellercongruence(int day, int month, int year)
{
    vector<string> days = { "Sunday",   "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
    if (month < 3) {
        month += 12;
        year -= 1;
    }
    int c = year / 100;
    year = year % 100;
    int h = (c / 4 - 2 * c + year + year / 4 + 13 * (month + 1) / 5 + day - 1) % 7;
    return days[(h + 7) % 7];
}

int main()
{
    cout << Zellercongruence(7, 3, 2003); // date (dd/mm/yyyy)
    return 0;
}

Conclusion:

In this comprehensive exploration of Zeller's Congruence, we've delved into the algorithm's formulae, its application for both the Julian and Gregorian calendars, and provided practical C++ implementations. Understanding Zeller's Congruence not only unveils the mechanics of calculating the day of the week but also offers insights into the intricacies of calendar systems. This algorithm, with its historical significance and practical utility, remains a valuable tool for various applications. Whether you're a programmer seeking an efficient way to determine weekdays or a history enthusiast curious about calendar calculations, Zeller's Congruence provides a fascinating journey into the world of date algorithms.

Sign up for FREE 3 months of Amazon Music. YOU MUST NOT MISS.