/// <summary> /// Apply the time-filter to the VFREEBUSY components. /// A VFREEBUSY component overlaps a given time range if the condition for the /// corresponding component state specified in the table (pg66 RFC 4791) is satisfied. /// </summary> /// <param name="component">THe VTODO</param> /// <param name="start">The start time of the filter</param> /// <param name="end">The end datetime of the filter</param> /// <returns>True if pass the filter, false otherwise.</returns> private static bool ApplyTimeFilterToVFREEBUSY(this ICalendarComponent component, DateTime start, DateTime end) { var DTSTART = component.GetComponentProperty("DTSTART") == null ? DateTime.MinValue : ((IValue <DateTime>)component.GetComponentProperty("DTSTART")).Value; var DTEND = component.GetComponentProperty("DTEND") == null ? DateTime.MaxValue : ((IValue <DateTime>)component.GetComponentProperty("DTEND")).Value; //VFREEBUSY has both the DTSTART and DTEND properties? Y // VFREEBUSY has the FREEBUSY property? * if (DTSTART != DateTime.MinValue && DTEND != DateTime.MaxValue) { return(start <= DTEND && end > DTSTART); } //VFREEBUSY has both the DTSTART and DTEND properties? N // VFREEBUSY has the FREEBUSY property? Y if (component.MultipleValuesProperties.ContainsKey("FREEBUSY")) { //take the freebusy properties var freeBProp = component.MultipleValuesProperties["FREEBUSY"] .Select(x => ((IValue <Period>)x).Value); if (freeBProp.Any(period => start < period.End.Value && end > period.Start.Value)) { return(true); } } //VFREEBUSY has both the DTSTART and DTEND properties? N // VFREEBUSY has the FREEBUSY property? N return(false); }
/// <summary> /// Apply the time-filter to the VTODOs components. /// A VTODO component overlaps a given time range if the condition for the /// corresponding component state specified in the table (pg64 RFC 4791) is satisfied. /// </summary> /// <param name="component">The VTODO</param> /// <param name="start">The start time of the filter</param> /// <param name="end">The end datetime of the filter</param> /// <param name="expandedDates">The expaned dts by the RRULEs if any.</param> /// <returns>True if pass the filter, false otherwise.</returns> private static bool ApplyTimeFilterToVTODO(this ICalendarComponent component, DateTime start, DateTime end, IEnumerable <DateTime> expandedDates) { var DURATION = component.GetComponentProperty("DURATION") == null ? null : ((IValue <DurationType>)component.GetComponentProperty("DURATION")).Value; var DUE = component.GetComponentProperty("DUE") == null ? null : ((IValue <Due>)component.GetComponentProperty("DUE")).Value; var COMPLETED = component.GetComponentProperty("COMPLETED") == null ? null : ((IValue <Completed>)component.GetComponentProperty("COMPLETED")).Value; var CREATED = component.GetComponentProperty("CREATED") == null ? null : ((IValue <Created>)component.GetComponentProperty("Created")).Value; //VTODO has the DTSTART property? Y if (expandedDates.Any()) { foreach (var DTSTART in expandedDates) { // VTODO has the DURATION property? Y // VTODO has the DUE property? N // VTODO has the COMPLETED property? * // VTODO has the CREATED property? * if (DURATION != null && DUE == null) { var DTSTARTplusDURATION = DTSTART.AddDuration(DURATION); if (start <= DTSTARTplusDURATION && (end > DTSTART || end > DTSTARTplusDURATION)) { return(true); } } // VTODO has the DURATION property? N // VTODO has the DUE property? Y // VTODO has the COMPLETED property? * // VTODO has the CREATED property? * else if (DUE != null) { if ((start < DUE.Value || start <= DTSTART) && (end > DTSTART) || end >= DUE.Value) { return(true); } } // VTODO has the DURATION property? N // VTODO has the DUE property? N // VTODO has the COMPLETED property? * // VTODO has the CREATED property? * if (DUE == null && DURATION == null) { if (start <= DTSTART && end > DTSTART) { return(true); } } } } //VTODO has the DTSTART property? N else { // VTODO has the DURATION property? N // VTODO has the DUE property? Y // VTODO has the COMPLETED property? * // VTODO has the CREATED property? * if (DUE != null && DURATION == null) { if (start < DUE.Value && end >= DUE.Value) { return(true); } } // VTODO has the DURATION property? N // VTODO has the DUE property? N // VTODO has the COMPLETED property? Y // VTODO has the CREATED property? Y if (COMPLETED != null && CREATED != null) { if ((start <= CREATED.Value || start <= COMPLETED.Value) && end >= CREATED.Value || end >= COMPLETED.Value) { return(true); } } // VTODO has the DURATION property? N // VTODO has the DUE property? N // VTODO has the COMPLETED property? Y // VTODO has the CREATED property? N else if (COMPLETED != null && CREATED == null) { if (start <= COMPLETED.Value && end >= COMPLETED.Value) { return(true); } } // VTODO has the DURATION property? N // VTODO has the DUE property? N // VTODO has the COMPLETED property? N // VTODO has the CREATED property? Y else if (COMPLETED == null && CREATED != null) { if (end > CREATED.Value) { return(true); } } } // VTODO has the DURATION property? N // VTODO has the DUE property? N // VTODO has the COMPLETED property? N // VTODO has the CREATED property? N return(true); }
/// <summary> /// Apply the time-filter to the VEVENT components. /// A VEVENT component overlaps a given time range if the condition for the /// corresponding component state specified in the table (pg64 RFC 4791) is satisfied. /// </summary> /// <param name="component">THe VTODO</param> /// <param name="start">The start time of the filter</param> /// <param name="end">The end datetime of the filter</param> /// <param name="expandedDates">The expaned dts by the RRULEs if any.</param> /// <returns>True if pass the filter, false otherwise.</returns> private static bool ApplyTimeFilterToVEVENT(this ICalendarComponent component, DateTime start, DateTime end, IEnumerable <DateTime> expandedDates) { var compEndTimeProp = component.GetComponentProperty("DTEND"); foreach (var DTSTART in expandedDates) { //VEVENT has the DTEND property? Y // VEVENT has the DURATION property? N // DURATION property value is greater than 0 seconds? N // DTSTART property is a DATE-TIME value? * if (compEndTimeProp != null) { var DTEND = ((IValue <DateTime>)compEndTimeProp).Value; if (start < DTEND && end > DTSTART) { return(true); } } var durationProp = component.GetComponentProperty("DURATION"); //VEVENT has the DTEND property? N // VEVENT has the DURATION property? Y if (durationProp != null) { var DURATION = ((IValue <DurationType>)durationProp).Value; var DTSTARTplusDURATION = DTSTART.AddDuration(DURATION); // DURATION property value is greater than 0 seconds? Y // DTSTART property is a DATE-TIME value? * if (DURATION.IsPositive) { if (start < DTSTARTplusDURATION && end > DTSTART) { return(true); } } // DURATION property value is greater than 0 seconds? N // DTSTART property is a DATE-TIME value? * else { if (start <= DTSTART && end > DTSTART) { return(true); } } } //VEVENT has the DTEND property? N // VEVENT has the DURATION property? N // DURATION property value is greater than 0 seconds? N // DTSTART property is a DATE-TIME value? Y if (start <= DTSTART && end > DTSTART) { return(true); } //VEVENT has the DTEND property? N // VEVENT has the DURATION property? N // DURATION property value is greater than 0 seconds? N // DTSTART property is a DATE-TIME value? N if (start < DTSTART.AddDays(1) && end > DTSTART) { return(true); } } return(false); }
/// <summary> /// Apply the time filter to the given component as /// defined in 9.9 CALDAV:time-range XML Element. /// </summary> /// <param name="component">The component where to apply the filter.</param> /// <param name="filter">The filter to apply.</param> /// <returns>True if the component pass the filter, false otherwise.</returns> private static bool ApplyTimeFilter(this ICalendarComponent component, IXMLTreeStructure filter) { DateTime?start; DateTime?end; //get the start and time attributes of the filter. if (filter.Attributes.ContainsKey("start")) { filter.Attributes["start"].ToDateTime(out start); } else //if not then assign infinite { start = DateTime.MinValue; } if (filter.Attributes.ContainsKey("end")) { filter.Attributes["end"].ToDateTime(out end); } else //if not then assign -infinite { end = DateTime.MaxValue; } //Get the DTSTART of the component. var compDTSTART = component.GetComponentProperty("DTSTART") == null ? DateTime.MaxValue : ((IValue <DateTime>)component.GetComponentProperty("DTSTART")).Value; //if the component contains RRULES then expand the dts IEnumerable <DateTime> expandedDates = null; if (component.MultipleValuesProperties.ContainsKey("RRULE")) { expandedDates = compDTSTART.ExpandTime(component.GetMultipleCompProperties("RRULE").Select( x => ((IValue <Recur>)x).Value).ToList()); } if (expandedDates == null) { expandedDates = new List <DateTime> { compDTSTART } } ; if (component is VEvent) { return(component.ApplyTimeFilterToVEVENT(start.Value, end.Value, expandedDates)); } if (component is VTodo) { return(component.ApplyTimeFilterToVTODO(start.Value, end.Value, expandedDates)); } if (component is VJournal) { throw new NotImplementedException("The doesn't support the VJOURNALs yet."); } if (component is VFreebusy) { return(component.ApplyTimeFilterToVFREEBUSY(start.Value, end.Value)); } if (component is VAlarm) { return(component.ApplyTimeFilterToVALARM(start.Value, end.Value)); } return(false); }