basics · intermediate · ~20 min

Day of week via Zeller's congruence

Apply a closed-form formula with several branching cases.

Challenge

Compute the day of the week for any Gregorian date using Zeller's congruence — a closed-form formula.

Task

Implement int day_of_week(int y, int m, int d) that returns the weekday of the date (y, m, d), encoded as 0=Saturday, 1=Sunday, 2=Monday, ..., 6=Friday.

Apply Zeller's congruence (Gregorian form):

  • If m < 3, treat the month as 13 or 14 of the previous year: set m += 12 and y -= 1.
  • Let K = y % 100 and J = y / 100.
  • h = (d + 13*(m+1)/5 + K + K/4 + J/4 - 2*J) mod 7, normalised to 0..6.

Input

A Gregorian year y, month m (1..12), and day d (1..31).

Output

Returns the weekday index 0..6 (0=Saturday).

Example

day_of_week(2024, 1, 1)     ->   2   (Monday)
day_of_week(2000, 1, 1)     ->   0   (Saturday)
day_of_week(2024, 12, 25)   ->   4   (Wednesday)

Edge cases

  • January and February require the month/year shift before applying the formula.
  • C's % can yield a negative result, so normalise with ((h % 7) + 7) % 7.

Rules

  • Pure arithmetic — no system calls or date libraries.

Why this matters

Calendar arithmetic shows up in log timestamps, scheduling, and security policies. Zeller's congruence is a clean way to teach modular branching.

Input format

A Gregorian date as ints y, m (1..12), d (1..31).

Output format

The weekday index 0..6, where 0=Saturday.

Constraints

Pure arithmetic, no system calls. Apply the Jan/Feb shift and normalise negative modulo.

Starter code

int day_of_week(int y, int m, int d) { /* TODO */ return 0; }

Common mistakes

Forgetting the Jan/Feb shift. Mishandling negative modulo (C99: (-1) % 7 == -1).

Edge cases to handle

Jan/Feb (shift), year 2000 (boundary), pre-Gregorian years (formula doesn't apply).

Complexity

O(1).

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.