public static TimeZoneStructure FromTimeZoneInfo(TimeZoneInfo staticTimeZone)
        {
            TimeZoneInfo.AdjustmentRule[] rules = staticTimeZone.GetAdjustmentRules();
            if (rules.Length > 1)
            {
                throw new ArgumentException("Cannot create TimeZoneStructure from a time zone with multiple DST rules");
            }

            TimeZoneStructure structure = new TimeZoneStructure();

            if (rules.Length == 0)
            {
                // no daylight saving
                structure.SetBias(staticTimeZone.BaseUtcOffset, new TimeSpan());
                structure.stStandardDate = new SystemTime();
                structure.stDaylightDate = new SystemTime();
            }
            else
            {
                TimeZoneInfo.AdjustmentRule rule = rules[0];
                structure.SetBias(staticTimeZone.BaseUtcOffset, rule.DaylightDelta);
                structure.stStandardDate = AdjustmentRuleHelper.GetStandardDate(rule);
                structure.stDaylightDate = AdjustmentRuleHelper.GetDaylightDate(rule);
            }

            return(structure);
        }
Exemple #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);
        }