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