Last Sunday
Level: Beginner 15–30 minConcepts: Algorithms
Solutions: C# | TypeScript | Python
Write a method that returns the last Sunday of each month for a given year.
Example
last_sunday(2013)
| Result |
|---|
| 2013-01-27 |
| 2013-02-24 |
| 2013-03-31 |
| 2013-04-28 |
| 2013-05-26 |
| 2013-06-30 |
| 2013-07-28 |
| 2013-08-25 |
| 2013-09-29 |
| 2013-10-27 |
| 2013-11-24 |
| 2013-12-29 |
Hint
If you input the year 2020, a leap year, is the last Sunday of February 2020-02-23? If you input the year 2032, also a leap year, is the last Sunday February 2032-02-29?
Reference Walkthrough
Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/last-sunday. The reference exposes the per-month primitive — find(year, month) with month 1-indexed per human convention — because the per-year list from the TDD Buddy prompt is a trivial map over 1..12 once the month-level math is solved. Ten scenarios cover January through December of 2013, leap-year February edges (2020-02-23, 2032-02-29 where the leap day is Sunday), a century non-leap (2100-02-28), and a four-hundred-divisible leap (2000-12-31 where the last day of the year is Sunday). Each implementation constructs the last day of the month from the standard library and walks back zero-to-six days to Sunday using (weekday_delta + 7) % 7, so the zero-step case falls out of the same arithmetic.
- C# (.NET 8, xUnit, FluentAssertions 6.12.0) — walkthrough —
public static DateOnly Find(int year, int month) - TypeScript (Node 20, Vitest 1.6, TS 5 strict) — walkthrough — UTC-disciplined
Date: constructed viaDate.UTC(...), read viagetUTCDay()/getUTCDate()so calendar components stay stable across host time zones - Python (3.11, pytest) — walkthrough —
datetime.date; note Python’sweekday()has Sunday=6 where C# / JavaScript have Sunday=0, so the walk-back arithmetic changes its target integer but keeps the same shape
This kata ships in Agent Full-Bake mode at high gear (F1 tier): the algorithm is small enough to land as one commit per language, with a brief walkthrough noting there are no builders because the date type comes from the standard library and the inputs/outputs are the domain. See the repo’s Gears section for when high gear is the right call.
Solutions
You can find all language solutions here Last Sunday Solutions
Or you can select a specific language below.
Related reading
- Katas Are Rehearsal, Not Performance
You don't practice TDD on production code. You practice on katas and bring the muscle memory to production. The gap between knowing TDD and doing TDD is reps. - The Contract Test Is the Only Witness the Agent Cannot Author
A test the agent wrote against code the same agent wrote shares the agent's blind spot: a misunderstanding in the implementation becomes a matching misunderstanding in the test, the bar goes green, and the bug ships certified. Consumer-driven contract tests are the only category where a second team publishes the assertion the first team has to satisfy. That separation of authorship is exactly what tamper-resistant test design demanded, applied at the integration seam. - Cohesion Is the Coverage of the Agent Era
Agent-generated codebases pass every structural-modularity metric while fragmenting the domain concept the team was trying to encode. Coverage measured whether a line ran. Mutation score measured whether an assertion pinned behavior. Cohesion is the next axis, and it measures whether the codebase's concepts are traversable end-to-end.