【问题标题】:How do I know Daylight Saving Time just went off when it JUST went back an hour? [duplicate]我怎么知道夏令时刚刚过去一小时? [复制]
【发布时间】:2018-04-22 13:58:21
【问题描述】:

我现在不在我的代码面前,但我真的认为我不需要它来问这个问题。所以我有一个倒数计时器,它每 18 小时关闭一次,然后重置。计时器检查当前的DateTime.Now 并根据需要调整倒计时计时器。我在尝试将夏令时倒退一小时时遇到问题,因为;例如,2017 年 11 月 5 日凌晨 2 点的过去事件会回到凌晨 1 点,但是当我这样做时 DateTime.IsDaylightSavingTime() 它告诉我这是错误的,即使夏令时刚刚结束。这使我的计时器额外返回一个小时,因为它认为夏令时在那一小时内仍然没有发生。我该如何解决这个问题?

【问题讨论】:

  • 不检查当前时间,倒计时。使用具有预定义间隔的计时器来减少计数器,当它达到零时,您就完成了。例如,设置一个以 18 小时为单位的秒数的变量和一个以 1 秒为间隔的计时器。这完全避免了了解系统时间的需要,并且可以随意更改而不会干扰您的系统。
  • DateTime.UtcNow 没有这个问题。例如,如果有人决定时钟关闭 18 小时并将时间设置为其他时间,它仍然会中断。
  • @Alejandro,我需要使用系统时间,因为我的计时器需要基于它。因此,如果我的应用程序关闭并重新打开,它可以获取当前时间并调整倒数计时器所需的时间。如果这有意义的话。
  • @JeroenMostert 我通过检查本地时间和 UtcNow 之间的时差来调整时区变化。如果差异发生变化,我会调整计时器,因为我认为发生了时区。当 DST 发生并返回一小时时,我的本地时间和 UtcNow 之间的偏移量会更改 -1。这使它认为发生了时区更改,并且当我不希望它发生时,我的计时器会失去一个小时。如果我能够检测到 1 小时内 DST 是否为假,我可以忽略时区更改“事件”。问题是我无法知道该小时是否是夏令时。
  • 如果您在所有计算中始终使用UtcNow,则无需进行任何调整。如果“每 18 小时”的意思不是“每 64800 秒”,那么您的问题并不清楚。 (顺便说一句,UTC 是一个好主意的全部原因在于,一般来说,如果没有上下文,就不可能说出您是否处于重复的小时内。对于将本地时间存储为的数据库系统来说,这是一个问题好吧。)

标签: c# datetime dst


【解决方案1】:

如果您出于某种原因确实需要使用当地时间,那么您应该提前计算 DST 更改(在安排下一个活动之前)。

TimeZoneInfo.GetAdjustmentRules() 应该可以帮助您获得下一次 DST 调整的时间和增量。

以下是获取upcomming调整的代码:

    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);
        }
    }

您需要添加更多代码来检索和应用调整增量。

嗯 - 现在,当您看到所有需要完成的艰苦工作(而不是维护并确保没有错误)时,您可能想要重新解决您的问题以能够使用 UTC。

【讨论】:

    【解决方案2】:

    我会使用 DateTime.UtcNow 你不会遇到夏令时问题

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-17
      • 2016-12-30
      • 1970-01-01
      • 2023-03-22
      • 2023-03-26
      • 1970-01-01
      • 2012-07-08
      相关资源
      最近更新 更多