analizar fechas con icalendar y compararlas con python datetime

Tengo un archivo .ics del que me gustaría extraer todos los eventos que ocurren en el día de hoy. Creo que estoy teniendo problemas para convertir los icsendar DTSTART y DTEND a fechas de tiempo de python. He intentado seguir la documentación en icalendar.readthedocs.org . La lista que estoy recibiendo está vacía, lo que no debería ser el caso.

Este es mi código:

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 

Y así es como se ve la entrada de ics:

 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 

Las propiedades DTSTART, DTEND tienen el atributo .dt :

 #!/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)) 

Salida

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

Verifique si tiene una discrepancia entre los tipos de datos o el contenido en su if start <= today <= end: comparación. Eche un vistazo (en el depurador o menos) a cuáles son los tipos y el contenido de esas tres variables. Creo que encontrará que la comparación es comparar cosas que son legales para comparar, pero no lo suficientemente compatibles para darle la respuesta que espera (es decir, ¿las horas de inicio y finalización de este evento se superponen en la fecha de hoy?)

Tu today es una estructura de datetime y datetime , que puede compararse con otras datetime tal como lo desees. Tal vez su vDatetime.from_ical(dtstart) esté devolviendo algo distinto a datetime . Sin embargo, un vistazo rápido a la fuente parece que debería devolver una datetime y datetime . Tal vez usted tiene un problema de zona horaria? Mire el contenido de los tres y verifique cuál es < o == o > otros.

Si ese es el caso, agregue una zona horaria a sus llamadas a vDatetime.from_ical() calls;

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

Su tiempo en el .ics indica Z , es decir, GMT.

Si necesita hacer más con las fechas, vea trabajar con tiempo .

El objeto de event tiene un método .decoded() , que le proporciona un objeto datetime.date (como en su caso, el .ics solo tiene una fecha) o un objeto datetime.datetime . Para el objeto datetime.datetime , adicionalmente necesita convertir la zona horaria correcta.

Para hacer una comparación unificada, convierto todo en una cadena y luego comparo la cadena. Esto terminó, que escribí un método isEventToday:

 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 

El código no me parece bien, pero está funcionando.