/// <summary>
        /// Generates a TimeChangeType object from it's XML representation
        /// </summary>
        /// <param name="reader">XmlReader posistioned at the start node
        /// of the TimeChangeType XML
        /// </param>
        public void ReadXml(System.Xml.XmlReader reader)
        {
            // Store the LocalName of the element we are currently at.
            // This should be either "Standard" or "Daylight".
            //
            // This also serves as our key to our position in the stream.
            // Once we reach an EndElement with this name, then we are done
            // with our portion of the XmlStream
            //
            string ruleSetName = reader.LocalName;

            // Value that indicates if the TimeChangePattern for us is a
            // RelativeYearlyRecurrence or not.  If not, then it must
            // be an AbsoluteDate
            //
            bool isRelativeYearlyPattern = false;
            RelativeYearlyRecurrencePatternType relativeYearlyPattern =
                new RelativeYearlyRecurrencePatternType();
            while (true)
            {
                // Check to see if we are done processing
                if ((reader.NodeType == XmlNodeType.EndElement) &&
                    (0 == String.Compare(reader.LocalName, ruleSetName)))
                {
                    // We are done, consume this EndElement and stop processing
                    reader.Read();
                    break;
                }

                if (reader.NodeType == XmlNodeType.EndElement)
                {
                    // This means we are at the closing tag of
                    // </RelativeYearlyRecurrence>
                    // No data here to process.
                    reader.Read();
                    continue;
                }

                // Consume TimeZoneName attribute
                //  e.g. <Standard|Daylight TimeZoneName="value">
                //
                if ((0 == String.Compare(reader.LocalName, "Standard")) ||
                    (0 == String.Compare(reader.LocalName, "Daylight")))
                {
                    if (reader.AttributeCount > 0)
                    {
                        reader.MoveToAttribute("TimeZoneName");
                        this.timeZoneNameField = reader.Value;
                    }
                    // We have consumed what we needed form this element
                    reader.Read();
                }

                // Consume Offset
                //  e.g <Offset>PT0M</Offset>
                if (0 == String.Compare(reader.LocalName, "Offset"))
                {
                    string value = reader.ReadElementContentAsString();
                    this.offsetField = value;
                }

                // Consume Time
                //  e.g. <Time>02:00:00</Time>
                if (0 == String.Compare(reader.LocalName, "Time"))
                {
                    this.timeField = reader.ReadElementContentAsDateTime();
                }

                // Consume the TimeChangePattern element if it is
                // an AbsoluteDate
                //
                if (0 == String.Compare(reader.LocalName, "AbsoluteDate"))
                {
                    isRelativeYearlyPattern = false;
                    this.itemField = reader.ReadElementContentAsDateTime();
                }

                // Consume the TimeChangePattern element if it is
                // an RelativeYearlyRecurrence
                //
                if (0 == String.Compare(reader.LocalName,
                    "RelativeYearlyRecurrence"))
                {
                    isRelativeYearlyPattern = true;
                    reader.Read();
                }

                // If the pattern is relative, then the next three checks
                // will get the DayOfWeek, DayOfWeekIndex, and Month values
                // accordingly.
                //
                if (0 == String.Compare(reader.LocalName, "DaysOfWeek"))
                {
                    string value = reader.ReadElementContentAsString();
                    relativeYearlyPattern.DaysOfWeek = value;
                }

                if (0 == String.Compare(reader.LocalName, "DayOfWeekIndex"))
                {
                    string value = reader.ReadElementContentAsString();
                    relativeYearlyPattern.DayOfWeekIndex =
                       (DayOfWeekIndexType)Enum.Parse(
                           typeof(DayOfWeekIndexType), value);
                }

                if (0 == String.Compare(reader.LocalName, "Month"))
                {
                    string value = reader.ReadElementContentAsString();
                    relativeYearlyPattern.Month =
                        (MonthNamesType)Enum.Parse(
                            typeof(MonthNamesType), value);
                }
            }

            // Before we leave, set the .itemField to our
            // relativeYearlyPattern if necessary
            if (isRelativeYearlyPattern)
                this.itemField = relativeYearlyPattern;
        }
        /// <summary>
        /// Creates a new TimeChangeInfoConverter object from the supplied byte 
        /// array and offset.  Sets the "isValidTZChangeInfo" flag to false if the 
        /// supplied bytes indicate that no time change is necessary for this 
        /// TimeZone (e.g. TimeZone does not support Daylight Savings Time.)
        /// </summary>
        /// <param name="dateTimeByteArray">
        /// Byte array from the reg value "TZI"</param>
        /// <param name="offsetIntoArray">Offset into the array where 
        /// Standard/Daylight time change information begins.</param>
        /// stored in 0 - 3 of the TZI registery byte array.</param>
        internal TimeChangeInfoConverter(
            Byte[] dateTimeByteArray,
            int offsetIntoArray)
        {
            // Bits 0 and 1 are the year bits - irrelivant to us
            // Bits 2 and 3 are the month bits
            monthVal = System.BitConverter.ToInt16(
                dateTimeByteArray,
                2 + offsetIntoArray);

            // According to the TIME_ZONE_INFORMATION documentation, if the month
            // is set to zero that means the zone doesn't ahdere to
            // Daylight Savings Time.
            //  http://msdn2.microsoft.com/en-us/library/ms725481.aspx
            //
            if (monthVal == 0) { this.isValidTZChangeInfo = false; return; }

            // We have a time zone that can be described in a Relative Yearly
            // Recurrence Pattern, begin to build that now
            //
            this.tzYearlyPatternDesc = new RelativeYearlyRecurrencePatternType();

            // The Month bit that we get is 1-based, however the MonthNamesType
            // enum is zero based
            //
            this.tzYearlyPatternDesc.Month = (MonthNamesType)(monthVal - 1);

            // Bits 4 and 5 are the day of the week indicator
            //  (0 = Sunday, 6 = Saturday)
            //
            this.dayOfWeekVal = System.BitConverter.ToInt16(
                dateTimeByteArray,
                4 + offsetIntoArray);
            this.dayOfWeek = ((DayOfWeekType)dayOfWeekVal).ToString();
            this.tzYearlyPatternDesc.DaysOfWeek = this.dayOfWeek;

            // Bits 6 and 7 represent typically represent the day, however, in
            // this case they represent the weekly index of the month (1 = First,
            // 2 = Second, ... 5 = Last), note DayOfWeekIndexType
            // is zero-based however.
            //
            this.dayOfWeekIndexVal = System.BitConverter.ToInt16(
                dateTimeByteArray,
                6 + offsetIntoArray);
            this.tzYearlyPatternDesc.DayOfWeekIndex =
                (DayOfWeekIndexType)(dayOfWeekIndexVal - 1);

            // Bits 8-9, 10-11, 12-13, and 14-15 represent the hour, minute,
            // second, and millesecond values of when the time change should occur
            //
            Int16 hourVal = System.BitConverter.ToInt16(
                dateTimeByteArray,
                8 + offsetIntoArray);
            Int16 minVal = System.BitConverter.ToInt16(
                dateTimeByteArray,
                10 + offsetIntoArray);
            Int16 secVal = System.BitConverter.ToInt16(
                dateTimeByteArray,
                12 + offsetIntoArray);

            // Although only a time element is needed for the EWS proxy, the type
            // still requires us to use a fully qualified DateTime object,
            // therefore, what we will do here is create one that represents the
            // time specified for today's date.  The EWS proxy code will take care
            // of only using the Time portion of the string
            //
            // Note: This method will require an IXmlSerializable interface
            // be defined on the TimeChangeType in order to ensure that
            // the .Time property values be serialized properly.  The code
            // for this interface can be found in Chapter 9 of
            //  "Inside Microsoft Exchange Server 2007 Web Services."
            //
            //
            this.time = new DateTime(
                DateTime.UtcNow.Year,
                DateTime.UtcNow.Month,
                DateTime.UtcNow.Day,
                hourVal,
                minVal,
                secVal,
                DateTimeKind.Unspecified);

            this.isValidTZChangeInfo = true;
        }