예제 #1
0
        /// <summary>
        /// Despite holding several adjustment rules, Outlook will only use the rule that is marked as effective.
        /// (see http://msdn.microsoft.com/en-us/library/ff960389.aspx )
        /// We should ignore all other rules to be consistent with Outlook (all versions).
        /// </summary>
        public TimeZoneInfo ToTimeZoneInfo()
        {
            TimeZoneRuleStructure effectiveTimeZoneRuleStructure = GetEffectiveTimeZoneRule();

            if (effectiveTimeZoneRuleStructure == null)
            {
                throw new InvalidPropertyException("No timezone rule has been marked as effective");
            }

            TimeZoneInfo.AdjustmentRule effectiveTimeZoneRule = effectiveTimeZoneRuleStructure.ToStaticAdjustmentRule();

            string standardDisplayName;
            string daylightDisplayName;
            string timezoneID = KeyName;

            if (KeyName == String.Empty)
            {
                // It's invalid to have an empty timezone ID, use the ID of current timezone
                timezoneID = TimeZoneInfo.Local.Id;
            }
            string displayName = RegistryTimeZoneUtils.GetDisplayName(timezoneID, out standardDisplayName, out daylightDisplayName);

            if (effectiveTimeZoneRule == null)
            {
                // no daylight savings
                return(TimeZoneInfo.CreateCustomTimeZone(timezoneID, effectiveTimeZoneRuleStructure.BaseUtcOffset, displayName, standardDisplayName));
            }
            else
            {
                TimeZoneInfo.AdjustmentRule[] adjustmentRules = new TimeZoneInfo.AdjustmentRule[] { effectiveTimeZoneRule };
                return(TimeZoneInfo.CreateCustomTimeZone(timezoneID, effectiveTimeZoneRuleStructure.BaseUtcOffset, displayName, standardDisplayName, daylightDisplayName, adjustmentRules));
            }
        }
예제 #2
0
        /// <summary>
        /// If the effective TZRule structure's lBias, lStandardBias, lDaylightBias,
        /// stStandardDate, and stDaylightDate fields are not equal to the corresponding
        /// fields in the PidLidTimeZoneStruct property,
        /// the PidLidAppointmentTimeZoneDefinitionRecur and PidLidTimeZoneStruct properties
        /// are considered inconsistent.
        /// </summary>
        public bool IsConsistent(TimeZoneStructure structure)
        {
            TimeZoneRuleStructure effectiveTimeZoneRule = null;

            foreach (TimeZoneRuleStructure timeZoneRule in TZRules)
            {
                if (timeZoneRule.IsEffectiveTimeZoneRule)
                {
                    effectiveTimeZoneRule = timeZoneRule;
                    break;
                }
            }

            if (effectiveTimeZoneRule == null)
            {
                return(false);
            }
            else
            {
                return(effectiveTimeZoneRule.lBias == structure.lBias &&
                       effectiveTimeZoneRule.lStandardBias == structure.lStandardBias &&
                       effectiveTimeZoneRule.lDaylightBias == structure.lDaylightBias &&
                       effectiveTimeZoneRule.stStandardDate == structure.stStandardDate &&
                       effectiveTimeZoneRule.stDaylightDate == structure.stDaylightDate);
            }
        }
예제 #3
0
 public TimeZoneRuleStructure GetEffectiveTimeZoneRule()
 {
     // Note: Outlook stores a first and last 'no adjustment' rules
     for (int index = 0; index < TZRules.Length; index++)
     {
         TimeZoneRuleStructure ruleStructure = TZRules[index];
         if (ruleStructure.IsEffectiveTimeZoneRule)
         {
             return(ruleStructure);
         }
     }
     return(null);
 }
예제 #4
0
        public TimeZoneDefinitionStructure(byte[] buffer)
        {
            int offset = 0;

            MajorVersion = ByteReader.ReadByte(buffer, ref offset);
            MinorVersion = ByteReader.ReadByte(buffer, ref offset);
            ushort cbHeader = LittleEndianReader.ReadUInt16(buffer, ref offset);

            Reserved = LittleEndianReader.ReadUInt16(buffer, ref offset);
            ushort cchKeyName = LittleEndianReader.ReadUInt16(buffer, ref offset);

            KeyName = ByteReader.ReadUTF16String(buffer, ref offset, cchKeyName);
            ushort cRules = LittleEndianReader.ReadUInt16(buffer, ref offset);

            TZRules = new TimeZoneRuleStructure[cRules];
            for (int index = 0; index < cRules; index++)
            {
                TZRules[index] = new TimeZoneRuleStructure(buffer, offset);
                offset        += TimeZoneRuleStructure.Length;
            }
        }
예제 #5
0
        /// Note about how Outlook selects the effective adjustment rule:
        /// For backward compatibility reasons, the effective rule is always the static timezone
        /// rule used by the OS.
        /// It's possible however that there is no dynamic rule that matches the static rule,
        /// If that's the case, Outlook will replace the dynamic rule of the current year
        /// with the static rule, which will be marked as the effective rule.
        /// <param name="effectiveRule">null if there are no daylight savings</param>
        public static TimeZoneDefinitionStructure FromTimeZoneInfo(TimeZoneInfo timezone, TimeZoneInfo.AdjustmentRule effectiveRule, int effectiveRuleYear, bool isRecurringTimeZoneRule)
        {
            TimeZoneInfo.AdjustmentRule[] adjustmentRules = timezone.GetAdjustmentRules();
            if (effectiveRule != null)
            {
                if ((effectiveRule.DaylightTransitionStart.IsFixedDateRule || effectiveRule.DaylightTransitionEnd.IsFixedDateRule) &&
                    effectiveRule.DateStart.Year < effectiveRule.DateEnd.Year)
                {
                    // a rule can either be fixed-date (wYear is not zero) or floating-date (wYear is zero)
                    // a fixed-date rule cannot span multiple years.
                    throw new NotImplementedException("Effective DST rule cannot be fixed-date and span multiple years");
                }

                if (adjustmentRules.Length == 0)
                {
                    // effective rule != null means timezone rule is defined, but the timezone has no such rule
                    throw new ArgumentException("Time zone does not match effective rule");
                }
            }

            TimeZoneRuleFlags effectiveRuleFlags = TimeZoneRuleFlags.EffectiveTimeZoneRule;

            if (isRecurringTimeZoneRule)
            {
                effectiveRuleFlags |= TimeZoneRuleFlags.RecurringTimeZoneRule;
            }

            TimeZoneRuleStructure[] tzRules;

            if (adjustmentRules.Length == 0)
            {
                // at this point effectiveRule must be null
                TimeZoneRuleStructure ruleStructure = new TimeZoneRuleStructure();
                ruleStructure.SetBias(timezone.BaseUtcOffset, new TimeSpan());
                ruleStructure.wYear       = 1601; // That's what Outlook 2007 SP3 uses
                ruleStructure.TZRuleFlags = effectiveRuleFlags;
                tzRules = new TimeZoneRuleStructure[] { ruleStructure };
            }
            else
            {
                List <TimeZoneRuleStructure> rules = new List <TimeZoneRuleStructure>();
                // First we will create a list of the dynamic rules:

                // we have an effective rule and at least one dynamic rule
                int firstRuleYear = adjustmentRules[0].DateStart.Year;
                if (firstRuleYear > 1)
                {
                    TimeZoneRuleStructure firstRule = new TimeZoneRuleStructure();
                    firstRule.SetBias(timezone.BaseUtcOffset, adjustmentRules[0].DaylightDelta);
                    firstRule.wYear = (ushort)(firstRuleYear - 1);
                    rules.Add(firstRule);
                }

                for (int index = 0; index < adjustmentRules.Length; index++)
                {
                    TimeZoneInfo.AdjustmentRule adjustmentRule = adjustmentRules[index];
                    TimeZoneRuleStructure       rule           = new TimeZoneRuleStructure();
                    rule.wYear = (ushort)adjustmentRule.DateStart.Year;;
                    rule.SetBias(timezone.BaseUtcOffset, adjustmentRule.DaylightDelta);
                    rule.stStandardDate = AdjustmentRuleHelper.GetStandardDate(adjustmentRule);
                    rule.stDaylightDate = AdjustmentRuleHelper.GetDaylightDate(adjustmentRule);

                    rules.Add(rule);
                }

                int lastRuleYear = adjustmentRules[adjustmentRules.Length - 1].DateEnd.Year;
                if (lastRuleYear < 9999)
                {
                    TimeZoneRuleStructure lastRule = new TimeZoneRuleStructure();
                    lastRule.SetBias(timezone.BaseUtcOffset, adjustmentRules[adjustmentRules.Length - 1].DaylightDelta);
                    lastRule.wYear = (ushort)(lastRuleYear + 1);
                    rules.Add(lastRule);
                }

                // Outlook will try to find a rule that match the static rule, and will use the last rule that fits

                // now we will replace a dynamic rule with the appropriate static rule

                // find the index for the rule
                int effectiveRuleIndex = 0;
                for (int index = 0; index < rules.Count; index++)
                {
                    if (effectiveRuleYear >= rules[index].wYear)
                    {
                        effectiveRuleIndex = index;
                    }
                }

                // prepare the effective rule structure
                TimeZoneRuleStructure ruleStructure = new TimeZoneRuleStructure();
                ruleStructure.wYear       = rules[effectiveRuleIndex].wYear;
                ruleStructure.TZRuleFlags = effectiveRuleFlags;

                if (effectiveRule == null)
                {
                    // We should have a no-daylight-savings rule
                    ruleStructure.SetBias(timezone.BaseUtcOffset, new TimeSpan());
                }
                else
                {
                    ruleStructure.SetBias(timezone.BaseUtcOffset, effectiveRule.DaylightDelta);
                    ruleStructure.stStandardDate = AdjustmentRuleHelper.GetStandardDate(effectiveRule);
                    ruleStructure.stDaylightDate = AdjustmentRuleHelper.GetDaylightDate(effectiveRule);
                }

                rules[effectiveRuleIndex] = ruleStructure;
                tzRules = rules.ToArray();
            }

            TimeZoneDefinitionStructure structure = new TimeZoneDefinitionStructure();

            structure.KeyName = timezone.Id;
            structure.TZRules = tzRules;
            return(structure);
        }