Python programming Ideas and Comments
Diary Recurring entries
I've been wanting to implement 'Recurring/Repeating' Events in the Diary for sometime.
A recent incident spurred me to start - I had forgotten to book an important annual test and when the usual reminder came two weeks late, I realise I had to get started.
I searched the Internet for some ideas, and quickly found that there are two main schools of thought:
- the iCalendar approach
- store every entry in the database
The iCalendar approach is well described here.
I have some issues with the article as it tries to dictate one approach, and fails with some of the arguments - especially about rendering 50 unique events. If you aren't going to display recurring events in your Diary, what's the point? Or is their database so slow they can't get 50 or more events out quickly?
One other argument is that of no 'end_date' for your event series, ie 'Create an event every Monday at 09:00 forever'
Well, there will be an 'end_date' - that imposed by the OS or Progamming language. Python on Linux will handle dates up to 9999-12-31! Somehow I think an end-date well before then will not 'cripple' the application.
Is this application still going to be the same in 20 years time, and with the same users? I some how doubt it!
Nevertheless, I decided to try the iCalendar approach having found the Python 'dateutil' module that can create a list of dates from an iCalendar RRule. iCalendar is designed for interoperability with other Calendar systems, and I wanted the ability to exchange calendar data with other systems.
I created a separate 'recurring_events' table, and added an 'is_recurring' flag to the existing diary table.
The RRule is stored as a text string in the 'recurring_events' table, along with an 'end_date'. 'end_date' crops up a lot! You have to have an 'end_date' to create a database query.
InfoCDB can display a single day, week or month's data at a time, so you query the database for any event that occurs within one day, or a date range. With recurring events, you need to include 'any event with an 'end_date' after the first date of the date range'.
I got something working, and then hit the first snag. Unlike some social media sites like Google and Facebook, the InfoCDB diary entries are private unless otherwise defined. There is a 'share with' option. I had to modify the 'share_with' option to work with recurring events.
Recurring events don't actually exist - they have to be generated every time you want to deal with them. And they all point to the original entry. So if you 'share_with' one event, you have shared them all.
You can handle date and time exceptions and deletions by storing those specific instances, and checking for them during the creation of the recurring events.
So far I had it working. But then I hit my breaking point. It is far too easy to alter history!
If I delete the recurrence rule, I lose all the entries, past and future. I could add more complexity to attempt to prevent this, but in my opinion that's just trying to fix something that is fundamentally not right for this use, especially when the next point is included for consideration.
I like to look back at my diary entries for past years, and as I have added comments to some entries, I have a simple journal. As the recurring events don't exist, I have nowhere to add a comment.
So that's it - ephemeral recurring entries are DEAD.
I will keep the RRule so that I can exchange calendar data with other systems, which is the reason for iCalendar, but the implementation will now be based on actual entries in the database!
There will be an 'end_date', probably 20 years from the creation date. You will always be able to extend the 'end_date', if you are still with us.
Deleting future events will not effect events that have already happened.
Access to the database is fast, as the Python app has permanent connections to the database. If we need to add some more storage space we will. We are using dedicated hardware - it isn't a cloud instance, so it hardly alters the economics.