/// <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; }