parse dates with icalendar and compare to python datetime

空扰寡人 提交于 2019-12-08 04:34:32

问题


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

回答1:


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"
  }
]



回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/26238835/parse-dates-with-icalendar-and-compare-to-python-datetime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!