public TimeZoneRuleStructure(byte[] buffer, int offset)
 {
     MajorVersion = ByteReader.ReadByte(buffer, offset + 0);
     MinorVersion = ByteReader.ReadByte(buffer, offset + 1);
     Reserved     = LittleEndianConverter.ToUInt16(buffer, offset + 2);
     TZRuleFlags  = (TimeZoneRuleFlags)LittleEndianConverter.ToUInt16(buffer, offset + 4);
     wYear        = LittleEndianConverter.ToUInt16(buffer, offset + 6);
     // 14 unused bytes
     lBias          = LittleEndianConverter.ToInt32(buffer, offset + 22);
     lStandardBias  = LittleEndianConverter.ToInt32(buffer, offset + 26);
     lDaylightBias  = LittleEndianConverter.ToInt32(buffer, offset + 30);
     stStandardDate = new SystemTime(buffer, offset + 34);
     stDaylightDate = new SystemTime(buffer, offset + 50);
 }
Esempio n. 2
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);
        }