From a46661c1b37f2160e1b589abf8aac58470827907 Mon Sep 17 00:00:00 2001
From: Edward Betts <edward@4angle.com>
Date: Sun, 5 Nov 2023 12:55:14 +0000
Subject: [PATCH] Add missing code

---
 agenda/birthday.py | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 agenda/birthday.py

diff --git a/agenda/birthday.py b/agenda/birthday.py
new file mode 100644
index 0000000..80a401d
--- /dev/null
+++ b/agenda/birthday.py
@@ -0,0 +1,39 @@
+"""Birthdays."""
+
+from datetime import date
+
+import yaml
+
+from .types import Event
+
+
+def next_birthday(from_date: date, birth_date: date) -> tuple[date, int]:
+    """Calculate the date of the next birthday based on a given birth date."""
+    next_birthday_date = birth_date.replace(year=from_date.year)
+
+    if from_date > next_birthday_date:
+        next_birthday_date = birth_date.replace(year=from_date.year + 1)
+
+    age_at_next_birthday = next_birthday_date.year - birth_date.year
+
+    return next_birthday_date, age_at_next_birthday
+
+
+def get_birthdays(from_date: date, filepath: str) -> list[Event]:
+    """Get birthdays from config."""
+    events = []
+    with open(filepath) as f:
+        entities = yaml.safe_load(f)
+
+    for entity in entities:
+        birthday = date(**entity["birthday"])
+        bday, age = next_birthday(from_date, birthday)
+        events.append(
+            Event(
+                date=bday,
+                name="birthday",
+                title=f'{entity["label"]} (aged {age})',
+            )
+        )
+
+    return events