C# 我怎么知道夏令时刚刚过去了一个小时?

C# 我怎么知道夏令时刚刚过去了一个小时?,c#,datetime,dst,C#,Datetime,Dst,我现在不在我的代码前面,但我真的不认为我需要它来问这个问题。所以我有一个倒数计时器,每18小时一次,然后重置。计时器检查当前的日期时间。现在,根据需要调整倒计时计时器。我有一个问题试图解释夏令时,当它回到一个小时,因为;例如,2017年11月5日凌晨2点发生的这起事件可以追溯到凌晨1点,但当我执行DateTime.IsDaylightSavingTime()时,它会告诉我,即使夏令时刚刚结束,这也是错误的。这让我的计时器又往回拨了一个小时,因为它认为夏令时在这一小时内还没有出现。我该如何解决这个

我现在不在我的代码前面,但我真的不认为我需要它来问这个问题。所以我有一个倒数计时器,每18小时一次,然后重置。计时器检查当前的日期时间。现在,根据需要调整倒计时计时器。我有一个问题试图解释夏令时,当它回到一个小时,因为;例如,2017年11月5日凌晨2点发生的这起事件可以追溯到凌晨1点,但当我执行
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之所以是一个好主意,完全是因为一般来说,如果没有上下文,就无法判断您是否在一个重复的小时内。这对于存储本地时间的数据库系统也是一个问题。)