Python Forum
Recommended data structure for this?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Recommended data structure for this?
#1
Question 
Hello,

I need to sort items from an .ICS file by their CREATED field in descending order.

What data structure would you suggest for that purpose? Should I use JSON, with the CREATED field as key?

Thank you.

BEGIN:VEVENT
CREATED:20251127T145325Z
DTSTART;TZID=Europe/Paris:20251209T000000
DTEND;TZID=Europe/Paris:20260331T235959
DTSTAMP:20260205T164010
LAST-MODIFIED:20260114T180026Z
UID:[email protected]
SUMMARY:Blah
DESCRIPTION:Blah
URL:https://www.acme.com/blah/
END:VEVENT
Reply
#2
JSON is a file format, not a data structure. You read a JSON formatted file and get back an object constructed of lists, dictionaries, strings, floats, ints and booleans.

There are multiple packages in PyPI that will read ICS files. Have you looked at any of those? icspy looks good.

https://icspy.readthedocs.io/en/latest/

Looks like it has tools for reading the ICS file format, creating a calendar object with a list of events. Each event has a created attribute.
Reply
#3
Probably best to convert to csv, then use pandas to sort by created. To try that you would need to supply more data.

Get the datetimes and compare them like this:

import re
from datetime import datetime

ics_file = '/home/peterr/temp/ics_stuff/calendar.ics'
with open(ics_file) as infile:
    data = infile.readlines()

date1 = data[1] # looks like 'CREATED:20251127T145325Z\n'
date2 = 'CREATED:20251128T145325Z\n'
e = re.compile(r'\d+')

time1 = e.findall(date1)
string1 = ''.join(time1)
dt1 = datetime.strptime(string1, "%Y%m%d%H%M%S")
time2 = e.findall(date2)
string2 =  ''.join(time2)
dt2 = datetime.strptime(string2, "%Y%m%d%H%M%S")
dt2 > dt1 # returns True
Reply
#4
Look at the results in Pypi. There are several modules related to ics. You could look into the modules to see which data structure they implement, or perhaps use directly one of these modules, such as ics.py.
« We can solve any problem by introducing an extra level of indirection »
Reply
#5
Thanks for the help.

It looks like a list of lists is good enough for my need (which is to turn an ICS into an HTML page):
#pip install icalendar
from icalendar import Calendar, Event
from datetime import datetime
import operator

ics_data = '''BEGIN:VCALENDAR
BEGIN:VEVENT
CREATED:20151219T021727Z
DTEND;TZID=America/Toronto:20170515T110000
DTSTAMP:20151219T022011Z
DTSTART;TZID=America/Toronto:20170515T100000
LAST-MODIFIED:20151219T021727Z
RRULE:FREQ=DAILY;UNTIL=20170519T035959Z
SEQUENCE:0
SUMMARY:Meeting
TRANSP:OPAQUE
UID:21B97459-D97B-4B23-AF2A-E2759745C299
END:VEVENT
BEGIN:VEVENT
CREATED:20201219T022011Z
DTEND;TZID=America/Toronto:20170518T120000
DTSTAMP:20151219T022011Z
DTSTART;TZID=America/Toronto:20170518T110000
LAST-MODIFIED:20151219T022011Z
RECURRENCE-ID;TZID=America/Toronto:20170518T100000
SEQUENCE:0
SUMMARY:Final Meeting
TRANSP:OPAQUE
UID:21B97459-D97B-4B23-AF2A-E2759745C299
END:VEVENT
END:VCALENDAR'''

stuff = []
gcal = Calendar.from_ical(ics_data)
for component in gcal.walk():
	if component.name == "VEVENT":
		created = component.decoded('created').date().strftime('%Y-%m-%d')
		dtstart = component.decoded('dtstart').date().strftime('%Y-%m-%d')
		summary = str(component.decoded('summary'), 'utf-8')
		stuff.append([created,dtstart,summary])
print(stuff)
sorted_list = sorted(stuff, key=operator.itemgetter(0), reverse=True)
print(sorted_list)
Reply
#6
Alternatively, using SQLite to create a temporary DB in RAM:

import sqlite3

conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute("CREATE TABLE events (created TEXT, dtstart TEXT, summary TEXT, age INTEGER)")

response = requests.get(URL, headers=HEADERS)
gcal = Calendar.from_ical(response.text)
for component in gcal.walk():
	if component.name == "VEVENT":
		created = component.decoded('created').date().strftime('%Y-%m-%d')
		dtstart = component.decoded('dtstart').date().strftime('%Y-%m-%d')
		summary = str(component.decoded('summary'), 'utf-8').replace("'", "`")
		cmd = f"INSERT INTO events (created,dtstart, summary) VALUES ('{created}','{dtstart}','{summary}')"
		cur.execute(cmd)
cur.execute("SELECT created,dtstart,summary FROM events ORDER by created DESC")
for row in cur.fetchall():
	print(row)

conn.close()
Reply
#7
The problem, as I see it, with this ics data is: How many columns do you have? I think each data set may have different lengths and categories. Maybe there is a definite set of column names, but that does not mean all datasets will have the same column names.

Also, you have info like this, which really should be 2 columns.

Quote:DTEND;TZID=America/Toronto:20170518T120000

Doesn't really matter, turns out you can sort by CREATED just using the whole string, without recourse to datetime:

Quote:CREATED:20101219T022011Z
CREATED:20101219T022012Z
CREATED:20111219T021727Z
CREATED:20111219T021728Z
CREATED:20151219T021727Z
CREATED:20201219T022011Z
CREATED:20251219T021727Z
CREATED:20251219T021729Z

And pandas is always handy. First sort by datasets, give each dataset a name, like set_1, set_2, etc.

import csv
import pandas as pd

ics_data_file = '/home/peterr/temp/ics_stuff/ics_data.ics'
savepath = '/home/peterr/temp/ics_stuff/ics_data_sorted.csv'

with open(ics_data_file) as infile:
        ics_data = infile.read()

temp = ics_data.rstrip() # get rid of newline at the end
data = temp.split('\n')
#len(data) # 62 is correct here
wanted = data[1:-1] # don't want "BEGIN:VCALENDAR\n" or "END:VCALENDAR\n" here
#len(wanted) # 60 is correct here
data_sets = []
satz = []
# get each data set
for w in wanted:
    if not w == 'END:VEVENT':
        satz.append(w)
    else:
        satz.append(w)
        data_sets.append(satz)
        satz = []
Now make a datasets dictionary, which can easily be imported into pandas:

# key is like set_1
data_dict = {}
for i in range(len(data_sets)):
    #print(data_sets[i])
    key = 'set_' + str(i)
    data_dict[key] = data_sets[i]

# orient='index' sets the keys as index
dict_df = pd.DataFrame.from_dict(data_dict, orient='index')
#print(dict_df.to_string())
#cols = [str(num) for num in range(12)]
sorted_df = dict_df.sort_values(by=1)
#print(sorted_df.to_string())
sorted_df.to_csv(savepath, index=True)
Once you have your data in pandas, you can do alll kinds of things!

Happy New Year of The Horse! (I'm a horse!)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Question [SOLVED] Recommended way to upgrade module? Winfried 3 67 Apr-19-2026, 11:57 AM
Last Post: noisefloor
Question [SOLVED] Recommended way to declare global variable? Winfried 1 90 Mar-19-2026, 09:30 PM
Last Post: deanhystad
  Recommended way to read/create PDF file? Winfried 3 18,942 Nov-26-2023, 07:51 AM
Last Post: Pedroski55
  How can I add certain elements in this 2d data structure and calculate a mean TheOddCircle 3 3,059 May-27-2022, 09:09 AM
Last Post: paul18fr
  Appropriate data-structure / design for business-day relations (week/month-wise) sx999 2 4,397 Apr-23-2021, 08:09 AM
Last Post: sx999
  what data structure to use? Winfried 4 4,652 Mar-16-2021, 12:11 PM
Last Post: buran
  Yahoo_fin, Pandas: how to convert data table structure in csv file detlefschmitt 14 13,125 Feb-15-2021, 12:58 PM
Last Post: detlefschmitt
  How to use Bunch data structure moish 2 4,922 Dec-24-2020, 06:25 PM
Last Post: deanhystad
  Correct data structure for this problem Wigi 13 8,578 Oct-09-2020, 11:09 AM
Last Post: buran
  difficulties to chage json data structure using json module in python Sibdar 1 3,179 Apr-03-2020, 06:47 PM
Last Post: micseydel

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020