/// <summary> /// Converts this time zone definition into a TimeZoneInfo structure. /// </summary> /// <param name="service">The service.</param> /// <returns>A TimeZoneInfo representing the same time zone as this definition.</returns> internal Misc.CustomTimeZoneInfo ToTimeZoneInfo(ExchangeService service) { this.Validate(); Misc.CustomTimeZoneInfo result; // Retrieve the base offset to UTC, standard and daylight display names from // the last transition group, which is the one that currently applies given that // transitions are ordered chronologically. TimeZoneTransitionGroup.CustomTimeZoneCreateParams creationParams = this.transitions[this.transitions.Count - 1].TargetGroup.GetCustomTimeZoneCreationParams(); List <Misc.AdjustmentRule> adjustmentRules = new List <Misc.AdjustmentRule>(); DateTime startDate = DateTime.MinValue; DateTime endDate; DateTime effectiveEndDate; for (int i = 0; i < this.transitions.Count; i++) { if (i < this.transitions.Count - 1) { endDate = (this.transitions[i + 1] as AbsoluteDateTransition).DateTime; effectiveEndDate = endDate.AddDays(-1); } else { endDate = DateTime.MaxValue; effectiveEndDate = endDate; } // OM:1648848 Due to bad timezone data from clients the // startDate may not always come before the effectiveEndDate if (startDate < effectiveEndDate) { Misc.AdjustmentRule adjustmentRule = this.transitions[i].TargetGroup.CreateAdjustmentRule(startDate, effectiveEndDate); if (adjustmentRule != null) { adjustmentRules.Add(adjustmentRule); } startDate = endDate; } else { service.TraceMessage( TraceFlags.EwsTimeZones, string.Format( "The startDate '{0}' is not before the effectiveEndDate '{1}'. Will skip creating adjustment rule.", startDate, effectiveEndDate)); } } if (adjustmentRules.Count == 0) { // If there are no adjustment rule, the time zone does not support Daylight // saving time. result = Misc.CustomTimeZoneInfo.CreateCustomTimeZone( this.Id, creationParams.BaseOffsetToUtc, this.Name, creationParams.StandardDisplayName); } else { result = Misc.CustomTimeZoneInfo.CreateCustomTimeZone( this.Id, creationParams.BaseOffsetToUtc, this.Name, creationParams.StandardDisplayName, creationParams.DaylightDisplayName, adjustmentRules.ToArray()); } return(result); }
/// <summary> /// Loads from json. /// </summary> /// <param name="jsonProperty">The json property.</param> /// <param name="service">The service.</param> internal override void LoadFromJson(JsonObject jsonProperty, ExchangeService service) { base.LoadFromJson(jsonProperty, service); foreach (string key in jsonProperty.Keys) { switch (key) { case XmlAttributeNames.Name: this.name = jsonProperty.ReadAsString(key); break; case XmlAttributeNames.Id: this.id = jsonProperty.ReadAsString(key); break; case XmlElementNames.Periods: foreach (object jsonPeriod in jsonProperty.ReadAsArray(key)) { TimeZonePeriod period = new TimeZonePeriod(); period.LoadFromJson(jsonPeriod as JsonObject, service); // OM:1648848 Bad timezone data from clients can include duplicate rules // for one year, with duplicate ID. In that case, let the first one win. if (!this.periods.ContainsKey(period.Id)) { this.periods.Add(period.Id, period); } else { service.TraceMessage( TraceFlags.EwsTimeZones, string.Format( "An entry with the same key (Id) '{0}' already exists in Periods. Cannot add another one. Existing entry: [Name='{1}', Bias='{2}']. Entry to skip: [Name='{3}', Bias='{4}'].", period.Id, this.Periods[period.Id].Name, this.Periods[period.Id].Bias, period.Name, period.Bias)); } } break; case XmlElementNames.TransitionsGroups: foreach (object arrayOfTransitionsTypeInstance in jsonProperty.ReadAsArray(key)) { TimeZoneTransitionGroup transitionGroup = new TimeZoneTransitionGroup(this); transitionGroup.LoadFromJson(arrayOfTransitionsTypeInstance as JsonObject, service); this.transitionGroups.Add(transitionGroup.Id, transitionGroup); } break; case XmlElementNames.Transitions: JsonObject arrayOfTransitionsType = jsonProperty.ReadAsJsonObject(key); foreach (object uncastJsonTransition in arrayOfTransitionsType.ReadAsArray(XmlElementNames.Transition)) { JsonObject jsonTransition = uncastJsonTransition as JsonObject; TimeZoneTransition transition = TimeZoneTransition.Create(this, jsonTransition.ReadTypeString()); transition.LoadFromJson(jsonTransition, service); this.transitions.Add(transition); } break; default: break; } } // EWS can return a TimeZone definition with no Id. Generate a new Id in this case. if (string.IsNullOrEmpty(this.id)) { string nameValue = string.IsNullOrEmpty(this.Name) ? string.Empty : this.Name; this.Id = NoIdPrefix + Math.Abs(nameValue.GetHashCode()).ToString(); } this.transitions.Sort(this.CompareTransitions); }