/// <summary>
        /// Initializes a new instance of the <see cref="LegacyAvailabilityTimeZone"/> class.
        /// </summary>
        /// <param name="timeZoneInfo">The time zone used to initialize this instance.</param>
        internal LegacyAvailabilityTimeZone(TimeZoneInfo timeZoneInfo)
            : this()
        {
            // Availability uses the opposite sign for the bias, e.g. if TimeZoneInfo.BaseUtcOffset = 480 than
            // SerializedTimeZone.Bias must be -480.
            this.bias = -timeZoneInfo.BaseUtcOffset;

            // To convert TimeZoneInfo into SerializableTimeZone, we need two time changes: one to Standard
            // time, the other to Daylight time. TimeZoneInfo holds a list of adjustment rules that represent
            // the different rules that govern time changes over the years. We need to grab one of those rules
            // to initialize this instance.
            AdjustmentRule[] adjustmentRules = timeZoneInfo.GetAdjustmentRulesEx();

            if (adjustmentRules.Length == 0)
            {
                // If there are no adjustment rules (which is the case for UTC), we have to come up with two
                // dummy time changes which both have a delta of zero and happen at two hard coded dates. This
                // simulates a time zone in which there are no time changes.
                this.daylightTime              = new LegacyAvailabilityTimeZoneTime();
                this.daylightTime.Delta        = TimeSpan.Zero;
                this.daylightTime.DayOrder     = 1;
                this.daylightTime.DayOfTheWeek = DayOfTheWeek.Sunday;
                this.daylightTime.Month        = 10;
                this.daylightTime.TimeOfDay    = TimeSpan.FromHours(2);
                this.daylightTime.Year         = 0;

                this.standardTime              = new LegacyAvailabilityTimeZoneTime();
                this.standardTime.Delta        = TimeSpan.Zero;
                this.standardTime.DayOrder     = 1;
                this.standardTime.DayOfTheWeek = DayOfTheWeek.Sunday;
                this.standardTime.Month        = 3;
                this.standardTime.TimeOfDay    = TimeSpan.FromHours(2);
                this.daylightTime.Year         = 0;
            }
            else
            {
                // When there is at least one adjustment rule, we need to grab the last one which is the
                // one that currently applies (TimeZoneInfo stores adjustment rules sorted from oldest to
                // most recent).
                AdjustmentRule currentRule = adjustmentRules[adjustmentRules.Length - 1];

                this.standardTime = new LegacyAvailabilityTimeZoneTime(currentRule.DaylightTransitionEnd, TimeSpan.Zero);

                // Again, TimeZoneInfo and SerializableTime use opposite signs for bias.
                this.daylightTime = new LegacyAvailabilityTimeZoneTime(currentRule.DaylightTransitionStart, -currentRule.DaylightDelta);
            }
        }
예제 #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TimeZoneDefinition"/> class.
        /// </summary>
        /// <param name="timeZoneInfo">The time zone info used to initialize this definition.</param>
        internal TimeZoneDefinition(TimeZoneInfo timeZoneInfo)
            : this()
        {
            this.Id   = timeZoneInfo.Id;
            this.Name = timeZoneInfo.DisplayName;

            // TimeZoneInfo only supports one standard period, which bias is the time zone's base
            // offset to UTC.
            TimeZonePeriod standardPeriod = new TimeZonePeriod();

            standardPeriod.Id   = TimeZonePeriod.StandardPeriodId;
            standardPeriod.Name = TimeZonePeriod.StandardPeriodName;
            standardPeriod.Bias = -timeZoneInfo.BaseUtcOffset;

            AdjustmentRule[] adjustmentRules = timeZoneInfo.GetAdjustmentRulesEx();

            TimeZoneTransition transitionToStandardPeriod = new TimeZoneTransition(this, standardPeriod);

            if (adjustmentRules.Length == 0)
            {
                this.periods.Add(standardPeriod.Id, standardPeriod);

                // If the time zone info doesn't support Daylight Saving Time, we just need to
                // create one transition to one group with one transition to the standard period.
                TimeZoneTransitionGroup transitionGroup = new TimeZoneTransitionGroup(this, "0");
                transitionGroup.Transitions.Add(transitionToStandardPeriod);

                this.transitionGroups.Add(transitionGroup.Id, transitionGroup);

                TimeZoneTransition initialTransition = new TimeZoneTransition(this, transitionGroup);

                this.transitions.Add(initialTransition);
            }
            else
            {
                for (int i = 0; i < adjustmentRules.Length; i++)
                {
                    TimeZoneTransitionGroup transitionGroup = new TimeZoneTransitionGroup(this, this.transitionGroups.Count.ToString());
                    transitionGroup.InitializeFromAdjustmentRule(adjustmentRules[i], standardPeriod);

                    this.transitionGroups.Add(transitionGroup.Id, transitionGroup);

                    TimeZoneTransition transition;

                    if (i == 0)
                    {
                        // If the first adjustment rule's start date in not undefined (DateTime.MinValue)
                        // we need to add a dummy group with a single, simple transition to the Standard
                        // period and a group containing the transitions mapping to the adjustment rule.
                        if (adjustmentRules[i].DateStart > DateTime.MinValue.Date)
                        {
                            TimeZoneTransition transitionToDummyGroup = new TimeZoneTransition(
                                this,
                                this.CreateTransitionGroupToPeriod(standardPeriod));

                            this.transitions.Add(transitionToDummyGroup);

                            AbsoluteDateTransition absoluteDateTransition = new AbsoluteDateTransition(this, transitionGroup);
                            absoluteDateTransition.DateTime = adjustmentRules[i].DateStart;

                            transition = absoluteDateTransition;
                            this.periods.Add(standardPeriod.Id, standardPeriod);
                        }
                        else
                        {
                            transition = new TimeZoneTransition(this, transitionGroup);
                        }
                    }
                    else
                    {
                        AbsoluteDateTransition absoluteDateTransition = new AbsoluteDateTransition(this, transitionGroup);
                        absoluteDateTransition.DateTime = adjustmentRules[i].DateStart;

                        transition = absoluteDateTransition;
                    }

                    this.transitions.Add(transition);
                }

                // If the last adjustment rule's end date is not undefined (DateTime.MaxValue),
                // we need to create another absolute date transition that occurs the date after
                // the last rule's end date. We target this additional transition to a group that
                // contains a single simple transition to the Standard period.
                DateTime lastAdjustmentRuleEndDate = adjustmentRules[adjustmentRules.Length - 1].DateEnd;

                if (lastAdjustmentRuleEndDate < DateTime.MaxValue.Date)
                {
                    AbsoluteDateTransition transitionToDummyGroup = new AbsoluteDateTransition(
                        this,
                        this.CreateTransitionGroupToPeriod(standardPeriod));
                    transitionToDummyGroup.DateTime = lastAdjustmentRuleEndDate.AddDays(1);

                    this.transitions.Add(transitionToDummyGroup);
                }
            }
        }