/// <summary> /// Returns a string that represents the specified <see cref="DateTime"/> with the specified format. /// </summary> /// <param name="format">String that represents the date and time format.</param> /// <param name="datetime">A date and time.</param> /// <returns>A string that represents the <see cref="DateTime"/> in the specified format.</returns> public string ToString(string format, DateTime datetime) { if (format == null) { throw new ArgumentNullException(nameof(format)); } if (datetime == null) { throw new ArgumentNullException(nameof(datetime)); } if (datetime.Kind == DateTimeKind.Unspecified) { return(datetime.ToString(format, CultureInfo.CurrentCulture)); } if (format == "o" || format == "O") { format = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffK"; } else if (format == "u") { format = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'"; } else if (format == "U" && datetime.Kind == DateTimeKind.Local) { datetime = ToUniversalTime(datetime); } if (format.Contains("K") || format.Contains("zzz") || format.Contains("#F")) { ZoneRuleAssociate zr = GetZoneRule(datetime); Debug.Assert(zr.zoneRule != null); TimeSpan eps = zr.zoneRule.GmtOffset + zr.standardOffset; string epss = string.Format(CultureInfo.InvariantCulture, "{0:00}:{1:00}", eps.Hours, eps.Minutes); if (eps >= TimeSpan.Zero) { epss = "+" + epss; } string result = format.Replace("#F", string.Format(CultureInfo.InvariantCulture, zr.zoneRule.Format.Replace("%s", "{0}"), (zr.Letter == "-") ? "" : zr.Letter)); if (datetime.Kind == DateTimeKind.Utc) { result = result.Replace("K", "Z").Replace("zzz", "Z"); } else { result = result.Replace("K", epss).Replace("zzz", epss); } return(datetime.ToString(result, CultureInfo.CurrentCulture)); } return(datetime.ToString(format, CultureInfo.CurrentCulture)); }
/// <summary> /// Obtient la description de zone correspondant à la date spécifiée /// </summary> /// <param name="point"><see cref="DateTime"/> spécifié.</param> /// <returns><see cref="ZoneRuleAssociate"/> contenant le <see cref="DateTime"/> spécifié</returns> private ZoneRuleAssociate GetZoneRule(DateTime point) { if (point.Kind == DateTimeKind.Unspecified) { throw new ArgumentException("Unspecified date time kind", nameof(point)); } ZoneRuleAssociate za = new ZoneRuleAssociate(); za.standardOffset = TimeSpan.Zero; TimeSpan stdoff = TimeSpan.Zero; bool utc = (point.Kind == DateTimeKind.Utc); // Traduction de la date en règle TzTimeZoneRuleUntil rulePoint = new TzTimeZoneRuleUntil(); rulePoint.Year = point.Year; rulePoint.At = point.TimeOfDay; rulePoint.AtKind = (utc) ? TimeKind.UniversalTime : TimeKind.LocalWallTime; rulePoint.Month = point.Month; rulePoint.Day = new DayOfRule(DayWorkKind.Dom, point.DayOfWeek, point.Day); for (int index = ZoneRules.Count - 1; index >= 0; index--) { TzTimeZoneRule temp = ZoneRules[index]; DateTime startTime = (utc) ? temp.StartZone.UtcDate : temp.StartZone.ToLocalTime(); DateTime endTime = (utc) ? temp.EndZone.UtcDate : temp.EndZone.ToLocalTime(); stdoff = temp.StartZone.StandardOffset; if (point >= startTime && point < endTime) { if (!TzTimeInfo.Rules.ContainsKey(temp.RuleName)) { // Max time za.zoneRule = temp; za.standardOffset = temp.FixedStandardOffset; break; } else { // Trouver la dernière règle applicable au point Rule lastRule = GetLastStandardOffset(TzTimeInfo.Rules[temp.RuleName], rulePoint, temp.StartZone, temp.GmtOffset, RuleSearchKind.LessThanOrEqual); za.zoneRule = temp; za.standardOffset = (lastRule == null) ? stdoff : lastRule.StandardOffset; za.Letter = (lastRule == null) ? string.Empty : lastRule.Letter; break; } } } return(za); }
/// <summary> /// Returns the Coordinated Universal Time (UTC) that corresponds to a specified time. /// </summary> /// <param name="datetime">A date and time.</param> /// <param name="optimize">Value which indicates whether to optimize the convert</param> /// <returns>A <see cref="DateTime"/> object whose value is the Coordinated Universal Time (UTC) that corresponds to time.</returns> public DateTime ToUniversalTime(DateTime datetime, bool optimize = false) { if (datetime.Kind == DateTimeKind.Unspecified) { throw new ArgumentException("Unspecified date time kind", nameof(datetime)); } if (datetime.Kind == DateTimeKind.Utc) { return(datetime); } // Check that local date is cover by zone if (!ZoneRules.Any(z => datetime >= z.StartZone.ToLocalTime() && datetime < z.EndZone.ToLocalTime())) { throw new ArgumentOutOfRangeException(nameof(datetime)); } if (optimize) { UpdateDateChange(datetime.Year); List <TzTimeZoneRuleDate> knownDate = _zoneDates[datetime.Year]; if (knownDate.Any()) { foreach (var elt in knownDate) { if ((datetime.Kind == DateTimeKind.Utc && datetime < elt.UtcDate) || (datetime.Kind == DateTimeKind.Local && datetime < elt.ToLocalTime())) { return(TzUtilities.GetDateTime(datetime, elt.GmtOffset, elt.StandardOffset, DateTimeKind.Utc)); } } } } ZoneRuleAssociate zr = GetZoneRule(datetime); Debug.Assert(zr.zoneRule != null); TimeSpan gmtOffset = zr.zoneRule.GmtOffset; DateTime utcclock = datetime.Add(-gmtOffset - zr.standardOffset); return(new DateTime(utcclock.Ticks, DateTimeKind.Utc)); }
/// <summary> /// Returns the local time that corresponds to a specified date and time value. /// </summary> /// <param name="datetime">A date and time.</param> /// <param name="optimize">Value which indicates whether optimize the convert</param> /// <returns>A <see cref="System.DateTime"/> object whose value is the local time that corresponds to time.</returns> public DateTime ToLocalTime(DateTime datetime, bool optimize = false) { if (datetime.Kind == DateTimeKind.Unspecified) { throw new ArgumentException("Unspecified date time kind", nameof(datetime)); } if (datetime.Kind == DateTimeKind.Local) { return(datetime); } if (optimize) { UpdateDateChange(datetime.Year); List <TzTimeZoneRuleDate> knownDate = _zoneDates[datetime.Year]; if (knownDate.Any()) { foreach (var elt in knownDate) { if ((datetime < elt.UtcDate && datetime.Kind == DateTimeKind.Utc) || (datetime < elt.ToLocalTime() && datetime.Kind == DateTimeKind.Local)) { return(TzUtilities.GetDateTime(datetime, elt.GmtOffset, elt.StandardOffset, DateTimeKind.Local)); } } } } ZoneRuleAssociate zr = GetZoneRule(datetime); Debug.Assert(zr.zoneRule != null); TimeSpan gmtOffset = zr.zoneRule.GmtOffset; DateTime wallclock = datetime.Add(gmtOffset + zr.standardOffset); return(new DateTime(wallclock.Ticks, DateTimeKind.Local)); }
/// <summary> /// Obtient la description de zone correspondant à la date spécifiée /// </summary> /// <param name="point"><see cref="DateTime"/> spécifié.</param> /// <returns><see cref="ZoneRuleAssociate"/> contenant le <see cref="DateTime"/> spécifié</returns> private ZoneRuleAssociate GetZoneRule(DateTime point) { if (point.Kind == DateTimeKind.Unspecified) throw new ArgumentException("Unspecified date time kind", "point"); ZoneRuleAssociate za = new ZoneRuleAssociate(); za.standardOffset = TimeSpan.Zero; TimeSpan gmtoff = TimeSpan.Zero; TimeSpan stdoff = TimeSpan.Zero; bool utc = (point.Kind == DateTimeKind.Utc); // Traduction de la date en règle TzTimeZoneRuleUntil rulePoint = new TzTimeZoneRuleUntil(); rulePoint.Year = point.Year; rulePoint.At = point.TimeOfDay; rulePoint.AtKind = (utc) ? TimeKind.UniversalTime : TimeKind.LocalWallTime; rulePoint.Month = point.Month; rulePoint.Day = new DayOfRule(DayWorkKind.Dom, point.DayOfWeek, point.Day); for (int index = ZoneRules.Count-1; index >= 0; index--) { TzTimeZoneRule temp = ZoneRules[index]; gmtoff = temp.GmtOffset; DateTime startTime = (utc) ? temp.StartZone.UtcDate : temp.StartZone.ToLocalTime(); DateTime endTime = (utc) ? temp.EndZone.UtcDate : temp.EndZone.ToLocalTime(); stdoff = temp.StartZone.StandardOffset; if (point >= startTime && point < endTime) { if (!TzTimeInfo.Rules.ContainsKey(temp.RuleName)) { // Max time za.zoneRule = temp; za.standardOffset = temp.FixedStandardOffset; break; } else { // Trouver la dernière règle applicable au point Rule lastRule = GetLastStandardOffset(TzTimeInfo.Rules[temp.RuleName], rulePoint, temp.StartZone, temp.GmtOffset); za.zoneRule = temp; za.standardOffset = (lastRule == null) ? stdoff : lastRule.StandardOffset; za.Letter = (lastRule == null) ? string.Empty : lastRule.Letter; break; } } } return za; }