TurkuPythonAssignment / calendar_app.py
KaiquanMah's picture
Update calendar_app.py
ad84ac1 verified
raw
history blame
11.2 kB
import json
import datetime
class Calendar:
def __init__(self, filename="calendar_data.json"):
self.filename = filename
self.reminders = self.load_calendar()
self.current_date = datetime.date.today()
def load_calendar(self):
"""Load reminders from a file."""
try:
with open(self.filename, "r") as file:
return json.load(file)
except (FileNotFoundError, json.JSONDecodeError):
return {}
def save_calendar(self):
"""Save reminders to a file."""
with open(self.filename, "w") as file:
json.dump(self.reminders, file, indent=4)
def add_reminder(self, date, reminder):
"""Add a reminder for a specific date."""
if date not in self.reminders:
self.reminders[date] = []
self.reminders[date].append(reminder)
self.save_calendar()
print(f"Reminder added for {date}: {reminder}")
def add_daterange(self, date_start, date_end, reminder):
"""Add a reminder for a date range."""
date_yyyymm = date_start[:-2]
date_start_day = int(date_start[-2:])
date_end_day = int(date_end[-2:])
for day_int in range(date_start_day, date_end_day+1):
day_str = f"{day_int:02d}"
date = str(date_yyyymm)+day_str
if str(date) not in self.reminders:
self.reminders[date] = []
self.reminders[date].append(reminder)
# debug
# print(f"day_int: {day_int}")
# print(f"day_str: {day_str}")
# print(f"date: {date}")
# print(f"reminder: {reminder}")
self.save_calendar()
print(f"Reminder added from {date_start} to {date_end} (inclusive of start and end dates): {reminder}")
def show_all_reminders(self):
"""Show all past and future reminders in our calendar app"""
if (self.reminders is None) or len(self.reminders)<1:
print("No reminders in calendar app. Please create an event reminder to start using the app.")
else:
print("# Date Event Description")
for i,(dt,event_description) in enumerate(self.reminders.items()):
print(f"{i+1}. {dt} {event_description}")
def show_future_reminders(self):
"""Show all future reminders in our calendar app"""
if (self.reminders is None) or len(self.reminders)<1:
print("No future reminders in calendar app. Please create a future event reminder.")
else:
current_datetime = datetime.datetime.now()
print("# Date Event Description")
print_counter=1
for i,(dt,event_description) in enumerate(self.reminders.items()):
dt = datetime.datetime.strptime(dt, '%Y-%m-%d')
if current_datetime.date() <= dt.date():
print(f"{print_counter}. {dt.date()} {event_description}")
print_counter+=1
def show_reminders(self, date):
"""Show reminders for a specific date."""
if date in self.reminders:
print(f"Reminders for {date}:")
for i, reminder in enumerate(self.reminders[date], 1):
print(f"{i}. {reminder}")
else:
print(f"No reminders for {date}.")
def show_month(self, user_mth):
"""Show reminders for a specific month."""
if (self.reminders is None) or len(self.reminders)<1:
print(f"No reminders for month: {user_mth}.")
else:
# user_mth = int(user_mth)
print(f"Event reminders for month: {user_mth}")
print("# Date Event Description")
print_counter=1
for i,(dt,event_description) in enumerate(self.reminders.items()):
# dt = datetime.datetime.strptime(dt, '%Y-%m-%d')
# dt_month = dt.month
dt_month = dt.split("-")[1]
# print(f"user_mth: {user_mth}")
# print(f"dt: {dt}")
# print(f"dt_month: {dt_month}")
if user_mth == dt_month:
print(f"{print_counter}. {dt} {event_description}")
print_counter+=1
#############################
# Input validation functions
def check_valid_menu_choice(choice):
"""Input sanitation for valid menu choice from 1 and 7."""
if not choice.isdigit() or int(choice) < 1 or int(choice) > 7:
print(f"Invalid choice: {choice}. Please choose an option number from 1 to 7.")
return "invalid_choice"
else:
return "valid_choice"
def check_valid_date(date):
"""Input sanitation for valid date format"""
date_parts = date.split("-")
count_date_parts = len(date_parts)
# check 3 date parts are found: YYYY, MM, DD
if count_date_parts<3:
print(f"You entered {date} containing only {count_date_parts} date parts. Please enter date in YYYY-MM-DD format")
return "invalid_date"
# check separator of date parts
elif "." in date:
print(f"You entered {date} split on '.'. Please enter date in YYYY-MM-DD format split by '-'")
return "invalid_date"
elif "/" in date:
print(f"You entered {date} split on '/'. Please enter date in YYYY-MM-DD format split by '-'")
return "invalid_date"
# check length of date parts
elif len(date_parts[0])!=4:
print(f"You entered {date} with year value {date_parts[0]}. Please enter date in YYYY-MM-DD format, starting with a 4-digit year")
return "invalid_date"
elif len(date_parts[1])!=2:
print(f"You entered {date} with month value {date_parts[1]}. Please enter date in YYYY-MM-DD format, with a 2-digit month in the middle")
return "invalid_date"
elif len(date_parts[2])!=2:
print(f"You entered {date} with day value {date_parts[2]}. Please enter date in YYYY-MM-DD format, with a 2-digit day at the end")
return "invalid_date"
# in this last scenario, we have a valid date
else:
return "valid_date"
def check_valid_date_range(date_start, date_end):
"""Input sanitation for start date before OR equal to the end date."""
if datetime.datetime.strptime(date_start, '%Y-%m-%d') > datetime.datetime.strptime(date_end, '%Y-%m-%d'):
print(f"Error: Start date {date_start} is after end date {date_end}.\nPlease enter end date after the start date {date_start}.")
return "invalid_range"
else:
return "valid_range"
def check_valid_month(month):
"""Input sanitation for month string between 1 and 12."""
if not month.isdigit() or int(month) < 1 or int(month) > 12:
print(f"Invalid month: {month}. Please enter a month from 01 to 12.")
return "invalid_month"
else:
return "valid_month"
def check_valid_reminder(reminder):
"""Input sanitation for reminder description."""
if len(reminder.strip())<1 or reminder is None:
print("Error: Reminder description cannot be empty.")
return "invalid_reminder"
else:
return "valid_reminder"
#############################
if __name__ == "__main__":
calendar = Calendar()
while True:
print("\nCalendar Menu:")
print("1. Add Reminder for 1 day")
print("2. Add Reminder for date range (in the same month, including weekends)")
print("3. Show All Past and Future Reminders")
print("4. Show All Future Reminders")
print("5. Show Reminders for Specific Day")
print("6. Show Reminders for Specific Month")
print("7. Exit")
choice = input("Choose an option number: ")
if check_valid_menu_choice(choice) == "valid_choice":
########################################
# user create event reminder
if choice == "1":
while True:
date = input("Enter date (YYYY-MM-DD): ")
if check_valid_date(date) == "invalid_date":
continue
else:
break
while True:
reminder = input("Enter description for event reminder: ")
if check_valid_reminder(reminder) == "invalid_reminder":
continue
else:
break
calendar.add_reminder(date, reminder)
elif choice == "2":
while True:
date_start = input("Enter start date (YYYY-MM-DD): ")
if check_valid_date(date_start) == "invalid_date":
continue
else:
break
while True:
date_end = input("Enter end date (YYYY-MM-DD): ")
if check_valid_date(date_end) == "invalid_date":
continue
else:
if check_valid_date_range(date_start, date_end) == "invalid_range":
continue
else:
break
while True:
reminder = input("Enter description for event reminder: ")
if check_valid_reminder(reminder) == "invalid_reminder":
continue
else:
break
calendar.add_daterange(date_start, date_end, reminder)
########################################
########################################
# list ALL or future reminders
elif choice == "3":
calendar.show_all_reminders()
elif choice == "4":
calendar.show_future_reminders()
########################################
########################################
# list reminders for specific date or month
elif choice == "5":
while True:
date = input("Enter date (YYYY-MM-DD): ")
if check_valid_date(date) == "invalid_date":
continue
else:
break
calendar.show_reminders(date)
elif choice == "6":
while True:
user_mth = input("Enter month number (MM): ")
if check_valid_month(user_mth) == "invalid_month":
continue
else:
break
calendar.show_month(user_mth)
########################################
elif choice == "7":
calendar.save_calendar()
break
else:
print("Invalid option. Please try again.")