获取夏令时转换发生的下一个日期/时间

我想在C#中编写(或使用,如果它已经退出)一个函数,它返回给定System.TimeZoneInfo对象的下一个DST转换的日期/时间以及该时区中特定的“截至”时间。 返回的时间应在提供的时区内。 我想要的function有这个签名:

public DateTime GetNextTransition(DateTime asOfTime, TimeZoneInfo timeZone) { // Implement me! } 

例如,如果我传入“东部标准时间”TimeZoneInfo对象,以及1/21/2011 @ 17:00作为“asOfTime”,我希望此函数返回2011年3月13日@ 2:00。

System.TimeZoneInfo.TransitionTime结构似乎具有我需要的所有信息,但理想情况下会有某种内置机制将规则转换为实际日期。 有人有什么建议吗?

看看这个页面上的例子,我认为它会得到你需要的东西。

MSDN – TransitionTime

你好。 可能为时已晚,但我会在此处发布我为此目的使用的代码。 这可能会安全某人的时间来实现它。 我实际上在链接的帮助下做到了@Jamiegs的答案。

  public static DateTime? GetNextTransition(DateTime asOfTime, TimeZoneInfo timeZone) { TimeZoneInfo.AdjustmentRule[] adjustments = timeZone.GetAdjustmentRules(); if (adjustments.Length == 0) { // if no adjustment then no transition date exists return null; } int year = asOfTime.Year; TimeZoneInfo.AdjustmentRule adjustment = null; foreach (TimeZoneInfo.AdjustmentRule adj in adjustments) { // Determine if this adjustment rule covers year desired if (adj.DateStart.Year <= year && adj.DateEnd.Year >= year) { adjustment = adj; break; } } if (adjustment == null) { // no adjustment found so no transition date exists in the range return null; } DateTime dtAdjustmentStart = GetAdjustmentDate(adjustment.DaylightTransitionStart, year); DateTime dtAdjustmentEnd = GetAdjustmentDate(adjustment.DaylightTransitionEnd, year); if (dtAdjustmentStart >= asOfTime) { // if adjusment start date is greater than asOfTime date then this should be the next transition date return dtAdjustmentStart; } else if (dtAdjustmentEnd >= asOfTime) { // otherwise adjustment end date should be the next transition date return dtAdjustmentEnd; } else { // then it should be the next year's DaylightTransitionStart year++; foreach (TimeZoneInfo.AdjustmentRule adj in adjustments) { // Determine if this adjustment rule covers year desired if (adj.DateStart.Year <= year && adj.DateEnd.Year >= year) { adjustment = adj; break; } } dtAdjustmentStart = GetAdjustmentDate(adjustment.DaylightTransitionStart, year); return dtAdjustmentStart; } } public static DateTime GetAdjustmentDate(TimeZoneInfo.TransitionTime transitionTime, int year) { if (transitionTime.IsFixedDateRule) { return new DateTime(year, transitionTime.Month, transitionTime.Day); } else { // For non-fixed date rules, get local calendar Calendar cal = CultureInfo.CurrentCulture.Calendar; // Get first day of week for transition // For example, the 3rd week starts no earlier than the 15th of the month int startOfWeek = transitionTime.Week * 7 - 6; // What day of the week does the month start on? int firstDayOfWeek = (int)cal.GetDayOfWeek(new DateTime(year, transitionTime.Month, 1)); // Determine how much start date has to be adjusted int transitionDay; int changeDayOfWeek = (int)transitionTime.DayOfWeek; if (firstDayOfWeek <= changeDayOfWeek) transitionDay = startOfWeek + (changeDayOfWeek - firstDayOfWeek); else transitionDay = startOfWeek + (7 - firstDayOfWeek + changeDayOfWeek); // Adjust for months with no fifth week if (transitionDay > cal.GetDaysInMonth(year, transitionTime.Month)) transitionDay -= 7; return new DateTime(year, transitionTime.Month, transitionDay, transitionTime.TimeOfDay.Hour, transitionTime.TimeOfDay.Minute, transitionTime.TimeOfDay.Second); } } 

示例用法如下所示:

 // This should give you DateTime object for date 26 March 2017 // because this date is first transition date after 1 January 2017 for Central Europe Standard Time zone DateTime nextTransitionDate = GetNextTransition(new DateTime(2017, 1, 1), TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time")) 

你可以在这里找到我玩过的代码。

System.TimeZoneInfo.TransitionTime看起来像一个可以保存这种时间转换数据的结构,而不是一个能够计算出实际值的函数。 要创建这样的函数,我会在某处找到数据,然后使用静态CreateFloatingDateRule或CreateFixedDateRule方法创建值。