/// <summary> /// Open a vCalendar or iCalendar file /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void miOpen_Click(object sender, EventArgs e) { if (wasModified && MessageBox.Show("Do you want to discard your changes to the current calendar?", "Discard Changes", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No) { return; } using (OpenFileDialog dlg = new OpenFileDialog()) { dlg.Title = "Load Calendar File"; dlg.Filter = "ICS files (*.ics)|*.ics|VCS files (*.vcs)|*.vcs|All files (*.*)|*.*"; if (vCal.Version == SpecificationVersions.vCalendar10) { dlg.DefaultExt = "vcs"; dlg.FilterIndex = 2; } else { dlg.DefaultExt = "ics"; dlg.FilterIndex = 1; } dlg.InitialDirectory = Path.GetFullPath(Path.Combine( Environment.CurrentDirectory, @"..\..\..\..\..\PDIFiles")); if (dlg.ShowDialog() == DialogResult.OK) { try { this.Cursor = Cursors.WaitCursor; // Parse the calendar information from the file and load the data grid with some basic // information about the items in it. vCal.Dispose(); vCal = VCalendarParser.ParseFromFile(dlg.FileName); LoadComponentList(); // Find the first collection with items if (vCal.Events.Count != 0) { cboComponents.SelectedIndex = 0; } else if (vCal.ToDos.Count != 0) { cboComponents.SelectedIndex = 1; } else if (vCal.Journals.Count != 0) { cboComponents.SelectedIndex = 2; } else if (vCal.FreeBusys.Count != 0) { cboComponents.SelectedIndex = 3; } else { cboComponents.SelectedIndex = 0; } LoadGridWithItems(true); lblFilename.Text = dlg.FileName; } catch (Exception ex) { string error = String.Format("Unable to load calendar:\n{0}", ex.Message); if (ex.InnerException != null) { error += ex.InnerException.Message + "\n"; if (ex.InnerException.InnerException != null) { error += ex.InnerException.InnerException.Message; } } System.Diagnostics.Debug.Write(ex); MessageBox.Show(error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { this.Cursor = Cursors.Default; } } } }
public void ToStringTest() { var calString = @"BEGIN:VCALENDAR PRODID:-//Google Inc//Google Calendar 70.9054//EN VERSION:2.0 CALSCALE:GREGORIAN X-WR-CALNAME:[email protected] X-WR-TIMEZONE:America/Los_Angeles BEGIN:VTIMEZONE TZID:America/Los_Angeles X-LIC-LOCATION:America/Los_Angeles BEGIN:DAYLIGHT TZOFFSETFROM:-0800 TZOFFSETTO:-0700 TZNAME:PDT DTSTART:19700308T020000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:-0700 TZOFFSETTO:-0800 TZNAME:PST DTSTART:19701101T020000 RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU RDATE:19450603T010000 END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTART;TZID=America/Los_Angeles:20120629T130000 DTEND;TZID=America/Los_Angeles:20120629T140000 DTSTAMP:20120629T112428Z UID:[email protected] RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU CREATED:20120629T111935Z DESCRIPTION:foo LAST-MODIFIED:20120629T112428Z LOCATION:Barcelona SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Demo B2G Calendar TRANSP:OPAQUE BEGIN:VALARM ACTION:EMAIL DESCRIPTION:This is an event reminder SUMMARY:Alarm notification ATTENDEE:mailto:[email protected] TRIGGER:-P0DT0H30M0S END:VALARM BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:This is an event reminder TRIGGER:-P0DT0H30M0S END:VALARM END:VEVENT END:VCALENDAR "; VCalendar calendar = VCalendar.Parse(calString); var xmlDoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?> <C:calendar-query xmlns:D=""DAV:"" xmlns:C=""urn:ietf:params:xml:ns:caldav""> <D:prop> <D:getetag/> <C:calendar-data> <C:comp name=""VCALENDAR""> <C:prop name=""VERSION""/> <C:comp name=""VEVENT""> <C:prop name=""SUMMARY""/> <C:prop name=""UID""/> <C:prop name=""DTSTART""/> <C:prop name=""DTEND""/> </C:comp> <C:comp name=""VTIMEZONE""/> </C:comp> </C:calendar-data> </D:prop> <C:filter> <C:comp-filter name=""VCALENDAR""> <C:comp-filter name=""VEVENT""> <C:time-range start=""20060104T000000Z"" end=""20060105T000000Z""/> </C:comp-filter> </C:comp-filter> </C:filter> </C:calendar-query>"; var xmlTree = XmlTreeStructure.Parse(xmlDoc); var node = xmlTree.GetChildAtAnyLevel("calendar-data"); var newCalString = calendar.ToString(node); var newCal = new VCalendar(newCalString); Assert.Equal(2, newCal.CalendarComponents.Count); Assert.Contains("VEVENT", newCal.CalendarComponents.Keys); Assert.Contains("VTIMEZONE", newCal.CalendarComponents.Keys); Assert.Equal(4, newCal.CalendarComponents["VEVENT"].First().Properties.Count); }
public void BuildVCalendar() { var calString = @"BEGIN:VCALENDAR PRODID:-//Google Inc//Google Calendar 70.9054//EN VERSION:2.0 CALSCALE:GREGORIAN X-WR-CALNAME:[email protected] X-WR-TIMEZONE:America/Los_Angeles BEGIN:VTIMEZONE TZID:America/Los_Angeles X-LIC-LOCATION:America/Los_Angeles BEGIN:DAYLIGHT TZOFFSETFROM:-0800 TZOFFSETTO:-0700 TZNAME:PDT DTSTART:19700308T020000 RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3 END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:-0700 TZOFFSETTO:-0800 TZNAME:PST DTSTART:19701101T020000 RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11 END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTART;TZID=America/Los_Angeles:20120629T130000 DTEND;TZID=America/Los_Angeles:20120629T140000 DTSTAMP:20120629T112428Z UID:[email protected] RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU; BYMONTHDAY=2,3,4,5,6,7,8 RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU; BYMONTHDAY=2,3,4,5,6,7,8 CREATED:20120629T111935Z DESCRIPTION:foo LAST-MODIFIED:20120629T112428Z LOCATION:Barcelona SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Demo B2G Calendar TRANSP:OPAQUE BEGIN:VALARM ACTION:EMAIL DESCRIPTION:This is an event reminder SUMMARY:Alarm notification ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] TRIGGER:-P0DT0H30M0S END:VALARM BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:This is an event reminder TRIGGER:-P0DT0H30M0S END:VALARM END:VEVENT END:VCALENDAR "; VCalendar calendar = VCalendar.Parse(calString); var calendarString = calendar.ToString(); UnicodeEncoding uniencoding = new UnicodeEncoding(); UTF8Encoding utf8Encoding = new UTF8Encoding(); var toWrite = utf8Encoding.GetBytes(calendarString); File.Delete("output1.ics"); using (var writer = File.OpenWrite("output1.ics")) { writer.Seek(0, SeekOrigin.End); writer.Write(toWrite, 0, toWrite.Length); } using (var reader = File.OpenText("output1.ics")) { var writedCal = reader.ReadToEnd(); var writedCalLines = Parser.CalendarReader(writedCal); var expectedLines = Parser.CalendarReader(calString); Assert.Equal(expectedLines.Length, writedCalLines.Length); for (int i = 0; i < writedCalLines.Length; i++) { Assert.Contains(expectedLines[i], writedCalLines); } } Assert.NotNull(calendarString); }
/// <summary> /// The CALDAV:calendar-multiget REPORT is used to retrieve specific calendar object resources from within a /// collection, if the Request-URI is a collection, or to retrieve a specific calendar object resource, if the /// Request-URI is a calendar object resource. This report is similar to the CALDAV:calendar-query REPORT /// (see Section 7.8), except that it takes a list of DAV:href elements, instead of a CALDAV:filter element, to /// determine which calendar object resources to return /// </summary> /// <returns></returns> private async Task CalendarMultiget(IXMLTreeStructure xmlBody, HttpContext httpContext) { // take the first prop node to know the data that // should ne returned IXMLTreeStructure propNode; xmlBody.GetChildAtAnyLevel("prop", out propNode); //take the href nodes. Contain the direction of the resources files that //are requested var hrefs = xmlBody.Children.Where(node => node.NodeName == "href").Select(href => href.Value); var result = new Dictionary <string, string>(); // process the requested resources foreach (var href in hrefs) { var fs = new FileSystemManagement(); var resourceContent = await fs.GetCalendarObjectResource(href); result.Add(href, resourceContent); } await ReportResponseBuilder(result .Select( x => new KeyValuePair <string, VCalendar>(x.Key, string.IsNullOrEmpty(x.Value) ? null : VCalendar.Parse(x.Value))), propNode, httpContext); }
public void CheckProperties() { var calString = @"BEGIN:VCALENDAR PRODID:-//Google Inc//Google Calendar 70.9054//EN VERSION:2.0 CALSCALE:GREGORIAN X-WR-CALNAME:[email protected] X-WR-TIMEZONE:America/Los_Angeles BEGIN:VTIMEZONE TZID:America/Los_Angeles X-LIC-LOCATION:America/Los_Angeles BEGIN:DAYLIGHT TZOFFSETFROM:-0800 TZOFFSETTO:-0700 TZNAME:PDT DTSTART:19700308T020000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:-0700 TZOFFSETTO:-0800 TZNAME:PST DTSTART:19701101T020000 RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTART;TZID=America/Los_Angeles:20120629T130000 DTEND;TZID=America/Los_Angeles:20120629T140000 DTSTAMP:20120629T112428Z UID:[email protected] CREATED:20120629T111935Z DESCRIPTION:foo LAST-MODIFIED:20120629T112428Z LOCATION:Barcelona SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Demo B2G Calendar TRANSP:OPAQUE BEGIN:VALARM ACTION:EMAIL DESCRIPTION:This is an event reminder SUMMARY:Alarm notification ATTENDEE:mailto:[email protected] TRIGGER:-P0DT0H30M0S END:VALARM BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:This is an event reminder TRIGGER:-P0DT0H30M0S END:VALARM END:VEVENT END:VCALENDAR "; VCalendar calendar = VCalendar.Parse(calString); var calEvent = calendar.GetCalendarComponents("VEVENT").First() as VEvent; var eventAlarms = calEvent.CalendarComponents["VALARM"]; Assert.Equal((calEvent.GetComponentProperty("UID") as IValue <string>).Value, "*****@*****.**"); Assert.Equal((calEvent.GetComponentProperty("DESCRIPTION") as IValue <string>).Value, "foo"); Assert.Equal(2, eventAlarms.Count); }
public async Task <bool> PreconditionsOK(Dictionary <string, string> propertiesAndHeaders, HttpResponse response) { #region Extracting Properties var url = propertiesAndHeaders["url"]; var contentSize = propertiesAndHeaders["content-length"]; var body = propertiesAndHeaders["body"]; VCalendar iCalendar; try { iCalendar = new VCalendar(body); //lo que no estoy seguro que en el body solo haya el iCal string } catch (Exception) { response.StatusCode = (int)HttpStatusCode.BadRequest; return(false); } #endregion //check that resourceId don't exist but the collection does. if ( !StorageManagement.ExistCalendarCollection(url.Remove(url.LastIndexOf("/", StringComparison.Ordinal) + 1))) { response.StatusCode = (int)HttpStatusCode.NotFound; return(false); } //check that if the resource exist then all its components different of VTIMEZONE has to have the same UID //if the resource not exist can not be another resource with the same uid. if (!StorageManagement.ExistCalendarObjectResource(url)) { var component = iCalendar.CalendarComponents.FirstOrDefault(comp => comp.Key != "VTIMEZONE").Value; var uid = component.FirstOrDefault()?.Properties["UID"].StringValue; // var resource = db.GetCalendarResource(userEmail, collectionName, calendarResourceId); var collection = _collectionRepository.Get(url.Remove(url.LastIndexOf("/", StringComparison.Ordinal) + 1)); foreach (var calendarresource in collection.CalendarResources) { if (uid == calendarresource.Uid) { response.StatusCode = (int)HttpStatusCode.Conflict; response.Body.Write( $@"<?xml version='1.0' encoding='UTF-8'?> <error xmlns='DAV:'> <no-uid-conflict xmlns='urn:ietf:params:xml:ns:caldav'> <href xmlns='DAV:'>{ SystemProperties._baseUrl + calendarresource .Href}</href> </no-uid-conflict> </error>"); return(false); } } } else { //If the resource exist the procedure is update and for that the uid has to be the same. var components = iCalendar.CalendarComponents.FirstOrDefault(comp => comp.Key != "VTIMEZONE").Value; var calendarComponent = components.FirstOrDefault(); if (calendarComponent != null) { var uid = calendarComponent.Properties["UID"].StringValue; var resource = _resourceRespository.Get(url); if (resource.Uid != null && resource.Uid != uid) { response.StatusCode = (int)HttpStatusCode.Conflict; response.Body.Write( $@"<?xml version='1.0' encoding='UTF-8'?> <error xmlns='DAV:'> <no-uid-conflict xmlns='urn:ietf:params:xml:ns:caldav'> <href xmlns='DAV:'>{ SystemProperties._baseUrl + resource .Href}</href> </no-uid-conflict> </error>"); return(false); } } } if (propertiesAndHeaders.ContainsKey("If-Match")) { //check that the value do exist if (!StorageManagement.ExistCalendarObjectResource(url)) { response.StatusCode = (int)HttpStatusCode.PreconditionFailed; return(false); } } if (propertiesAndHeaders.ContainsKey("If-None-Match")) { //check that the value do not exist if (StorageManagement.ExistCalendarObjectResource(url)) { response.StatusCode = (int)HttpStatusCode.PreconditionFailed; return(false); } } //it does not contain more than two calendar components //and if it has 2, one must be VTIMEZONE if (iCalendar.CalendarComponents.Count > 2) { if (!iCalendar.CalendarComponents.ContainsKey("VTIMEZONE")) { response.StatusCode = (int)HttpStatusCode.Conflict; response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?> <error xmlns='DAV:'> <valid-calendar-object-resource xmlns='urn:ietf:params:xml:ns:caldav'></valid-calendar-object-resource> <error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'> VTimezone Calendar Component Must be present. </error-description> </error>"); return(false); } var calendarComponents = iCalendar.CalendarComponents.FirstOrDefault(comp => comp.Key != "VTIMEZONE").Value; //A Calendar Component can be separated in multiples calendar components but all MUST //have the same UID. var calendarComponent = calendarComponents.FirstOrDefault(); if (calendarComponent != null) { var uid = calendarComponent.Properties["UID"].StringValue; foreach (var component in calendarComponents) { var uidComp = component.Properties["UID"].StringValue; if (uid != uidComp) { response.StatusCode = (int)HttpStatusCode.Conflict; response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?> <error xmlns='DAV:'> <valid-calendar-object-resource xmlns='urn:ietf:params:xml:ns:caldav'></valid-calendar-object-resource> <error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'> If the count of calendar components execeds 2 including VTimezone the rest must have the same Uid and the same type. </error-description> </error>"); return(false); } } } // response.StatusCode = (int)HttpStatusCode.Conflict; // response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?> //<error xmlns='DAV:'> //<valid-calendar-object-resource xmlns='urn:ietf:params:xml:ns:caldav'></valid-calendar-object-resource> //<error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'> //Wrong amount of calendar components //</error-description> //</error>"); // return false; } //precondition responsible of check that an VTIMEZONE is obligatory if (iCalendar.CalendarComponents.Count == 2) { if (!iCalendar.CalendarComponents.ContainsKey("VTIMEZONE")) { response.StatusCode = (int)HttpStatusCode.Conflict; response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?> <error xmlns='DAV:'> <valid-calendar-object-resource xmlns='urn:ietf:params:xml:ns:caldav'></valid-calendar-object-resource> <error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'> VTimezone Calendar Component Must be present. </error-description> </error>"); return(false); } } //var uidCalendar = ((ComponentProperty<string>)iCalendar.Properties["UID"]).Value; ////Check that if the operation is create there is not another element in the collection with the same UID //if (!StorageManagement.ExistCalendarObjectResource(calendarResourceId)) //{ // using (db) // { // if ((from calendarResource in db.CalendarResources // where calendarResource.Uid == uidCalendar // select calendarResource).Count() > 0) // return false; // } //} ////Check if the operation is update the element to be updated must have the same UID. //else //{ // using (db) // { // if ((from calendarResource in db.CalendarResources // where calendarResource.Uid == uidCalendar // select calendarResource).Count() == 0) // return false; // } //} var methodProp = iCalendar.GetComponentProperties("METHOD"); //iCalendar object MUST NOT implement METHOD property if (!string.IsNullOrEmpty(methodProp?.StringValue)) { response.StatusCode = (int)HttpStatusCode.Conflict; response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?> <error xmlns='DAV:'> <valid-calendar-object-resource xmlns='urn:ietf:params:xml:ns:caldav'></valid-calendar-object-resource> <error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'> Method prop must not be present </error-description> </error>"); return(false); } //This precondition is the one in charge of check that the size of the body of the resource //included in the request dont exceeds the max-resource-size property of the colletion. int contentSizeInt; //for that i need that the controller has as request header content-size available if (!string.IsNullOrEmpty(contentSize) && int.TryParse(contentSize, out contentSizeInt)) { var collection = _collectionRepository.Get(url.Remove(url.LastIndexOf("/", StringComparison.Ordinal) + 1)); //here the max-resource-property of the collection is called. var maxSize = collection.Properties.FirstOrDefault( p => p.Name == "max-resource-size" && p.Namespace == "urn:ietf:params:xml:ns:caldav"); int maxSizeInt; if (int.TryParse(XmlTreeStructure.Parse(maxSize?.Value).Value, out maxSizeInt) && contentSizeInt > maxSizeInt) { response.StatusCode = (int)HttpStatusCode.Conflict; response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?> <error xmlns='DAV:'> <max-resource-size xmlns='urn:ietf:params:xml:ns:caldav'></max-resource-size> <error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'> Content size exceeds max size allowed. </error-description> </error>"); return(false); } } //TODO: Checking that all DateTime values are less-equal than //the max-date-time //TODO: Checking that all DateTime values are grater-equal than //the min-date-time //TODO: Checking that the number of recurring instances is less-equal //than the max-instances property value. return(await Task.FromResult(true)); }
public static bool CalendarWriter(TextWriter writer, VCalendar calendar) { return(false); }
/// <summary> /// This method is used to return all recurring instances between the two specified date/times based on /// the current settings. /// </summary> /// <param name="fromDate">The minimum date/time on or after which instances should occur. This will /// include an instance if it starts before the date/time but overlaps it when its duration is added to /// its start time.</param> /// <param name="toDate">The maximum date/time on or before which instances should occur. This will /// include an instance if it starts on or before the specified date/time regardless of its duration.</param> /// <param name="inLocalTime">If true, the date/time parameters are assumed to be in local time and the /// returned date/times are expressed in local time. If false, the date/time parameters are assumed to /// be in the time zone of the object and the returned date/times are expressed in the time zone of the /// object as specified by the <see cref="TimeZoneId"/> property. If no time zone ID has been specified /// or it cannot be found, local time is used.</param> /// <returns>Returns a <see cref="DateTimeInstanceCollection"/> containing <see cref="DateTimeInstance" /> /// objects that represent all instances found between the two specified date/times. Instances may have /// a different duration if created from an <c>RDATE</c> property.</returns> /// <exception cref="ArgumentException">This is thrown if a start date has not been specified (it equals /// <c>DateTime.MinValue</c>) or the duration is negative.</exception> /// <seealso cref="AllInstances"/> /// <seealso cref="OccursOn"/> public DateTimeInstanceCollection InstancesBetween(DateTime fromDate, DateTime toDate, bool inLocalTime) { DateTimeCollection recurDates; Period p; DateTime endDate, tempDate1 = DateTime.MaxValue, tempDate2; int idx, count; string timeZoneID = this.TimeZoneId; PeriodCollection periods = new PeriodCollection(); DateTime startDate = this.StartDateTime.TimeZoneDateTime; Duration dur = this.InstanceDuration; if (startDate == DateTime.MinValue) { throw new ArgumentException(LR.GetString("ExNoComponentStartDate")); } if (dur.Ticks < 0) { throw new ArgumentException(LR.GetString("ExRONegativeDuration")); } // Convert fromDate and toDate to time zone time if inLocalTime is true. Recurrences are always // resolved in the time of the object. if (inLocalTime && timeZoneID != null) { fromDate = VCalendar.LocalTimeToTimeZoneTime(fromDate, timeZoneID).StartDateTime; toDate = VCalendar.LocalTimeToTimeZoneTime(toDate, timeZoneID).StartDateTime; } // There might be instances that overlap the requested range so we'll adjust the From date/time by // the duration to catch them. if (dur.Ticks > 1) { fromDate = fromDate.Add(new TimeSpan(0 - dur.Ticks + 1)); } // As per the spec, the start date/time is always included in the set but only if it (or it's // duration) is within the requested range. However, if it is recurring and the custom Exclude Start // property is set to true, it is not added. p = new Period(startDate, dur); if (((p.StartDateTime >= fromDate && p.StartDateTime <= toDate) || (p.EndDateTime >= fromDate && p.EndDateTime <= toDate)) && (!this.IsRecurring || !this.ExcludeStartDateTime)) { periods.Add(p); } // If it isn't recurring or starts after the requested end date, just return the collection as it is if (this.IsRecurring && startDate <= toDate) { // Expand each recurrence rule foreach (RRuleProperty rr in this.RecurrenceRules) { // If used, RecurUntil is stored in Universal Time which is converted to local time. If a // time zone ID is specified, convert it to that time zone temporarily to make sure things // are calculated correctly. if (rr.Recurrence.MaximumOccurrences == 0 && timeZoneID != null) { tempDate1 = rr.Recurrence.RecurUntil; rr.Recurrence.RecurUntil = VCalendar.LocalTimeToTimeZoneTime(tempDate1, timeZoneID).StartDateTime; } rr.Recurrence.StartDateTime = startDate; recurDates = rr.Recurrence.InstancesBetween(fromDate, toDate); if (rr.Recurrence.MaximumOccurrences == 0 && timeZoneID != null) { rr.Recurrence.RecurUntil = tempDate1; } foreach (DateTime dt in recurDates) { periods.Add(new Period(dt, dur)); } } // Add on recurrence dates within the range foreach (RDateProperty rd in this.RecurDates) { if (rd.ValueLocation != ValLocValue.Period) { // If it's not a period, use the component's duration. If it's only a date, assume it's // the whole day. The spec is not clear on this so I'm making a best guess. if (rd.ValueLocation == ValLocValue.DateTime) { endDate = rd.TimeZoneDateTime.Add(dur.TimeSpan); } else { endDate = rd.TimeZoneDateTime.Add(new TimeSpan(TimeSpan.TicksPerDay)); } if ((rd.TimeZoneDateTime >= fromDate && rd.TimeZoneDateTime <= toDate) || (endDate >= fromDate && endDate <= toDate)) { periods.Add(new Period(rd.TimeZoneDateTime, endDate)); } } else { // As with Recurrence.RecurUntil, the period values are in Universal Time so convert them // to the time zone time for proper comparison. tempDate1 = rd.PeriodValue.StartDateTime; tempDate2 = rd.PeriodValue.EndDateTime; if (timeZoneID != null) { tempDate1 = VCalendar.LocalTimeToTimeZoneTime(tempDate1, timeZoneID).StartDateTime; } if (timeZoneID != null) { tempDate2 = VCalendar.LocalTimeToTimeZoneTime(tempDate2, timeZoneID).StartDateTime; } if ((tempDate1 >= fromDate && tempDate1 <= toDate) || (tempDate2 >= fromDate && tempDate2 <= toDate)) { periods.Add(new Period(tempDate1, tempDate2)); } } } // Expand exception rules and filter out those instances count = periods.Count; foreach (RRuleProperty er in this.ExceptionRules) { // Same as above if (er.Recurrence.MaximumOccurrences == 0 && timeZoneID != null) { tempDate1 = er.Recurrence.RecurUntil; er.Recurrence.RecurUntil = VCalendar.LocalTimeToTimeZoneTime(tempDate1, timeZoneID).StartDateTime; } er.Recurrence.StartDateTime = startDate; recurDates = er.Recurrence.InstancesBetween(fromDate, toDate); if (er.Recurrence.MaximumOccurrences == 0 && timeZoneID != null) { er.Recurrence.RecurUntil = tempDate1; } foreach (DateTime dt in recurDates) { for (idx = 0; idx < count; idx++) { if (periods[idx].StartDateTime == dt) { periods.RemoveAt(idx); idx--; count--; } } } } // Filter out any exception dates foreach (ExDateProperty ed in this.ExceptionDates) { DateTime dt = ed.TimeZoneDateTime; // If it's only a date, assume it's the whole day and remove all instances on that day // regardless of the time. The spec is not clear on this so I'm making a best guess. if (ed.ValueLocation == ValLocValue.DateTime) { if (dt >= fromDate && dt <= toDate) { for (idx = 0; idx < count; idx++) { if (periods[idx].StartDateTime == dt) { periods.RemoveAt(idx); idx--; count--; } } } } else if (dt >= fromDate.Date && dt <= toDate.Date) { for (idx = 0; idx < count; idx++) { if (periods[idx].StartDateTime.Date == dt) { periods.RemoveAt(idx); idx--; count--; } } } } // Sort the periods and remove duplicates periods.Sort(true); for (idx = 1; idx < count; idx++) { if (periods[idx] == periods[idx - 1]) { periods.RemoveAt(idx); idx--; count--; } } } // Now convert the periods to DateTimeInstances that include the necessary time zone information DateTimeInstanceCollection dtic = new DateTimeInstanceCollection(); DateTimeInstance dti, dtiEnd; // Always in local time if there is no time zone ID if (timeZoneID == null) { inLocalTime = true; } foreach (Period pd in periods) { if (inLocalTime) { dti = VCalendar.TimeZoneTimeToLocalTime(pd.StartDateTime, timeZoneID); dtiEnd = VCalendar.TimeZoneTimeToLocalTime(pd.EndDateTime, timeZoneID); } else { dti = VCalendar.TimeZoneTimeInfo(pd.StartDateTime, timeZoneID); dtiEnd = VCalendar.TimeZoneTimeInfo(pd.EndDateTime, timeZoneID); } dti.Duration = pd.Duration; dti.EndDateTime = dtiEnd.EndDateTime; dti.EndIsDaylightSavingTime = dtiEnd.EndIsDaylightSavingTime; dti.EndTimeZoneName = dtiEnd.EndTimeZoneName; // If it already contains the entry and it is in DST, bump it forward an hour to account for the // time adjustment. This will happen on hourly, minutely, and secondly recurrence patterns. By // moving duplicates forward an hour, we retain the expected number of occurrences. if (!dtic.Contains(dti)) { dtic.Add(dti); } else if (dti.StartIsDaylightSavingTime) { dti.StartDateTime = dti.StartDateTime.AddHours(1); dti.EndDateTime = dti.EndDateTime.AddHours(1); dtic.Add(dti); } } return(dtic); // And finally, we are done }
/// <summary> /// Returns a list of the user's calendar items. /// </summary> /// <param name="UserName">User name used for logging in</param> /// <param name="Password">Password for logging in</param> /// <param name="Directory">User's directory</param> /// <param name="StartDate">Date to start at</param> /// <param name="EndDate">Date to end at</param> /// <param name="Server">Server Name</param> /// <returns>A list of the user's calendar items in VCalendar format, between two date ranges</returns> public static List <VCalendar> GetCalendarItems(string UserName, string Password, string Server, string Directory, DateTime StartDate, DateTime EndDate) { List <VCalendar> ReturnArray = new List <VCalendar>(); string Uri = string.Format("http://{0}/exchange/{1}/calendar/", Server, Directory); string Query = "<?xml version=\"1.0\"?>" + "<g:searchrequest xmlns:g=\"DAV:\">" + "<g:sql>SELECT \"urn:schemas:calendar:location\", \"urn:schemas:httpmail:subject\", " + "\"urn:schemas:httpmail:textdescription\", " + "\"urn:schemas:calendar:dtstart\", \"urn:schemas:calendar:dtend\", " + "\"urn:schemas:calendar:busystatus\", \"urn:schemas:calendar:instancetype\" " + "FROM Scope('SHALLOW TRAVERSAL OF \"" + Uri + "\"') " + "WHERE ((\"urn:schemas:calendar:dtstart\" >= '" + StartDate.ToString("yyyy/MM/dd hh:mm:ss") + "' " + "AND \"urn:schemas:calendar:dtstart\" <= '" + EndDate.ToString("yyyy/MM/dd hh:mm:ss") + "') " + "OR (\"urn:schemas:calendar:dtend\" >= '" + StartDate.ToString("yyyy/MM/dd hh:mm:ss") + "' " + "AND \"urn:schemas:calendar:dtstart\" <= '" + EndDate.ToString("yyyy/MM/dd hh:mm:ss") + "')) " + "AND \"DAV:contentclass\" = 'urn:content-classes:appointment' " + "AND NOT \"urn:schemas:calendar:instancetype\" = 1 " + "ORDER BY \"urn:schemas:calendar:dtstart\" ASC" + "</g:sql></g:searchrequest>"; byte[] Contents = System.Text.Encoding.UTF8.GetBytes(Query); HttpWebRequest Request = HttpWebRequest.Create(Uri) as HttpWebRequest; System.Net.CredentialCache MyCredentialCache = new System.Net.CredentialCache(); if (!string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(Password)) { MyCredentialCache.Add(new System.Uri(Uri), "NTLM", new System.Net.NetworkCredential(UserName, Password)); } else { MyCredentialCache.Add(new System.Uri(Uri), "Negotiate", (System.Net.NetworkCredential)CredentialCache.DefaultCredentials); } Request.Credentials = MyCredentialCache; Request.Method = "SEARCH"; Request.ContentLength = Contents.Length; Request.ContentType = "text/xml"; using (System.IO.Stream RequestStream = Request.GetRequestStream()) { RequestStream.Write(Contents, 0, Contents.Length); using (HttpWebResponse Response = Request.GetResponse() as HttpWebResponse) { using (System.IO.Stream ResponseStream = Response.GetResponseStream()) { XmlDocument Document = new XmlDocument(); Document.Load(ResponseStream); foreach (XmlElement Element in Document.GetElementsByTagName("a:prop")) { VCalendar Cal = new VCalendar(); if (Element["e:textdescription"] != null) { Cal.Description = Element["e:textdescription"].InnerText; } if (Element["e:subject"] != null) { Cal.Subject = Element["e:subject"].InnerText; } if (Element["d:location"] != null) { Cal.Location = Element["d:location"].InnerText; } if (Element["d:dtstart"] != null) { Cal.StartTime = DateTime.Parse(Element["d:dtstart"].InnerText); } if (Element["d:dtend"] != null) { Cal.EndTime = DateTime.Parse(Element["d:dtend"].InnerText); } ReturnArray.Add(Cal); } } } } return(ReturnArray); }
public void TestTheToStringMethod() { var vCalString = @"BEGIN:VCALENDAR VERSION:2.0 PRODID:+//IDN bitfire.at//DAVdroid/1.0.8 ical4android ical4j/2.x BEGIN:VEVENT DTSTAMP:20160907T213117Z UID:1d2a9f2f-40d0-4733-b81b-1ea15d79ee21 DTSTART;TZID=America/Havana:20160905T080000 DURATION:PT5700S RRULE:FREQ=WEEKLY;WKST=SU;COUNT=16;BYDAY=MO SUMMARY:Programación y algoritmos CF LOCATION:Aula 8 STATUS:CONFIRMED END:VEVENT BEGIN:VTIMEZONE TZID:America/Havana TZURL:http://tzurl.org/zoneinfo/America/Havana X-LIC-LOCATION:America/Havana BEGIN:DAYLIGHT TZOFFSETFROM:-0500 TZOFFSETTO:-0400 TZNAME:CDT DTSTART:19280610T010000 RDATE:19280610T010000 RDATE:19400602T010000 RDATE:19410601T010000 RDATE:19420607T010000 RDATE:19450603T010000 RDATE:19460602T010000 RDATE:19650601T010000 RDATE:19660529T010000 RDATE:19670408T010000 RDATE:19680414T010000 RDATE:19690427T010000 RDATE:19700426T000000 RDATE:19710425T000000 RDATE:19720430T000000 RDATE:19730429T000000 RDATE:19740428T000000 RDATE:19750427T000000 RDATE:19760425T000000 RDATE:19770424T000000 RDATE:19780507T000000 RDATE:19790318T000000 RDATE:19800316T000000 RDATE:19810510T000000 RDATE:19820509T000000 RDATE:19830508T000000 RDATE:19840506T000000 RDATE:19850505T000000 RDATE:19860316T000000 RDATE:19870315T000000 RDATE:19880320T000000 RDATE:19890319T000000 RDATE:19900401T000000 RDATE:19910407T000000 RDATE:19920405T000000 RDATE:19930404T000000 RDATE:19940403T000000 RDATE:19950402T000000 RDATE:19960407T000000 RDATE:19970406T000000 RDATE:19980329T000000 RDATE:19990328T000000 RDATE:20000402T000000 RDATE:20010401T000000 RDATE:20020407T000000 RDATE:20030406T000000 RDATE:20040328T000000 RDATE:20070311T000000 RDATE:20080316T000000 RDATE:20090308T000000 RDATE:20100314T000000 RDATE:20110320T000000 RDATE:20120401T000000 END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:-0400 TZOFFSETTO:-0500 TZNAME:CST DTSTART:19281010T000000 RDATE:19281010T000000 RDATE:19400901T000000 RDATE:19410907T000000 RDATE:19420906T000000 RDATE:19450902T000000 RDATE:19460901T000000 RDATE:19650930T000000 RDATE:19661002T000000 RDATE:19670910T000000 RDATE:19680908T000000 RDATE:19691026T000000 RDATE:19701025T000000 RDATE:19711031T000000 RDATE:19721008T000000 RDATE:19731008T000000 RDATE:19741008T000000 RDATE:19751026T000000 RDATE:19761031T000000 RDATE:19771030T000000 RDATE:19781008T000000 RDATE:19791014T000000 RDATE:19801012T000000 RDATE:19811011T000000 RDATE:19821010T000000 RDATE:19831009T000000 RDATE:19841014T000000 RDATE:19851013T000000 RDATE:19861012T000000 RDATE:19871011T000000 RDATE:19881009T000000 RDATE:19891008T000000 RDATE:19901014T000000 RDATE:19911013T010000 RDATE:19921011T010000 RDATE:19931010T010000 RDATE:19941009T010000 RDATE:19951008T010000 RDATE:19961006T010000 RDATE:19971012T010000 RDATE:19981025T010000 RDATE:19991031T010000 RDATE:20001029T010000 RDATE:20011028T010000 RDATE:20021027T010000 RDATE:20031026T010000 RDATE:20061029T010000 RDATE:20071028T010000 RDATE:20081026T010000 RDATE:20091025T010000 RDATE:20101031T010000 RDATE:20111113T010000 END:STANDARD END:VTIMEZONE END:VCALENDAR "; var vCal = VCalendar.Parse(vCalString); var stringFromVCal = vCal.ToString(); var vCalFromString = VCalendar.Parse(stringFromVCal); //check the vCalendar's properties Assert.True(checkProperties(vCal.Properties, vCalFromString.Properties)); //check the calendar components foreach (var calComp in vCal.CalendarComponents) { Assert.Contains(calComp.Key, vCalFromString.CalendarComponents.Keys); Assert.Equal(calComp.Value.Count, vCalFromString.CalendarComponents[calComp.Key].Count); Assert.True(checkProperties(calComp.Value.First().Properties, vCalFromString.CalendarComponents[calComp.Key].First().Properties)); } }
public void UnitTest3() { var calStr = @"BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Example Corp.//CalDAV Client//EN BEGIN:VTIMEZONE LAST-MODIFIED:20040110T032845Z TZID:US/Eastern BEGIN:DAYLIGHT DTSTART:20000404T020000 RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4 TZNAME:EDT TZOFFSETFROM:-0500 TZOFFSETTO:-0400 END:DAYLIGHT BEGIN:STANDARD DTSTART:20001026T020000 RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 TZNAME:EST TZOFFSETFROM:-0400 TZOFFSETTO:-0500 END:STANDARD END:VTIMEZONE BEGIN:VEVENT ATTENDEE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:[email protected] ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:[email protected] DTSTAMP:20060206T001220Z DTSTART;TZID=US/Eastern:20060104T100000 DURATION:PT1H RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 LAST-MODIFIED:20060206T001330Z ORGANIZER:mailto:[email protected] SEQUENCE:1 STATUS:TENTATIVE SUMMARY:Event #3 UID:[email protected] X-ABC-GUID:[email protected] END:VEVENT END:VCALENDAR"; var result = VCalendar.Parse(calStr); var xmlStr = @" <C:calendar-data xmlns:C=""urn:ietf:params:xml:ns:caldav""> <C:comp name=""VCALENDAR""> <C:prop name=""VERSION""/> <C:comp name=""VEVENT""> <C:prop name=""SUMMARY""/> <C:prop name=""UID""/> <C:prop name=""DTSTART""/> <C:prop name=""DTEND""/> <C:prop name=""DURATION""/> <C:prop name=""RRULE""/> <C:prop name=""ATTENDEE""/> <C:prop name=""EXRULE""/> <C:prop name=""EXDATE""/> <C:prop name=""RECURRENCE-ID""/> </C:comp> <C:comp name=""VTIMEZONE""/> </C:comp> </C:calendar-data>"; var calString = result.ToString(XmlTreeStructure.Parse(xmlStr)); }
public void TestNullReferenceOnDurationProp() { var vCalString = @"BEGIN:VCALENDAR VERSION:2.0 PRODID:+//IDN bitfire.at//DAVdroid/1.0.8 ical4android ical4j/2.x BEGIN:VEVENT DTSTAMP:20160907T213117Z UID:1d2a9f2f-40d0-4733-b81b-1ea15d79ee21 DTSTART;TZID=America/Havana:20160905T080000 DURATION:PT5700S RRULE:FREQ=WEEKLY;WKST=SU;COUNT=16;BYDAY=MO SUMMARY:Programación y algoritmos CF LOCATION:Aula 8 STATUS:CONFIRMED END:VEVENT BEGIN:VTIMEZONE TZID:America/Havana TZURL:http://tzurl.org/zoneinfo/America/Havana X-LIC-LOCATION:America/Havana BEGIN:STANDARD TZOFFSETFROM:-0400 TZOFFSETTO:-0500 TZNAME:CST DTSTART:20121104T010000 RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU END:STANDARD BEGIN:DAYLIGHT TZOFFSETFROM:-0500 TZOFFSETTO:-0400 TZNAME:CDT DTSTART:20130310T000000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:-052928 TZOFFSETTO:-052936 TZNAME:HMT DTSTART:18900101T000000 RDATE:18900101T000000 END:STANDARD BEGIN:STANDARD TZOFFSETFROM:-052936 TZOFFSETTO:-0500 TZNAME:CST DTSTART:19250719T120000 RDATE:19250719T120000 END:STANDARD BEGIN:DAYLIGHT TZOFFSETFROM:-0500 TZOFFSETTO:-0400 TZNAME:CDT DTSTART:19280610T010000 RDATE:19280610T010000 RDATE:19400602T010000 RDATE:19410601T010000 RDATE:19420607T010000 RDATE:19450603T010000 RDATE:19460602T010000 RDATE:19650601T010000 RDATE:19660529T010000 RDATE:19670408T010000 RDATE:19680414T010000 RDATE:19690427T010000 RDATE:19700426T000000 RDATE:19710425T000000 RDATE:19720430T000000 RDATE:19730429T000000 RDATE:19740428T000000 RDATE:19750427T000000 RDATE:19760425T000000 RDATE:19770424T000000 RDATE:19780507T000000 RDATE:19790318T000000 RDATE:19800316T000000 RDATE:19810510T000000 RDATE:19820509T000000 RDATE:19830508T000000 RDATE:19840506T000000 RDATE:19850505T000000 RDATE:19860316T000000 RDATE:19870315T000000 RDATE:19880320T000000 RDATE:19890319T000000 RDATE:19900401T000000 RDATE:19910407T000000 RDATE:19920405T000000 RDATE:19930404T000000 RDATE:19940403T000000 RDATE:19950402T000000 RDATE:19960407T000000 RDATE:19970406T000000 RDATE:19980329T000000 RDATE:19990328T000000 RDATE:20000402T000000 RDATE:20010401T000000 RDATE:20020407T000000 RDATE:20030406T000000 RDATE:20040328T000000 RDATE:20070311T000000 RDATE:20080316T000000 RDATE:20090308T000000 RDATE:20100314T000000 RDATE:20110320T000000 RDATE:20120401T000000 END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:-0400 TZOFFSETTO:-0500 TZNAME:CST DTSTART:19281010T000000 RDATE:19281010T000000 RDATE:19400901T000000 RDATE:19410907T000000 RDATE:19420906T000000 RDATE:19450902T000000 RDATE:19460901T000000 RDATE:19650930T000000 RDATE:19661002T000000 RDATE:19670910T000000 RDATE:19680908T000000 RDATE:19691026T000000 RDATE:19701025T000000 RDATE:19711031T000000 RDATE:19721008T000000 RDATE:19731008T000000 RDATE:19741008T000000 RDATE:19751026T000000 RDATE:19761031T000000 RDATE:19771030T000000 RDATE:19781008T000000 RDATE:19791014T000000 RDATE:19801012T000000 RDATE:19811011T000000 RDATE:19821010T000000 RDATE:19831009T000000 RDATE:19841014T000000 RDATE:19851013T000000 RDATE:19861012T000000 RDATE:19871011T000000 RDATE:19881009T000000 RDATE:19891008T000000 RDATE:19901014T000000 RDATE:19911013T010000 RDATE:19921011T010000 RDATE:19931010T010000 RDATE:19941009T010000 RDATE:19951008T010000 RDATE:19961006T010000 RDATE:19971012T010000 RDATE:19981025T010000 RDATE:19991031T010000 RDATE:20001029T010000 RDATE:20011028T010000 RDATE:20021027T010000 RDATE:20031026T010000 RDATE:20061029T010000 RDATE:20071028T010000 RDATE:20081026T010000 RDATE:20091025T010000 RDATE:20101031T010000 RDATE:20111113T010000 END:STANDARD END:VTIMEZONE END:VCALENDAR "; var vCal = VCalendar.Parse(vCalString); var stringFromVCal = vCal.ToString(); Assert.NotNull(stringFromVCal); }
/// <summary> /// Constructor /// </summary> public AppointmentSender() : base() { AppointmentInfo = new VCalendar(); }
/// <summary> /// Save changes and return to the calendar browser /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> protected void btnSave_Click(object sender, EventArgs e) { DateTime startDate = DateTime.MinValue, endDate = DateTime.MinValue; Duration dur = Duration.Zero; if (!Page.IsValid) { return; } lblMsg.Text = null; // Perform some edits if (txtStartDate.Text.Trim().Length != 0 && !DateTime.TryParse(txtStartDate.Text, CultureInfo.CurrentCulture, DateTimeStyles.None, out startDate)) { lblMsg.Text = "Invalid start date format<br>"; } if (txtEndDate.Text.Trim().Length != 0 && !DateTime.TryParse(txtEndDate.Text, CultureInfo.CurrentCulture, DateTimeStyles.None, out endDate)) { lblMsg.Text += "Invalid end date format<br>"; } if (txtDuration.Text.Trim().Length != 0 && !Duration.TryParse(txtDuration.Text, out dur)) { lblMsg.Text += "Invalid duration format<br>"; } if (startDate != DateTime.MinValue && endDate != DateTime.MinValue && startDate > endDate) { lblMsg.Text += "Start date must be less than or equal to end date<br>"; } if (!String.IsNullOrWhiteSpace(lblMsg.Text)) { return; } VCalendar cal = (VCalendar)Session["VCalendar"]; // Not very friendly, but it's just a demo if (cal == null) { Response.Redirect("CalendarBrowser.aspx"); return; } VFreeBusy fb = cal.FreeBusys[(int)this.ViewState["FreeBusyIndex"]]; // The unique ID is not changed fb.Organizer.Value = txtOrganizer.Text; fb.Contact.Value = txtContact.Text; // We'll use the TimeZoneDateTime property on all date/time values so that they are set literally // rather than being converted to the time zone as would happen with the DateTimeValue property. fb.StartDateTime.TimeZoneDateTime = startDate; fb.StartDateTime.ValueLocation = ValLocValue.DateTime; fb.EndDateTime.TimeZoneDateTime = endDate; fb.StartDateTime.ValueLocation = ValLocValue.DateTime; fb.Duration.DurationValue = dur; fb.Url.Value = txtUrl.Text; fb.Comment.Value = txtComments.Text; Response.Redirect("CalendarBrowser.aspx"); }
/// <summary> /// This is used to custom draw the start date/time and summary columns based on the information /// available. /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void dgvCalendar_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { CurrencyManager cm; StartDateProperty startProp; SummaryProperty summaryProp; DescriptionProperty descProp; DateTimeInstance dti; Color foreColor; object item; string columnText = null; if (e.RowIndex > -1 && (e.ColumnIndex == 0 || e.ColumnIndex == 1)) { cm = (CurrencyManager)dgvCalendar.BindingContext[dgvCalendar.DataSource]; item = cm.List[e.RowIndex]; if (e.ColumnIndex == 0) { if (item is VEvent) { startProp = ((VEvent)item).StartDateTime; } else if (item is VToDo) { startProp = ((VToDo)item).StartDateTime; } else if (item is VJournal) { startProp = ((VJournal)item).StartDateTime; } else { startProp = ((VFreeBusy)item).StartDateTime; } dti = VCalendar.TimeZoneTimeInfo(startProp.TimeZoneDateTime, startProp.TimeZoneId); // Format as date or date/time and include time zone if available if (startProp.ValueLocation == ValLocValue.Date) { columnText = String.Format("{0:d} {1}", dti.StartDateTime, dti.AbbreviatedStartTimeZoneName); } else { columnText = String.Format("{0} {1}", dti.StartDateTime, dti.AbbreviatedStartTimeZoneName); } } else if (e.ColumnIndex == 1) { if (item is VEvent) { summaryProp = ((VEvent)item).Summary; descProp = ((VEvent)item).Description; } else if (item is VToDo) { summaryProp = ((VToDo)item).Summary; descProp = ((VToDo)item).Description; } else if (item is VJournal) { summaryProp = ((VJournal)item).Summary; descProp = ((VJournal)item).Description; } else { summaryProp = null; descProp = null; } // If summary is empty, use description instead if (summaryProp != null && summaryProp.Value != null) { columnText = summaryProp.Value; } else if (descProp != null) { columnText = descProp.Value; } } if (columnText != null) { // If multi-line, limit it to the first line if (columnText.IndexOf('\n') != -1) { columnText = columnText.Substring(0, columnText.IndexOf('\n')); } e.Paint(e.CellBounds, e.PaintParts & ~DataGridViewPaintParts.ContentForeground); // Based the foreground color on the selected state if ((e.State & DataGridViewElementStates.Selected) != 0) { foreColor = e.CellStyle.SelectionForeColor; } else { foreColor = e.CellStyle.ForeColor; } using (SolidBrush b = new SolidBrush(foreColor)) { e.Graphics.DrawString(columnText, e.CellStyle.Font, b, e.CellBounds, sf); } e.Handled = true; } } }
/// <summary> /// Test the recurrence within the specified iCalendar component /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void btnTest_Click(object sender, EventArgs e) { RecurringObject ro = null; DateTimeInstanceCollection instances; string calendar; int start; double elapsed; try { lblCount.Text = null; // Wrap it in VCALENDAR tags and parse it calendar = String.Format("BEGIN:VCALENDAR\nVERSION:2.0\n{0}\nEND:VCALENDAR", txtCalendar.Text); VCalendar cal = VCalendarParser.ParseFromString(calendar); // Get the first event, to-do, or journal item if (cal.Events.Count > 0) { ro = cal.Events[0]; } else if (cal.ToDos.Count > 0) { ro = cal.ToDos[0]; } else if (cal.Journals.Count > 0) { ro = cal.Journals[0]; } if (ro == null) { lblCount.Text = "No event, to-do, or journal item found"; return; } // Apply the time zone to the calendar. If "None" is selected, the time zone will be cleared on // all items. if (cboTimeZone.SelectedIndex < 1) { cal.ApplyTimeZone(null); } else { cal.ApplyTimeZone(VCalendar.TimeZones[cboTimeZone.SelectedIndex - 1]); } txtCalendar.Text = ro.ToString(); lbDates.Items.Clear(); this.Cursor = Cursors.WaitCursor; start = System.Environment.TickCount; instances = ro.InstancesBetween(dtpStartDate.Value, dtpEndDate.Value, chkInLocalTime.Checked); elapsed = (System.Environment.TickCount - start) / 1000.0; cal.Dispose(); // The date instance contains the start and end date/times, the duration, and time zone // information. The duration is based on the duration of the calendar component. The time // zone information is based on the "In Local Time" parameter of the InstancesBetween() method // and whether or not the component has a Time Zone ID specified. foreach (DateTimeInstance dti in instances) { lbDates.Items.Add(String.Format("{0:G} {1} to {2:G} {3} ({4})", dti.StartDateTime, dti.AbbreviatedStartTimeZoneName, dti.EndDateTime, dti.AbbreviatedEndTimeZoneName, dti.Duration.ToDescription())); if (lbDates.Items.Count > 5000) { lblCount.Text += "A large number of instances were returned. Only the first 5000 " + "have been loaded into the list box.\r\n"; break; } } // If nothing was found remind the user that they may need to adjust the start and end date range // to find stuff within the item. if (instances.Count == 0) { MessageBox.Show("Nothing found. If this was unexpected, check the limiting date range in " + "the two date/time text boxes at the top of the form and the calendar item date/time " + "properties to make sure that they do overlap"); } lblCount.Text += String.Format("Found {0:N0} instances in {1:N2} seconds ({2:N2} instances/second)", instances.Count, elapsed, instances.Count / elapsed); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } finally { this.Cursor = Cursors.Default; } }
/// <summary> /// Generate instances for the specified component /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event parameters</param> protected void btnTest_Click(object sender, EventArgs e) { RecurringObject ro = null; DateTimeInstanceCollection instances; string calendar; int start; double elapsed; DateTime startDate, endDate; try { lblCount.Text = String.Empty; if (!DateTime.TryParse(txtStartDate.Text, CultureInfo.CurrentCulture, DateTimeStyles.None, out startDate) || !DateTime.TryParse(txtEndDate.Text, CultureInfo.CurrentCulture, DateTimeStyles.None, out endDate)) { lblCount.Text = "Invalid start or end date/time format"; return; } // Wrap it in VCALENDAR tags and parse it calendar = String.Format("BEGIN:VCALENDAR\nVERSION:2.0\n{0}\nEND:VCALENDAR", txtCalendar.Text); VCalendar cal = VCalendarParser.ParseFromString(calendar); // Get the first event, to-do, or journal item if (cal.Events.Count > 0) { ro = cal.Events[0]; } else if (cal.ToDos.Count > 0) { ro = cal.ToDos[0]; } else if (cal.Journals.Count > 0) { ro = cal.Journals[0]; } if (ro == null) { lblCount.Text = "No event, to-do, or journal item found"; return; } // Apply the time zone to the calendar. If "None" is selected, the time zone will be cleared on // all items. if (cboTimeZone.SelectedIndex < 1) { cal.ApplyTimeZone(null); } else { cal.ApplyTimeZone(VCalendar.TimeZones[cboTimeZone.SelectedIndex - 1]); } foreach (RRuleProperty rrule in ro.RecurrenceRules) { ApplyLimits(ro, rrule.Recurrence); } foreach (ExRuleProperty exrule in ro.ExceptionRules) { ApplyLimits(ro, exrule.Recurrence); } txtCalendar.Text = ro.ToString(); start = System.Environment.TickCount; instances = ro.InstancesBetween(startDate, endDate, chkInLocalTime.Checked); elapsed = (System.Environment.TickCount - start) / 1000.0; cal.Dispose(); // The date instance contains the start and end date/times, the duration, and time zone // information. The duration is based on the duration of the calendar component. The time zone // information is based on the "In Local Time" parameter of the InstancesBetween() method and // whether or not the component has a Time Zone ID specified. dlDates.DataSource = instances; dlDates.DataBind(); // If nothing was found remind the user that they may need to adjust the start and end date range // to find stuff within the item. if (instances.Count == 0) { lblCount.Text = "Nothing found. If this was unexpected, check the limiting date range " + "in the two date/time text boxes at the top of the form and the calendar item date/time " + "properties to make sure that they do overlap<br/><br/>"; } lblCount.Text += String.Format("Found {0:N0} instances in {1:N2} seconds ({2:N2} instances/second)", instances.Count, elapsed, instances.Count / elapsed); } catch (Exception ex) { lblCount.Text = ex.Message; } }
public void ToStringTest() { var calString = @"BEGIN:VCALENDAR PRODID:-//Google Inc//Google Calendar 70.9054//EN VERSION:2.0 CALSCALE:GREGORIAN X-WR-CALNAME:[email protected] X-WR-TIMEZONE:America/Los_Angeles BEGIN:VTIMEZONE TZID:America/Los_Angeles X-LIC-LOCATION:America/Los_Angeles BEGIN:DAYLIGHT TZOFFSETFROM:-0800 TZOFFSETTO:-0700 TZNAME:PDT DTSTART:19700308T020000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:-0700 TZOFFSETTO:-0800 TZNAME:PST DTSTART:19701101T020000 RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTART;TZID=America/Los_Angeles:20120629T130000 DTEND;TZID=America/Los_Angeles:20120629T140000 DTSTAMP:20120629T112428Z UID:[email protected] RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU CREATED:20120629T111935Z DESCRIPTION:foo LAST-MODIFIED:20120629T112428Z LOCATION:Barcelona SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Demo B2G Calendar TRANSP:OPAQUE BEGIN:VALARM ACTION:EMAIL DESCRIPTION:This is an event reminder SUMMARY:Alarm notification ATTENDEE:mailto:[email protected] TRIGGER:-P0DT0H30M0S END:VALARM BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:This is an event reminder TRIGGER:-P0DT0H30M0S END:VALARM END:VEVENT END:VCALENDAR "; VCalendar calendar = VCalendar.Parse(calString); var xmlDoc = @"<?xml version=""1.0"" encoding=""utf-8"" ?> <C:calendar-query xmlns:D=""DAV:"" xmlns:C=""urn:ietf:params:xml:ns:caldav""> <D:prop> <D:getetag/> <C:calendar-data> <C:comp name=""VCALENDAR""> <C:prop name=""VERSION""/> <C:comp name=""VEVENT""> <C:prop name=""SUMMARY""/> <C:prop name=""UID""/> <C:prop name=""DTSTART""/> <C:prop name=""DTEND""/> </C:comp> <C:comp name=""VTIMEZONE""/> </C:comp> </C:calendar-data> </D:prop> <C:filter> <C:comp-filter name=""VCALENDAR""> <C:comp-filter name=""VEVENT""> <C:time-range start=""20060104T000000Z"" end=""20060105T000000Z""/> </C:comp-filter> </C:comp-filter> </C:filter> </C:calendar-query>"; var xmlTree = XmlTreeStructure.Parse(xmlDoc); var node = xmlTree.GetChildAtAnyLevel("calendar-data"); var newCalString = calendar.ToString(node); var newCal = new VCalendar(newCalString); Assert.Equal(2, newCal.CalendarComponents.Count); Assert.Contains("VEVENT", newCal.CalendarComponents.Keys); Assert.Contains("VTIMEZONE", newCal.CalendarComponents.Keys); Assert.Equal(4, newCal.CalendarComponents["VEVENT"].First().Properties.Count); }
/// <summary> /// This is used to apply the time zone selection to all date/time values in the dialog box /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event parameters</param> private void btnApplyTZ_Click(object sender, EventArgs e) { DateTimeInstance dti; string sourceTZ, destTZ; if (cboTimeZone.SelectedIndex == timeZoneIdx) { MessageBox.Show("The time zone has not changed", "No Change", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } if (MessageBox.Show(String.Format("Do you want to convert all times from the '{0}' time zone to " + "the '{1}' time zone?", cboTimeZone.Items[timeZoneIdx], cboTimeZone.Items[cboTimeZone.SelectedIndex]), "Change Time Zone", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) { return; } // Get the time zone IDs if (timeZoneIdx == 0) { sourceTZ = null; } else { sourceTZ = (string)cboTimeZone.Items[timeZoneIdx]; } destTZ = (string)cboTimeZone.Items[cboTimeZone.SelectedIndex]; // Convert the times if (sourceTZ == null) { if (dtpStartDate.Checked) { dti = VCalendar.LocalTimeToTimeZoneTime(dtpStartDate.Value, destTZ); dtpStartDate.Value = dti.StartDateTime; } if (dtpEndDate.Checked) { dti = VCalendar.LocalTimeToTimeZoneTime(dtpEndDate.Value, destTZ); dtpEndDate.Value = dti.StartDateTime; } } else { if (dtpStartDate.Checked) { dti = VCalendar.TimeZoneToTimeZone(dtpStartDate.Value, sourceTZ, destTZ); dtpStartDate.Value = dti.StartDateTime; } if (dtpEndDate.Checked) { dti = VCalendar.TimeZoneToTimeZone(dtpEndDate.Value, sourceTZ, destTZ); dtpEndDate.Value = dti.StartDateTime; } } ucFreeBusy.ApplyTimeZone(sourceTZ, destTZ); timeZoneIdx = cboTimeZone.SelectedIndex; }
public void Returns_Correct_VCalendar() { // Arrange var e0 = new EventModel(Rnd.DateTime, Rnd.DateTime, false, Rnd.Str, Rnd.Str, Rnd.Str, false); var e1 = new EventModel(Rnd.DateTime, Rnd.DateTime, false, Rnd.Str, Rnd.Str, Rnd.Str, true); var events = ImmutableList.Create(e0, e1); var lastModified = Rnd.DateTime; var lastModifiedStr = VCalendar.Format(lastModified); var calendar = new CalendarModel(events, lastModified); var tzid = Rnd.Str; var domain = Rnd.Str; var vcal = new VCalendar(calendar, tzid); var expected = new StringBuilder() .AppendLine("BEGIN:VCALENDAR") .AppendLine("VERSION:2.0") .AppendLine("PRODID:-//bfren//NONSGML Jeebs.Calendar//EN") .AppendLine("CALSCALE:GREGORIAN") .AppendLine("X-PUBLISHED-TTL:PT1H") .AppendLine("BEGIN:VTIMEZONE") .AppendLine("TZID:Europe/London") .AppendLine("BEGIN:STANDARD") .AppendLine("TZNAME:GMT") .AppendLine("DTSTART:19710101T020000") .AppendLine("TZOFFSETFROM:+0100") .AppendLine("TZOFFSETTO:+0000") .AppendLine("RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU") .AppendLine("END:STANDARD") .AppendLine("BEGIN:DAYLIGHT") .AppendLine("TZNAME:BST") .AppendLine("DTSTART:19710101T010000") .AppendLine("TZOFFSETFROM:+0000") .AppendLine("TZOFFSETTO:+0100") .AppendLine("RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU") .AppendLine("END:DAYLIGHT") .AppendLine("END:VTIMEZONE") .AppendLine("BEGIN:VEVENT") .AppendLine($"UID:{lastModifiedStr}-000000@{domain}") .AppendLine($"CREATED:{lastModifiedStr}") .AppendLine($"LAST-MODIFIED:{lastModifiedStr}") .AppendLine($"DTSTAMP:{lastModifiedStr}") .AppendLine($"SUMMARY:{e0.Summary}") .AppendLine($"DESCRIPTION:{e0.Description}") .AppendLine($"LOCATION:{e0.Location}") .AppendLine($"DTSTART;TZID={tzid}:{VCalendar.Format(e0.Start)}") .AppendLine($"DTEND;TZID={tzid}:{VCalendar.Format(e0.End)}") .AppendLine("END:VEVENT") .AppendLine("BEGIN:VEVENT") .AppendLine($"UID:{lastModifiedStr}-000001@{domain}") .AppendLine($"CREATED:{lastModifiedStr}") .AppendLine($"LAST-MODIFIED:{lastModifiedStr}") .AppendLine($"DTSTAMP:{lastModifiedStr}") .AppendLine($"SUMMARY:{e1.Summary}") .AppendLine($"DESCRIPTION:{e1.Description}") .AppendLine($"LOCATION:{e1.Location}") .AppendLine($"DTSTART;TZID={tzid}:{VCalendar.Format(e1.Start)}") .AppendLine($"DTEND;TZID={tzid}:{VCalendar.Format(e1.End)}") .AppendLine("TRANSP:TRANSPARENT") .AppendLine("END:VEVENT") .AppendLine("END:VCALENDAR") .ToString(); // Act var result = vcal.ToString(domain); // Assert Assert.Equal(expected, result); }