C# 我怎么知道夏令时刚刚过去了一个小时?
我现在不在我的代码前面,但我真的不认为我需要它来问这个问题。所以我有一个倒数计时器,每18小时一次,然后重置。计时器检查当前的日期时间。现在,根据需要调整倒计时计时器。我有一个问题试图解释夏令时,当它回到一个小时,因为;例如,2017年11月5日凌晨2点发生的这起事件可以追溯到凌晨1点,但当我执行C# 我怎么知道夏令时刚刚过去了一个小时?,c#,datetime,dst,C#,Datetime,Dst,我现在不在我的代码前面,但我真的不认为我需要它来问这个问题。所以我有一个倒数计时器,每18小时一次,然后重置。计时器检查当前的日期时间。现在,根据需要调整倒计时计时器。我有一个问题试图解释夏令时,当它回到一个小时,因为;例如,2017年11月5日凌晨2点发生的这起事件可以追溯到凌晨1点,但当我执行DateTime.IsDaylightSavingTime()时,它会告诉我,即使夏令时刚刚结束,这也是错误的。这让我的计时器又往回拨了一个小时,因为它认为夏令时在这一小时内还没有出现。我该如何解决这个
DateTime.IsDaylightSavingTime()
时,它会告诉我,即使夏令时刚刚结束,这也是错误的。这让我的计时器又往回拨了一个小时,因为它认为夏令时在这一小时内还没有出现。我该如何解决这个问题呢?我会使用DateTime.UtcNow如果你真的因为某种原因需要使用当地时间,你就不会有夏令时的问题了你应该提前计算DST的变化(在安排下一个活动之前)
TimeZoneInfo.GetAdjustmentRules()应该可以帮助您获取下一次DST调整的时间和增量
以下是获取升级调整的代码:
public static DateTime? GetNextAdjustmentDate(TimeZoneInfo timeZoneInfo)
{
var adjustments = timeZoneInfo.GetAdjustmentRules();
if (adjustments.Length == 0)
{
return null;
}
int year = DateTime.UtcNow.Year;
TimeZoneInfo.AdjustmentRule adjustment = null;
foreach (TimeZoneInfo.AdjustmentRule adjustment1 in adjustments)
{
// Determine if this adjustment rule covers year desired
if (adjustment1.DateStart.Year <= year && adjustment1.DateEnd.Year >= year)
adjustment = adjustment1;
}
if (adjustment == null)
return null;
//TimeZoneInfo.TransitionTime startTransition, endTransition;
DateTime dstStart = GetCurrentYearAdjustmentDate(adjustment.DaylightTransitionStart);
DateTime dstEnd = GetCurrentYearAdjustmentDate(adjustment.DaylightTransitionEnd);
if (dstStart >= DateTime.UtcNow.Date)
return dstStart;
if (dstEnd >= DateTime.UtcNow.Date)
return dstEnd;
return null;
}
private static DateTime GetCurrentYearAdjustmentDate(TimeZoneInfo.TransitionTime transitionTime)
{
int year = DateTime.UtcNow.Year;
if (transitionTime.IsFixedDateRule)
return new DateTime(year, transitionTime.Month, transitionTime.Day);
else
{
// For non-fixed date rules, get local calendar
System.Globalization.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);
}
}
公共静态日期时间?GetNextAdjustmentDate(TimeZoneInfo TimeZoneInfo)
{
var调整=timeZoneInfo.GetAdjustmentRules();
如果(调整数.长度==0)
{
返回null;
}
int year=DateTime.UtcNow.year;
TimeZoneInfo.AdjustmentRule adjustment=null;
foreach(时区信息调整中的规则调整1)
{
//确定此调整规则是否涵盖所需年份
如果(调整1.DateStart.Year=年)
调整=调整1;
}
如果(调整==null)
返回null;
//TimeZoneInfo.TransitionTime startTransition、endTransition;
DateTime dstStart=GetCurrentYearAdjustmentDate(adjustment.DaylightTransitionStart);
DateTime dstEnd=GetCurrentYearAdjustmentDate(adjustment.DaylightTransitionEnd);
如果(dstStart>=DateTime.UtcNow.Date)
返回启动;
如果(dstEnd>=DateTime.UtcNow.Date)
返回dstEnd;
返回null;
}
私有静态日期时间GetCurrentYearAdjustmentDate(TimeZoneInfo.TransitionTime TransitionTime)
{
int year=DateTime.UtcNow.year;
if(transitionTime.IsFixedDateRule)
返回新的日期时间(年、过渡时间、月、过渡时间、日);
其他的
{
//对于非固定日期规则,获取本地日历
System.Globalization.Calendar cal=CultureInfo.CurrentCulture.Calendar;
//获得每周第一天的过渡时间
//例如,第三周不早于当月15日开始
int startOfWeek=transitionTime.Week*7-6;
//一个月从星期几开始?
int firstDayOfWeek=(int)cal.GetDayOfWeek(新的日期时间(年,过渡时间.月,1));
//确定需要调整多少开始日期
国际过渡日;
int changeDayOfWeek=(int)transitionTime.DayOfWeek;
if(星期的第一天cal.GetDaysInMonth(年,transitionTime.Month))
过渡日-=7;
返回新的日期时间(年、过渡时间、月、过渡日);
}
}
您需要添加更多的代码来检索和应用调整增量
好的-现在,当您看到所有需要完成的艰苦工作时(然后进行维护并确保没有bug),您可能希望重新思考您的问题,以便能够使用UTC而不是检查当前时间,请倒计时。使用具有预定义间隔的计时器来减少计数器,当计数器达到零时,您就完成了。例如,设置一个18小时内秒数的变量和一个间隔为1秒的计时器。这完全避免了了解系统时间的需要,并且可以在不干扰系统的情况下随意更改。
DateTime.UtcNow
没有此问题。如果,比如说,有人认为时钟关闭了18小时,并将时间设置为其他时间,它仍然会中断。@Alejandro,我需要使用系统时间,因为我的计时器需要基于它。因此,如果我的应用程序关闭并重新打开,它可以获得当前时间,并根据倒计时需要进行调整。如果这有意义的话。@JeroenMostert我通过检查本地时间和UtcNow之间的时差来调整时区的变化。如果差异发生变化,我会调整计时器,因为我认为出现了时区。当DST发生时,它返回到小时,我的本地时间和UtcNow之间的偏移量变化为-1。这使它认为时区发生了变化,而我的计时器在我不想的时候丢失了一个小时。如果我能够检测到DST在1小时内是否为假,我可以忽略时区更改“事件”。问题是,我没有办法知道那个小时的延迟是否为DST。如果在所有计算中都一致地使用UtcNow
,则无需进行任何调整。如果你说的“每18小时”不是指“每64800秒”,那你的问题就不清楚了。(顺便说一句,UTC之所以是一个好主意,完全是因为一般来说,如果没有上下文,就无法判断您是否在一个重复的小时内。这对于存储本地时间的数据库系统也是一个问题。)