Exemple #1
0
        //=====================================================================

        /// <summary>
        /// This is overridden to allow cloning of a PDI object
        /// </summary>
        /// <returns>A clone of the object.</returns>
        public override object Clone()
        {
            ObservanceRule o = new ObservanceRule();

            o.Clone(this);
            return(o);
        }
Exemple #2
0
        /// <summary>
        /// This is overridden to allow proper comparison of observance objects
        /// </summary>
        /// <param name="obj">The object to which this instance is compared</param>
        /// <returns>Returns true if the object equals this instance, false if it does not</returns>
        public override bool Equals(object obj)
        {
            ObservanceRule obr = obj as ObservanceRule;

            if (obr == null)
            {
                return(false);
            }

            // The ToString() method returns a text representation of the observance based on all of its settings
            // so it's a reliable way to tell if two instances are the same.
            return(this == obr || this.ToString() == obr.ToString());
        }
Exemple #3
0
        /// <summary>
        /// This is overridden to allow copying of the additional properties
        /// </summary>
        /// <param name="p">The PDI object from which the settings are to be copied</param>
        protected override void Clone(PDIObject p)
        {
            ObservanceRule o = (ObservanceRule)p;

            this.ClearProperties();

            ruleType   = o.RuleType;
            startDate  = (StartDateProperty)o.StartDateTime.Clone();
            offsetFrom = (TimeZoneOffsetProperty)o.OffsetFrom.Clone();
            offsetTo   = (TimeZoneOffsetProperty)o.OffsetTo.Clone();
            comment    = (CommentProperty)o.Comment.Clone();

            this.RecurrenceRules.CloneRange(o.RecurrenceRules);
            this.RecurDates.CloneRange(o.RecurDates);
            this.TimeZoneNames.CloneRange(o.TimeZoneNames);
            this.CustomProperties.CloneRange(o.CustomProperties);
        }
        /// <summary>
        /// Update the prior row with the values from the unbound controls and load the values for the new row
        /// when the position changes.
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void BindingSource_PositionChanged(object sender, EventArgs e)
        {
            ObservanceRule newItem = (ObservanceRule)this.BindingSource.Current;
            int hours, minutes;

            // If all deleted, ignore it
            if(newItem == null)
            {
                currentRule = null;
                return;
            }

            // Save changes to the unbound controls to the prior row
            this.StoreChanges();

            // Load the new values into the unbound controls
            currentRule = newItem;

            // We'll only edit the first time zone name
            if(currentRule.TimeZoneNames.Count == 0)
                currentRule.TimeZoneNames.Add("GMT");

            txtTZName.Text = currentRule.TimeZoneNames[0].Value;

            hours = currentRule.OffsetFrom.TimeSpanValue.Hours;
            minutes = currentRule.OffsetFrom.TimeSpanValue.Minutes;

            // If hours are specified, keep minutes positive
            if(hours != 0 && minutes < 0)
                minutes *= -1;

            udcFromHours.Value = (hours < -23) ? -23 : (hours > 23) ? 23 : hours;
            udcFromMinutes.Value = (minutes < -59) ? -59 : (minutes > 59) ? 59 : minutes;

            hours = currentRule.OffsetTo.TimeSpanValue.Hours;
            minutes = currentRule.OffsetTo.TimeSpanValue.Minutes;

            // If hours are specified, keep minutes positive
            if(hours != 0 && minutes < 0)
                minutes *= -1;

            udcToHours.Value = (hours < -23) ? -23 : (hours > 23) ? 23 : hours;
            udcToMinutes.Value = (minutes < -59) ? -59 : (minutes > 59) ? 59 : minutes;

            rcRulesDates.SetValues(currentRule.RecurrenceRules, currentRule.RecurDates);
        }
Exemple #5
0
        /// <summary>
        /// This is used by the time zone conversion methods to find the correct observance rules to calculate
        /// the standard time and daylight saving time information.
        /// </summary>
        /// <param name="convertDate">The date being converted.</param>
        /// <param name="timeZoneId">The time zone for the conversion.</param>
        /// <param name="useLocalTime">True to return information in local time or false to return the
        /// information in the specified time zone's time.</param>
        /// <param name="standardRule">This is used to returned the standard rule.  It is null if one is not
        /// found.</param>
        /// <param name="daylightRule">This is used to returned the daylight rule.  It is null if one is not
        /// found.</param>
        /// <param name="standardDate">This is used to return the start of standard time for the returned
        /// standard rule.</param>
        /// <param name="dstDate">This is used to return the start of daylight saving time for the returned
        /// daylight rule.</param>
        private static void FindRules(DateTime convertDate, string timeZoneId, bool useLocalTime,
          out ObservanceRule standardRule, out ObservanceRule daylightRule, out DateTime standardDate,
          out DateTime dstDate)
        {
            DateTime startDate;
            DateTimeCollection dates;

            standardRule = daylightRule = null;
            standardDate = dstDate = DateTime.MinValue;

            VTimeZone vtz = timeZones[timeZoneId];

            if(vtz == null)
                return;

            // In order to calculate the correct time, we need the UTC offset for standard time locally
            TimeZone tzCurrent = TimeZone.CurrentTimeZone;
            TimeSpan tsUTC = tzCurrent.GetUtcOffset(tzCurrent.GetDaylightChanges(convertDate.Year).End);

            // Get the observance rules to use in the conversion
            foreach(ObservanceRule or in vtz.ObservanceRules)
            {
                startDate = or.StartDateTime.TimeZoneDateTime;

                if(startDate.Year > convertDate.Year)
                    continue;

                // Find the first standard rule that generates a date for the date/time's year
                if(standardRule == null && or.RuleType == ObservanceRuleType.Standard)
                {
                    // Check for an RDATE that matches.
                    foreach(RDateProperty rdt in or.RecurDates)
                        if(rdt.TimeZoneDateTime.Year == convertDate.Year)
                        {
                            standardRule = or;

                            if(useLocalTime)
                                standardDate = rdt.TimeZoneDateTime.Add(or.OffsetFrom.TimeSpanValue.Negate()).ToLocalTime();
                            else
                                standardDate = rdt.TimeZoneDateTime;

                            break;
                        }

                    // If there wasn't one, check the RRULEs
                    if(standardRule == null)
                        foreach(RRuleProperty rrule in or.RecurrenceRules)
                        {
                            // Set the start date and resolve the recurrence
                            rrule.Recurrence.StartDateTime = startDate;
                            dates = rrule.Recurrence.InstancesBetween(new DateTime(convertDate.Year, 1, 1),
                                new DateTime(convertDate.Year, 12, 31, 23, 59, 59));

                            // There should only be one...
                            if(dates.Count != 0)
                            {
                                standardRule = or;

                                if(useLocalTime)
                                    standardDate = dates[0].Add(or.OffsetTo.TimeSpanValue.Negate()).Add(tsUTC);
                                else
                                    standardDate = dates[0];

                                break;
                            }
                        }

                    // If it doesn't have any RDATEs or RRULEs and the year is on or after the start date year,
                    // use the start date.
                    if(or.RecurDates.Count == 0 && or.RecurrenceRules.Count == 0 && startDate.Year <= convertDate.Year)
                    {
                        standardRule = or;

                        if(useLocalTime)
                            standardDate = startDate.Add(or.OffsetTo.TimeSpanValue.Negate()).Add(tsUTC);
                        else
                            standardDate = startDate;
                    }
                }

                // Find the first daylight rule that generates a date for the date/times' year
                if(daylightRule == null && or.RuleType == ObservanceRuleType.Daylight)
                {
                    // Check for an RDATE that matches.
                    foreach(RDateProperty rdt in or.RecurDates)
                        if(rdt.TimeZoneDateTime.Year == convertDate.Year)
                        {
                            daylightRule = or;

                            if(useLocalTime)
                                dstDate = rdt.TimeZoneDateTime.Add(or.OffsetFrom.TimeSpanValue.Negate()).ToLocalTime();
                            else
                                dstDate = rdt.TimeZoneDateTime;

                            break;
                        }

                    // If there wasn't one, check the RRULEs
                    if(daylightRule == null)
                        foreach(RRuleProperty rrule in or.RecurrenceRules)
                        {
                            // Set the start date and resolve the recurrence
                            rrule.Recurrence.StartDateTime = startDate;
                            dates = rrule.Recurrence.InstancesBetween(new DateTime(convertDate.Year, 1, 1),
                                new DateTime(convertDate.Year, 12, 31, 23, 59, 59));

                            // There should only be one...
                            if(dates.Count != 0)
                            {
                                daylightRule = or;

                                if(useLocalTime)
                                    dstDate = dates[0].Add(or.OffsetFrom.TimeSpanValue.Negate()).Add(tsUTC);
                                else
                                    dstDate = dates[0];

                                break;
                            }
                        }

                    // If it doesn't have any RDATEs or RRULEs and the year is on or after the start date year,
                    // use the start date.
                    if(or.RecurDates.Count == 0 && or.RecurrenceRules.Count == 0 && startDate.Year <= convertDate.Year)
                    {
                        daylightRule = or;

                        if(useLocalTime)
                            dstDate = startDate.Add(or.OffsetFrom.TimeSpanValue.Negate()).Add(tsUTC);
                        else
                            dstDate = startDate;
                    }
                }

                // Stop when we've got a match for each
                if(standardRule != null && daylightRule != null)
                    break;
            }
        }
Exemple #6
0
        //=====================================================================

        /// <summary>
        /// This is overridden to allow cloning of a PDI object
        /// </summary>
        /// <returns>A clone of the object.</returns>
        public override object Clone()
        {
            ObservanceRule o = new ObservanceRule();
            o.Clone(this);
            return o;
        }
Exemple #7
0
        //=====================================================================

        /// <summary>
        /// This is overridden to handle the additional state maintained by the calendar parser
        /// </summary>
        /// <param name="fullReset">If true, a full reset is done (i.e. this is the start of a brand new session.
        /// If false only the line state is reset (it's done parsing a property name or value).</param>
        protected override void ResetState(bool fullReset)
        {
            if(fullReset)
            {
                currentState = VCalendarParserState.VCalendar;
                vEvent = null;
                vToDo = null;
                vJournal = null;
                vAlarm = null;
                vFreeBusy = null;
                vTimeZone = null;
                obsRule = null;

                priorState.Clear();
                beginValue.Clear();
            }

            base.ResetState(fullReset);
        }
Exemple #8
0
        /// <summary>
        /// This is implemented to handle properties related to observance rule items in VTimeZone objects
        /// </summary>
        /// <param name="propertyName">The name of the property.</param>
        /// <param name="parameters">A string collection containing the parameters and their values.  If empty,
        /// there are no parameters.</param>
        /// <param name="propertyValue">The value of the property.</param>
        protected virtual void ObservanceRuleParser(string propertyName, StringCollection parameters, string propertyValue)
        {
            StringCollection sc;
            string[] parts, parms;
            int idx;

            // The last entry is always CustomProperty so scan for length minus one
            for(idx = 0; idx < ntvORule.Length - 1; idx++)
                if(ntvORule[idx].IsMatch(propertyName))
                    break;

            // An opening BEGIN:STANDARD or BEGIN:DAYLIGHT property must have been seen.
            if(obsRule == null)
                throw new PDIParserException(this.LineNumber, LR.GetString("ExParseNoBeginProp",
                        "BEGIN:STANDARD/BEGIN:DAYLIGHT", propertyName));

            // Handle or create the property
            switch(ntvORule[idx].EnumValue)
            {
                case PropertyType.Begin:    // Handle unknown nested objects
                    priorState.Push(currentState);
                    currentState = VCalendarParserState.Custom;
                    CustomObjectParser(propertyName, parameters, propertyValue);
                    break;

                case PropertyType.End:
                    // For this, the value must be STANDARD or DAYLIGHT depending on the rule type
                    if((obsRule.RuleType == ObservanceRuleType.Standard &&
                      String.Compare(propertyValue.Trim(), "STANDARD", StringComparison.OrdinalIgnoreCase) != 0) ||
                      (obsRule.RuleType == ObservanceRuleType.Daylight &&
                      String.Compare(propertyValue.Trim(), "DAYLIGHT", StringComparison.OrdinalIgnoreCase) != 0))
                    {
                        throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedTagValue",
                            ntvORule[idx].Name, propertyValue));
                    }

                    // The rule is added to the collection when created so we don't have to rely on an END tag to
                    // add it.
                    obsRule = null;
                    currentState = priorState.Pop();
                    break;

                case PropertyType.StartDateTime:
                    obsRule.StartDateTime.DeserializeParameters(parameters);
                    obsRule.StartDateTime.EncodedValue = propertyValue;
                    break;

                case PropertyType.TimeZoneOffsetFrom:
                    obsRule.OffsetFrom.DeserializeParameters(parameters);
                    obsRule.OffsetFrom.EncodedValue = propertyValue;
                    break;

                case PropertyType.TimeZoneOffsetTo:
                    obsRule.OffsetTo.DeserializeParameters(parameters);
                    obsRule.OffsetTo.EncodedValue = propertyValue;
                    break;

                case PropertyType.Comment:
                    // If this is seen more than once, just add the new stuff to the existing property
                    if(obsRule.Comment.Value != null)
                    {
                        obsRule.Comment.EncodedValue += "\r\n";
                        obsRule.Comment.EncodedValue += propertyValue;
                    }
                    else
                    {
                        obsRule.Comment.DeserializeParameters(parameters);
                        obsRule.Comment.EncodedValue = propertyValue;
                    }
                    break;

                case PropertyType.RecurrenceRule:
                    RRuleProperty rr = new RRuleProperty();
                    rr.DeserializeParameters(parameters);
                    rr.EncodedValue = propertyValue;
                    obsRule.RecurrenceRules.Add(rr);
                    break;

                case PropertyType.RecurDate:
                    // There may be more than one date in the value.  If so, split them into separate ones.  This
                    // makes it easier to manage.  They'll get written back out as individual properties but
                    // that's okay.
                    parts = propertyValue.Split(',', ';');

                    // It's important that we retain the same parameters for each one
                    parms = new string[parameters.Count];
                    parameters.CopyTo(parms, 0);

                    foreach(string s in parts)
                    {
                        sc = new StringCollection();
                        sc.AddRange(parms);

                        RDateProperty rd = new RDateProperty();
                        rd.DeserializeParameters(sc);
                        rd.EncodedValue = s;

                        obsRule.RecurDates.Add(rd);
                    }
                    break;

                case PropertyType.TimeZoneName:
                    TimeZoneNameProperty tzn = new TimeZoneNameProperty();
                    tzn.DeserializeParameters(parameters);
                    tzn.EncodedValue = propertyValue;
                    obsRule.TimeZoneNames.Add(tzn);
                    break;

                default:    // Anything else is a custom property
                    CustomProperty cust = new CustomProperty(propertyName);
                    cust.DeserializeParameters(parameters);
                    cust.EncodedValue = propertyValue;
                    obsRule.CustomProperties.Add(cust);
                    break;
            }
        }
Exemple #9
0
        /// <summary>
        /// This is implemented to handle properties related to VTimeZone items
        /// </summary>
        /// <param name="propertyName">The name of the property.</param>
        /// <param name="parameters">A string collection containing the parameters and their values.  If empty,
        /// there are no parameters.</param>
        /// <param name="propertyValue">The value of the property.</param>
        protected virtual void VTimeZoneParser(string propertyName, StringCollection parameters, string propertyValue)
        {
            int idx;

            // The last entry is always CustomProperty so scan for length minus one
            for(idx = 0; idx < ntvTimeZone.Length - 1; idx++)
                if(ntvTimeZone[idx].IsMatch(propertyName))
                    break;

            // An opening BEGIN:VTIMEZONE property must have been seen
            if(vTimeZone == null)
                throw new PDIParserException(this.LineNumber, LR.GetString("ExParseNoBeginProp", "BEGIN:VTIMEZONE",
                    propertyName));

            // Handle or create the property
            switch(ntvTimeZone[idx].EnumValue)
            {
                case PropertyType.Begin:    // Handle nested objects
                    priorState.Push(currentState);

                    // Is it a STANDARD or DAYLIGHT property?
                    if(String.Compare(propertyValue.Trim(), "STANDARD", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        obsRule = new ObservanceRule(ObservanceRuleType.Standard);
                        vTimeZone.ObservanceRules.Add(obsRule);
                        currentState = VCalendarParserState.ObservanceRule;
                    }
                    else
                        if(String.Compare(propertyValue.Trim(), "DAYLIGHT", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            obsRule = new ObservanceRule(ObservanceRuleType.Daylight);
                            vTimeZone.ObservanceRules.Add(obsRule);
                            currentState = VCalendarParserState.ObservanceRule;
                        }
                        else
                        {
                            // Unknown/custom object
                            currentState = VCalendarParserState.Custom;
                            CustomObjectParser(propertyName, parameters, propertyValue);
                        }
                    break;

                case PropertyType.End:
                    // For this, the value must be VTIMEZONE
                    if(String.Compare(propertyValue.Trim(), "VTIMEZONE", StringComparison.OrdinalIgnoreCase) != 0)
                        throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedTagValue",
                            ntvTimeZone[idx].Name, propertyValue));

                    // Unlike other objects, we do rely on the end tag to add the time zone object to the
                    // collection as they are shared amongst all instances.
                    VCalendar.TimeZones.Merge(vTimeZone);

                    vTimeZone = null;
                    currentState = priorState.Pop();
                    break;

                case PropertyType.TimeZoneId:
                    vTimeZone.TimeZoneId.EncodedValue = propertyValue;
                    break;

                case PropertyType.TimeZoneUrl:
                    vTimeZone.TimeZoneUrl.EncodedValue = propertyValue;
                    break;

                case PropertyType.LastModified:
                    vTimeZone.LastModified.DeserializeParameters(parameters);
                    vTimeZone.LastModified.EncodedValue = propertyValue;
                    break;

                default:    // Anything else is a custom property
                    CustomProperty cust = new CustomProperty(propertyName);
                    cust.DeserializeParameters(parameters);
                    cust.EncodedValue = propertyValue;
                    vTimeZone.CustomProperties.Add(cust);
                    break;
            }
        }