Получить DateTime для другого часового пояса, независимо от местного часового пояса - PullRequest
43 голосов
/ 14 января 2009

Независимо от того, какой локальный часовой пояс пользователя установлен, с помощью C # (.NET 2.0) мне нужно определить время (объект DateTime) в восточном часовом поясе.

Я знаю об этих методах, но, кажется, нет очевидного способа получить объект DateTime для другого часового пояса, чем тот, в котором находится пользователь.

 DateTime.Now
 DateTime.UtcNow
 TimeZone.CurrentTimeZone

Конечно, решение должно быть ориентировано на летнее время.

Ответы [ 6 ]

85 голосов
/ 14 января 2009

В .NET 3.5 есть TimeZoneInfo, что обеспечивает большую функциональность в этой области; 2.0SP1 имеет DateTimeOffset, но это намного более ограничено.

Получение UtcNow и добавление фиксированного смещения является частью работы, но не учитывает DST.

Так что в 3.5 я думаю, что вы можете сделать что-то вроде:

DateTime eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(
    DateTime.UtcNow, "Eastern Standard Time");

Но этого просто нет в 2.0; извините.

8 голосов
/ 20 января 2009

Как уже упоминалось, .NET 2 не содержит никакой информации о часовом поясе. Информация хранится в реестре, и довольно просто написать класс-оболочку вокруг нее:

SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones

содержит подразделы для всех часовых поясов. Значение поля TZI содержит все свойства перехода и смещения для часового пояса, но все это в двоичном массиве. Наиболее важные биты (смещение и дневной свет) - это int32, хранящиеся в позициях 0 и 8 соответственно:

int bias = BitConverter.ToInt32((byte[])tzKey.GetValue("TZI"), 0);
int daylightBias = BitConverter.ToInt32((byte[])tzKey.GetValue("TZI"), 8);

Вот архив Как получить информацию о часовом поясе (DST) из реестра?

6 голосов
/ 14 января 2009

С - http://msdn.microsoft.com/en-us/library/system.timezoneinfo.converttimefromutc.aspx

Это позволяет найти часовой пояс по имени, если США когда-либо пойдут на 15 градусов западнее или восточнее лондонского меридиана.

DateTime timeUtc = DateTime.UtcNow;
try
{
   TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
   DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
   Console.WriteLine("The date and time are {0} {1}.", 
                     cstTime, 
                     cstZone.IsDaylightSavingTime(cstTime) ?
                             cstZone.DaylightName : cstZone.StandardName);
}
catch (TimeZoneNotFoundException)
{
   Console.WriteLine("The registry does not define the Central Standard Time zone.");
}                           
catch (InvalidTimeZoneException)
{
   Console.WriteLine("Registry data on the Central STandard Time zone has been corrupted.");
}
2 голосов
/ 14 января 2009

Я сэкономлю вам время и скажу, что в самой версии .net версии 2.0 нет способа получить объект DateTime для другого часового пояса, отличного от того, на котором работает программное обеспечение (кроме UTC).

Однако это не значит, что нет способа сделать это вне .net. Взгляните здесь на класс TimeZoneInformation. Этот класс переносит некоторые вещи p / invoke в Win O / S, чтобы получить информацию о часовом поясе из O / S. Я успешно использовал его, когда 2.0 был новым, и он работал очень хорошо. Сайт, над которым я работал, должен был показывать каждую дату / время локально для пользователя и должен был быть осведомлен о летнем времени, и этот класс заполнил счет для нас.

1 голос
/ 14 января 2009

Как насчет

 DateTime lclTime = DateTime.Now;
 DateTime ept = lclTime.ToUniversalTime().AddHours(
                   IsEasternDaylightSavingTime(
                       lclTime.ToUniversalTime())? -5: -4)

или, если у вас уже есть местный UTC, просто

 DateTime lclUtc = DateTime.UtcNow;
 DateTime ept = lclUtc.AddHours(
                  IsEasternDaylightSavingTime(lclUtc)? -5: -4)

Используйте статический словарь жестко закодированных значений для Spring-forward и резервных дат для восточного времени на следующие 50 лет. Это всего 300 байтов или около того ..., а затем индексируйте его, чтобы определить, будет ли летнее время включено восточное побережье ... Как уже указывалось, вам все равно, находится ли он в местной зоне или нет ...

 private static bool IsEasternDaylightSavingTime(DateTime utcDateTime)
   {
        // hard coded method to determine 
        // whether utc datetime is Eastern Standard time
        // or Eastern Daylight Time
   }
0 голосов
/ 12 декабря 2014

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

Кроме того, преобразование возможно только в том случае, если вам известны оба смещения источника и пункта назначения, а затем вычисление всегда соответствует заданному в -1 * (sourceOffset - destOffset)

Где часть в скобках представляет разницу часовых поясов.

Пожалуйста, смотрите также

Получить восточное время в c # без преобразования местного времени

...