How to Create a Birthday Reminder System with Python

How to Create a Birthday Reminder System with Python

A birthday reminder system is a program that stores and manages birthday information, notifying users of upcoming birthdays. In this tutorial, we’ll build a simple yet effective birthday reminder system using Python, leveraging its powerful date-handling capabilities and built-in libraries.

Let’s break down the process into manageable steps, each accompanied by Python code examples and explanations.

1. Setting Up the Environment

First, we’ll import the necessary modules for our birthday reminder system:

import datetime
import json
from collections import defaultdict
  • The datetime module helps us work with dates.
  • json allows us to store and retrieve birthday data.
  • defaultdict from the collections module simplifies our data structure.

2. Managing Birthday Data

Let’s create functions to add, save, and load birthday data:

def add_birthday(birthdays, name, date):
    birthdays[name] = date
    return birthdays

def save_birthdays(birthdays, filename='birthdays.json'):
    with open(filename, 'w') as f:
        json.dump(birthdays, f)

def load_birthdays(filename='birthdays.json'):
    try:
        with open(filename, 'r') as f:
            return json.load(f)
    except FileNotFoundError:
        return {}

# Example usage:
birthdays = {}
birthdays = add_birthday(birthdays, "Alice", "1990-05-15")
birthdays = add_birthday(birthdays, "Bob", "1985-12-31")
print(birthdays)
save_birthdays(birthdays)
loaded_birthdays = load_birthdays()
print(loaded_birthdays)

These functions allow us to:

  • Add new birthdays to our dictionary
  • Save the birthday dictionary to a JSON file
  • Load birthdays from a JSON file

When you run this code, you should see:

{'Alice': '1990-05-15', 'Bob': '1985-12-31'}
{'Alice': '1990-05-15', 'Bob': '1985-12-31'}

This output shows that we’ve successfully added birthdays, saved them to a file, and loaded them back into our program.

3. Implementing the Reminder System

Now, let’s create the core functionality of our reminder system:

def days_until_birthday(birthday, current_date):
    next_birthday = datetime.datetime.strptime(birthday, "%Y-%m-%d").date().replace(year=current_date.year)
    if next_birthday < current_date:
        next_birthday = next_birthday.replace(year=current_date.year + 1)
    return (next_birthday - current_date).days

def get_upcoming_birthdays(birthdays, current_date, days_ahead=7):
    upcoming = defaultdict(list)
    for name, birthday in birthdays.items():
        days_until = days_until_birthday(birthday, current_date)
        if days_until <= days_ahead:
            upcoming[days_until].append((name, birthday))
    return upcoming

def print_reminders(upcoming):
    for days, birthdays in sorted(upcoming.items()):
        if days == 0:
            print("Today's birthdays:")
        elif days == 1:
            print("Tomorrow's birthdays:")
        else:
            print(f"Birthdays in {days} days:")
        for name, date in birthdays:
            print(f"  - {name} ({date})")
        print()

# Example usage:
birthdays = {
    "Alice": "1990-05-15",
    "Bob": "1985-12-31",
    "Charlie": "1995-09-20"
}

# Let's pretend today is September 18, 2023
current_date = datetime.date(2023, 9, 18)

upcoming = get_upcoming_birthdays(birthdays, current_date)
print_reminders(upcoming)

Here’s what each function does:

  • days_until_birthday: Calculates the number of days until the next birthday.
  • get_upcoming_birthdays: Finds birthdays within a specified number of days.
  • print_reminders: Formats and displays the reminders.

In the get_upcoming_birthdays function, we use defaultdict(list). This allows us to append birthdays to each day’s list without explicitly initializing empty lists, simplifying our code. It automatically creates a new empty list when we access a new key, saving us from having to check if a key exists and create a new list manually each time we want to add a birthday to a particular day.

When you run this code with the example date (September 18, 2023), you should see:

Birthdays in 2 days:
  - Charlie (1995-09-20)

This output shows that Charlie’s birthday is coming up in 2 days from our example current date.

4. Putting It All Together

Finally, let’s create a main function that ties everything together and includes a feature to view all birthdays:

def print_all_birthdays(birthdays):
    if not birthdays:
        print("No birthdays stored.")
    else:
        print("All stored birthdays:")
        for name, date in sorted(birthdays.items()):
            print(f"  - {name}: {date}")

def main():
    birthdays = load_birthdays()
    
    while True:
        print("\nBirthday Reminder System")
        print("1. Add a birthday")
        print("2. View upcoming birthdays")
        print("3. View all birthdays")
        print("4. Exit")
        
        choice = input("Enter your choice (1-4): ")
        
        if choice == '1':
            name = input("Enter name: ")
            date = input("Enter birthday (YYYY-MM-DD): ")
            birthdays = add_birthday(birthdays, name, date)
            save_birthdays(birthdays)
            print(f"Birthday added for {name}")
        elif choice == '2':
            current_date = datetime.date.today()  # Use today's date
            upcoming = get_upcoming_birthdays(birthdays, current_date)
            if upcoming:
                print_reminders(upcoming)
            else:
                print("No upcoming birthdays in the next 7 days.")
        elif choice == '3':
            print_all_birthdays(birthdays)
        elif choice == '4':
            print("Goodbye!")
            break
        else:
            print("Invalid choice. Please try again.")

if __name__ == "__main__":
    main()

This main function provides a simple command-line interface for our birthday reminder system, allowing users to:

  1. Add new birthdays
  2. View upcoming birthdays
  3. View all stored birthdays
  4. Exit the program

The print_all_birthdays function displays all stored birthdays in alphabetical order by name, providing users with a complete overview of the data in the system.

Here’s an example of how interacting with the program might look:

Birthday Reminder System
1. Add a birthday
2. View upcoming birthdays
3. View all birthdays
4. Exit
Enter your choice (1-4): 1
Enter name: David
Enter birthday (YYYY-MM-DD): 1992-09-25
Birthday added for David

Birthday Reminder System
1. Add a birthday
2. View upcoming birthdays
3. View all birthdays
4. Exit
Enter your choice (1-4): 2
Birthdays in 3 days:
  - David (1992-09-25)

Birthday Reminder System
1. Add a birthday
2. View upcoming birthdays
3. View all birthdays
4. Exit
Enter your choice (1-4): 3
All stored birthdays:
  - Alice: 1990-05-15
  - Bob: 1985-12-31
  - Charlie: 1995-09-20
  - David: 1992-09-25

Birthday Reminder System
1. Add a birthday
2. View upcoming birthdays
3. View all birthdays
4. Exit
Enter your choice (1-4): 4
Goodbye!

This interface allows users to easily manage their birthday reminders, view upcoming celebrations, and get an overview of all stored birthdays.

Conclusion

We’ve created a functional birthday reminder system using Python’s datetime module for date manipulation, json for data persistence, and collections.defaultdict for organizing upcoming birthdays. This system demonstrates key concepts in working with dates in Python, including date arithmetic, formatting, and storage.

Key takeaways from this tutorial:

  1. Using datetime for date calculations and manipulations.
  2. Storing data persistently with JSON.
  3. Organizing data efficiently with defaultdict.
  4. Creating a simple command-line interface for user interaction.
  5. Implementing features to add, view upcoming, and list all birthdays.

To further enhance this system, you could consider adding features like:

  • Email notifications for upcoming birthdays
  • A graphical user interface for easier interaction
  • Integration with calendar applications
  • The ability to edit or delete existing birthday entries
  • Sorting birthdays by month or zodiac sign

Remember, working with dates in Python can be tricky due to leap years, different date formats, and time zones. Always test your date-related code thoroughly, especially around edge cases like year transitions.

Happy coding, and never miss a birthday again with your new Python birthday reminder system!

Leave a Reply

Your email address will not be published. Required fields are marked *