Преобразование UTC DateTime в локальное DateTime в С#

Я хочу показать дату и время события, которое будет управляться в соответствии с часовым поясом пользователя. Чтобы проверить часовой пояс, я меняю системный часовой пояс на другой часовой пояс, но мой код все еще получает местный часовой пояс. Вот мой код

Я использую базу данных Cassendra и С# .NET MVC.

DateTime startTimeFormate = x.Startdate;
DateTime endTimeFormate = x.Enddate;
TimeZone zone = TimeZone.CurrentTimeZone;
DateTime startTime = zone.ToLocalTime(startTimeFormate);
DateTime endTime = zone.ToLocalTime(endTimeFormate);

🤔 А знаете ли вы, что...
C# также используется для разработки игр с помощью Unity3D, популярного игрового движка.


4
11 756
4

Ответы:

Согласно Документация MSDN по свойству TimeZone.CurrentTimeZone местный часовой пояс кэшируется после первого вызова TimeZone.CurrentTimeZone. На практике это означает, что ваш код должен работать нормально, если динамические обновления часового пояса в середине выполнения не должны поддерживаться. Чтобы сразу увидеть изменения, перед вызовом TimeZone.CurrentTimeZone необходимо вызвать

TimeZoneInfo.ClearCachedData();

Это задокументировано в статье MSDN следующим образом:

Notes to Callers

Local time zone data is cached after CurrentTimeZone is first used to retrieve time zone information. If the system's local time zone subsequently changes, the CurrentTimeZone property does not reflect this change. If you need to handle time zone changes while your application is running, use the TimeZoneInfo class and call its ClearCachedData() method.


Чтобы преобразовать UTC DateTime в ваш Local DateTime, вы должны использовать TimeZoneInfo следующим образом:

DateTime startTimeFormate = x.Startdate; // This  is utc date time
TimeZoneInfo systemTimeZone = TimeZoneInfo.Local;
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(startTimeFormate, systemTimeZone);

Кроме того, если вы хотите преобразовать UTC DateTime в пользовательский Local DateTime, сделайте следующее:

string userTimeZoneId = "New Zealand Standard Time";
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(userTimeZoneId);
DateTime userLocalDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, userTimeZoneId);

Примечание. TimeZone в .NET теперь называется устаревший, и он устарел. Вместо этого используйте TimeZoneInfo.


Это помощники DateTime, которые я использую, и они охватывают все случаи, которые мне нужны до сих пор.

public static class DateTimeHelpers
  {
    public static DateTime ConvertToUTC(DateTime dateTimeToConvert, string sourceZoneIdentifier)
    {
      TimeZoneInfo sourceTZ = TimeZoneInfo.FindSystemTimeZoneById(sourceZoneIdentifier);
      TimeZoneInfo destinationTZ = TimeZoneInfo.FindSystemTimeZoneById("UTC");

      return TimeZoneInfo.ConvertTime(dateTimeToConvert, sourceTZ, destinationTZ);
    }

    public static DateTime ConvertToTimezone(DateTime utcDateTime, string destinationZoneIdentifier)
    {
      TimeZoneInfo sourceTZ = TimeZoneInfo.FindSystemTimeZoneById("UTC");
      TimeZoneInfo destinazionTZ = TimeZoneInfo.FindSystemTimeZoneById(destinationZoneIdentifier);

      return DateTime.SpecifyKind(TimeZoneInfo.ConvertTime(utcDateTime, sourceTZ, destinazionTZ), DateTimeKind.Local);
    }

    public static DateTime GetCurrentDateTimeInZone(string destinationZoneIdentifier)
    {
      TimeZoneInfo sourceTZ = TimeZoneInfo.FindSystemTimeZoneById("UTC");
      TimeZoneInfo destinazionTZ = TimeZoneInfo.FindSystemTimeZoneById(destinationZoneIdentifier);

      return DateTime.SpecifyKind(TimeZoneInfo.ConvertTime(DateTime.UtcNow, sourceTZ, destinazionTZ), DateTimeKind.Local);
    }
  }

TimeZone.CurrentTimeZone, TimeZoneInfo.Local и ToLocalTime используют локальный часовой пояс сервер, а не конечного пользователя.

Вместо этого сначала см. как надежно получить часовой пояс конечных пользователей в вашем коде .NET.

Затем, предполагая, что теперь у вас есть объект TimeZoneInfo, просто используйте метод TimeZoneInfo.ConvertTimeFromUtc.