.NET DateTime.Now возвращает неверное время при изменении часового пояса. - PullRequest
36 голосов
/ 18 ноября 2008

Эта проблема возникла при переходе на летнее время. После того, как произошли изменения, мы заметили, что наше серверное приложение начало записывать в журнал неправильное время - на час вперед, что означает, что .NET кеширует смещение часового пояса. Нам пришлось перезапустить наше приложение, чтобы решить эту проблему. Я написал простое приложение, чтобы воспроизвести эту проблему. Когда я меняю часовой пояс во время работы приложения, свойство DateTime.Now продолжает показывать время в старом часовом поясе. Кто-нибудь знает, есть ли обходной путь для этой проблемы, кроме перезапуска приложения?

Ответы [ 4 ]

46 голосов
/ 18 ноября 2008

Да, текущий часовой пояс кэшируется. По уважительной причине он позволяет избежать проблем с неработающим кодом, который использует DateTime.Now для реализации измерения прошедшего времени. Такой код имеет тенденцию страдать от сердечного приступа, когда время внезапно меняется на час или более.

Вам потребуется вызвать System.Globalization.CultureInfo.ClearCachedData () для сброса кэшированного значения. Следующий вызов DateTime.Now теперь даст новое местное время. Если вы вообще используете класс .NET 3.5 TimeZoneInfo, вам также необходимо вызвать его метод ClearCachedData (). Вы можете использовать событие SystemEvents.TimeChanged в качестве триггера.

3 голосов
/ 18 ноября 2008

Наиболее распространенная рекомендация - хранить DateTime.UtcNow и, когда вы хотите показать локализованное время пользователю, преобразовать в местное время с учетом перехода на летнее время.

.NET обеспечивает расчеты, связанные с переходом на летнее время, с классами DaylightTime и TimeZone , а метод ToLocalTime предположительно может конвертировать UTC в локальный учет для дневного света экономия времени.

1 голос
/ 22 апреля 2011

Полностью квалифицированный класс, приведенный выше, немного отключен, но, возможно, он изменился в .NET 3.5.

System.Globalization.CultureInfo.CurrentCulture.ClearCachedData()

также не забудьте включить (в C # .NET) или импортировать (с VB.NET) библиотечную ссылку System.Globalization.CultureInfo

Позвоните прямо перед использованием DateTime.Now. Хотя, вероятно, лучше всего вызывать его в событии запуска вашего файла Global.asax.

========== Также убедитесь, что вы проверяете часовой пояс на самом Windows Server или на локальном компьютере в зависимости от того, где работает веб-сервер IIS.

0 голосов
/ 26 июня 2009

В моем проекте мне нужно было сбросить ряд переменных, если время (или часовой пояс) было изменено. Чтобы я мог понять, что это событие произошло, я использовал WindowsMessageFilter.

Я использую .Net 2.0, поэтому я не мог использовать (или, может быть, я искал не в тех местах) ClearCachedData, поэтому я использовал этот подход с помощью небольшого отражения.

    Private mTZChangeFilter As WindowsMessageFilter


    mTZChangeFilter = New WindowsMessageFilter()
    AddHandler mTZChangeFilter.TimeChanged, AddressOf onTimeChanged

    Application.RemoveMessageFilter(mTZChangeFilter)


Public Class WindowsMessageFilter
    Implements IMessageFilter

    <System.Diagnostics.DebuggerStepThrough()> _
    Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
        ' Debug.Print(m.Msg.ToString)
        If m.Msg = 30 Then
            ResetTimeZone()
            RaiseEvent TimeChanged(Me)
        End If
    End Function

    Private Sub ResetTimeZone()
        Dim tz As Type = GetType(System.TimeZone)
        Dim mth As System.Reflection.MethodInfo

        Try
            mth = tz.GetMethod("ResetTimeZone", BindingFlags.NonPublic Or BindingFlags.Static)
            mth.Invoke(mth, Nothing)
        Catch ex As Exception
            Debug.Print(ex.ToString)
        End Try
    End Sub 

end class
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...