File size: 11,224 Bytes
e11016d
 
 
 
 
 
 
 
 
22be156
e11016d
 
 
 
 
 
 
 
22be156
e11016d
 
 
 
 
22be156
e11016d
 
 
 
 
 
 
 
ffa1076
c46051b
20c927b
 
a740100
20c927b
 
 
d998e3e
f265be4
 
 
a740100
 
 
 
 
f265be4
c46051b
 
 
 
22be156
1c86b91
 
c19b6b0
22be156
 
 
 
d835f0d
22be156
 
 
 
c19b6b0
22be156
1c86b91
4f45292
22be156
 
1d9d88b
22be156
8b369c9
22be156
8b369c9
f9c3afa
1d9d88b
22be156
1c86b91
e11016d
 
 
 
 
 
 
 
 
22be156
c46051b
 
 
bfadbcf
c46051b
82d8a33
 
c46051b
 
 
82d8a33
 
 
fa686c6
82d8a33
 
 
fa686c6
c46051b
82d8a33
c46051b
 
409a3e7
ad84ac1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
409a3e7
5ae492e
22be156
 
e11016d
 
22be156
e11016d
 
c46051b
20c927b
c46051b
 
 
 
 
 
 
409a3e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5ae492e
409a3e7
 
 
 
 
 
 
 
 
ad84ac1
 
 
 
409a3e7
 
 
 
 
 
 
 
 
 
 
 
5ae492e
409a3e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c46051b
 
409a3e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ad84ac1
409a3e7
 
 
 
 
 
 
 
 
 
 
 
 
e11016d
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
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.")