yack spillsaps
yack spillsaps

Reputation: 59

parse dates with icalendar and compare to python datetime

I have an .ics file from which I would like to extract all of the events that occur on today's day. I think I'm having trouble converting the icalendar DTSTART and DTEND to python datetimes. I've tried to follow the documentation at icalendar.readthedocs.org. The list I'm getting is empty, which should not be the case.

This is my code:

import urllib2
import json
from datetime import datetime
from icalendar import Calendar, Event, vDatetime


def getTodayEvents(icsFile):
    cal = Calendar.from_ical(icsFile)
    today = datetime.now().date()
    entries = []
    for event in cal.walk('VEVENT'):
        dtstart = event['DTSTART']
        dtend = event['DTEND']
        start = vDatetime.from_ical(dtstart)      //Trouble here?
        end = vDatetime.from_ical(dtend)
        if start <= today <= end:
            entry = {'summary' : event['SUMMARY'] }
            entries.append(entry)
   output = json.dumps(entries)
   return output                                  //This list is empty

And this is what the and ics entry looks like:

BEGIN:VEVENT
SUMMARY:Jonny Smith
DTSTART;VALUE=DATE:20140731
DTEND;VALUE=DATE:20150802
UID: 12345
CLASS:PUBLIC
PRIORITY:5
DTSTAMP:20141006T160145Z
TRANSP:OPAQUE
STATUS:CONFIRMED
SEQUENCE:0
LOCATION:Mansfield\, GA
X-MICROSOFT-CDO-APPT-SEQUENCE:0
X-MICROSOFT-CDO-BUSYSTATUS:FREE
X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
X-MICROSOFT-CDO-ALLDAYEVENT:TRUE
X-MICROSOFT-CDO-IMPORTANCE:1
X-MICROSOFT-CDO-INSTTYPE:0
X-MICROSOFT-DISALLOW-COUNTER:FALSE
END:VEVENT

Upvotes: 2

Views: 7918

Answers (3)

ToBe_HH
ToBe_HH

Reputation: 716

The event object has a method .decoded(), which gives you either a datetime.date object (as in your case, the .ics only has a date) or a datetime.datetime object. For the datetime.datetime object, you additionally need to convert the correct timezone.

In order to make a unified comparison, I convert everything to a string and then compare the string. This ended up, that I wrote an isEventToday method:


from datetime import datetime, timezone, timedelta

def isEventToday(event):
    if event.get('dtstart') == None:
        dtstart = ""
    else:
        temp = event.decoded('dtstart')
        if isinstance(temp, datetime):
            dtstart = temp.astimezone().strftime("%Y-%m-%d")
        else:
            dtstart = temp.strftime("%Y-%m-%d")
    if event.get('dtend') == None:
        dtend = ""
    else:
        temp = event.decoded('dtend')
        if isinstance(temp, datetime):
            dtend = temp.astimezone().strftime("%Y-%m-%d")
        else:
            # dtend for day events is the day AFTER the event, so we
            # need to substract one!
            dtend = (temp - timedelta(days=1)).strftime("%Y-%m-%d")

    today = datetime.today().date().strftime("%Y-%m-%d")

    if dtstart != "" and dtstart == today:
        return True
    if dtend != "" and dtend == today:
        return True
    if dtstart != "" and dtend != "" and dtstart <= today and today <= dtend:
        return True
    return False

The code does not look nice to me, but it is working.

Upvotes: 2

jfs
jfs

Reputation: 414079

DTSTART, DTEND properties have .dt attribute:

#!/usr/bin/env python
import json
from datetime import date
import icalendar # $ pip install icalendar

today = date.today()
calendar = icalendar.Calendar.from_ical(ics_file)
entries = [dict(summary=event['SUMMARY'])
           for event in calendar.walk('VEVENT')
           if event['DTSTART'].dt <= today <= event['DTEND'].dt]
print(json.dumps(entries, indent=2, sort_keys=True))

Output

[
  {
    "summary": "Jonny Smith"
  }
]

Upvotes: 4

hoc_age
hoc_age

Reputation: 1995

Check to see if you've got a discrepancy between data types or content in your if start <= today <= end: comparison. Take a look (in debugger or so) at what are the types and content of those three variables. I think you'll find that the comparison is comparing things that are legal to compare, but not compatible enough to give you the answer you expect (i.e., do the start and end times of this event overlap todays date?)

Your today is a datetime structure, which can be compared to other datetimes as you intend. Perhaps your vDatetime.from_ical(dtstart) is returning something other than a datetime. A quick glance at the source looks like it should be returning a datetime though. Maybe you've got a time zone issue? Look at the content of all three and check which is < or == or > others.

If that's the case, add a time zone to your calls to vDatetime.from_ical() calls;

start = vDatetime.from_ical(dtstart,'Europe/Amsterdam') #or wherever you are

Your time in the .ics indicates Z -- i.e., GMT.

If you need to do more with dates, see working with time.

Upvotes: 1

Related Questions