C# 获取下一个发生夏令时转换的日期/时间
我想在C#中编写(或使用,如果它已经退出)一个函数,该函数返回给定对象的下一个DST转换的日期/时间以及该时区中的特定“截止时间”。返回的时间应在提供的时区内。我想要的函数具有以下签名:C# 获取下一个发生夏令时转换的日期/时间,c#,datetime,dst,C#,Datetime,Dst,我想在C#中编写(或使用,如果它已经退出)一个函数,该函数返回给定对象的下一个DST转换的日期/时间以及该时区中的特定“截止时间”。返回的时间应在提供的时区内。我想要的函数具有以下签名: public DateTime GetNextTransition(DateTime asOfTime, TimeZoneInfo timeZone) { // Implement me! } 例如,如果传入“东部标准时间”TimeZoneInfo对象,则为1/21/2011@17:00作为“asOf
public DateTime GetNextTransition(DateTime asOfTime, TimeZoneInfo timeZone)
{
// Implement me!
}
例如,如果传入“东部标准时间”TimeZoneInfo对象,则为1/21/2011@17:00作为“asOfTime”,我希望此函数返回3/13/2011@2:00
该结构似乎包含了我需要的所有信息,但理想情况下,会有某种内置机制将规则转换为实际日期。有人有什么建议吗?System.TimeZoneInfo.TransitionTime看起来像是一个可以保存此类时间转换数据的结构,而不是一个计算实际值的函数。要创建这样一个函数,我会在某个地方在线查找数据,然后使用静态CreateFloatingDateRule或CreateFixedDateRule方法创建值。看看本页上的示例,我想它会得到您需要的
你好。这可能太晚了,但我将在这里发布我用于此目的的代码。这可能会确保某人有时间实施它。实际上,我是在链接is@Jamiegs-answer的帮助下完成的
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);
}
}
你可以找到我玩过的代码。DST是一种非常有趣的动物……请记住,亚利桑那州的大部分地区(一些印第安保留地尊重DST)都不尊重DST。我们的时区仍然是MST,因此我们不调整我们的时间…而说丹佛将过渡到MDT并调整他们的时间。使用野田佳彦时间,看看如何使用它获得过渡时间。谢谢——我在这里发布后不久也发现了这一点。我能够修改那里的代码来完成工作。一旦我对问题有了更多的信心,我会在我的问题中发布我的最终代码。框架没有公开浮动日期规则到实际日期的转换,这太糟糕了。@StuartLange在过去4.5年中,我一直在这里等待您发布代码。仍在使用它吗?请注意,有一个名为
TransitionTimeToDateTime
的内部方法可以执行此操作。你可以找到它。@MattJohnson one仍然需要自己构建TransitionTime
。这并不能解决OT发布的问题,我也在为…@Azizont-look inTimeZoneInfo.GetAdjustmentRules
寻找解决方案。从那里开始相当容易。但是,如果您想要一种更简单、更可靠的方法,请使用
// 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"))