2008-10-07 5 views
244

Мы разрабатываем приложение C# для клиента веб-сервиса. Это будет работать на ПК с Windows XP.Конвертировать UTC/GMT по местному времени

Одним из полей, возвращаемых веб-службой, является поле DateTime. Сервер возвращает поле в формате GMT, то есть с «Z» в конце.

Однако мы обнаружили, что .NET, похоже, выполняет какое-то неявное преобразование, и время было всегда 12 часов.

Следующий пример кода разрешает это в некоторой степени тем, что разница в 12 часов прошла, но не учитывает переход на летнее время NZ.

CultureInfo ci = new CultureInfo("en-NZ"); 
string date = "Web service date".ToString("R", ci); 
DateTime convertedDate = DateTime.Parse(date);    

В соответствии с this date site:

UTC/GMT Смещение

Стандартный часовой пояс: UTC/GMT +12 часов
Переход на летнее время: +1 час
Текущее смещение часового пояса : UTC/GMT +13 часов

Как настроить дополнительный час? Можно ли это сделать программно или это какая-то настройка на ПК?

+1

`время Z` относится к UTC, а не по Гринвичу. Эти два могут отличаться на 0,9 секунды. – mc0e 2017-02-27 04:30:07

ответ

42
TimeZone.CurrentTimeZone.ToLocalTime(date); 
+8

Это работает только в том случае, если система знает, что конвертируемая дата находится в UTC. Пожалуйста, см. Мой ответ. – 2009-06-08 07:44:19

+1

Но UTC по умолчанию не так ли? Следовательно, он работает для «неопределенного», как в ответе CJ7. – NickG 2013-06-12 14:06:05

2

В ответ на предложение Дана:

Пример кода теперь выглядит следующим образом:

string date = "Web service date"..ToString("R", ci); 
DateTime convertedDate = DateTime.Parse(date);    
DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(convertedDate); 

Первоначальная дата была 20/08/08; вид был UTC.

И "convertedDate" и "дт" одинаковы:

21/08/08 10:00:26; вид был местным

+0

Пожалуйста, см. Мой ответ для объяснения этого. – 2009-06-08 07:46:35

1

У меня была проблема с тем, что он находился в наборе данных, проталкиваемом через провод (webservice к клиенту), который он автоматически изменил бы, поскольку поле DateType DataColumn было установлено на локальное. Убедитесь, что вы проверяете, что такое тип DateType, если вы нажимаете DataSets.

Если вы не хотите, чтобы это изменить, установите его Неопределенный

13

Я просто хотел бы добавить общее предостережение.

Если все, что вы делаете, получает текущее время от внутренних часов компьютера, чтобы поместить дату/время на дисплей или отчет, тогда все будет хорошо. Но если вы , то сохраняете информацию о дате/времени для последующей справки или вычисления дата/время, остерегайтесь!

Предположим, вы определили, что круизный корабль прибыл в Гонолулу 20 декабря 2007 года в 15:00 UTC. И вы хотите знать, что такое местное время.
1. Возможно, задействовано не менее трех «местных жителей». Местный может означать Гонолулу, или это может означать, где находится ваш компьютер, или это может означать местоположение, где находится ваш клиент.
2. Если вы используете встроенные функции для преобразования, это, вероятно, будет ошибкой. Это связано с тем, что переход на летнее время (возможно) на данный момент действует на ваш компьютер, но в декабре не был установлен. Но Windows этого не знает ... все, что у него есть, - это один флаг, чтобы определить, действует ли летнее время. И если он действует, то он с радостью добавит час даже до даты в декабре.
3. Переход на летнее время осуществляется по-разному (или вообще отсутствует) в различных политических подразделениях. Не думайте, что только потому, что ваша страна меняется в определенную дату, что другие страны тоже.

+5

Собственно, # 2 не совсем корректно. На самом деле существуют правила о DST в каждом часовом поясе, которые ваш компьютер будет знать, если информация была установлена ​​(и обновлена). Для многих зон эти правила фиксированы. Другие реализуют «динамический DST». Бразилия - это мое домашнее животное. Таким образом, ваш спутник может работать, если ваше местное время будет DST в декабре, при условии, что между этими моментами никакие изменения не вступают в закон. – 2011-06-16 12:04:04

+0

Даже если вы не живете в Бразилии, DST является «динамичным» в том, что политики могут изменить его в любое время (как это было сделано несколько лет назад в США). Поскольку большинство программ написано с учетом будущего использования, важно понять, что нет никакого практического, предсказуемого или даже теоретического способа узнать, какие правила DST будут действовать. Вы можете приблизиться, но сберечь себя от разочарования, отказавшись от совершенства. – DaveWalley 2014-05-14 20:45:31

4

Не забывайте, если у вас уже есть объект DateTime и не уверен, если это UTC или Local, это достаточно легко использовать методы объекта непосредственно:

DateTime convertedDate = DateTime.Parse(date); 
DateTime localDate = convertedDate.ToLocalTime(); 

Как мы регулируем за дополнительный час?

Если указанный .net не будет использовать настройки локального компьютера. Я бы прочитанный из: http://msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx

Взглядами код может выглядеть примерно так:

DaylightTime daylight = TimeZone.CurrentTimeZone.GetDaylightChanges(year); 

И как уже говорилось выше двойной проверки того, что установка часового пояса сервер включен. В сети есть статьи о том, как безопасно влиять на изменения в IIS.

+0

Система будет иметь дело с этой сложностью для вас, если вы сообщите системе о том, какая «твоя» дата (местная/нет/неуказана). – 2009-06-08 07:47:43

103

Я бы изучил использование класса System.TimeZoneInfo, если вы в .NET 3.5. См. http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx. Это должно учитывать изменения дневного света.

// Coordinated Universal Time string from 
// DateTime.Now.ToUniversalTime().ToString("u"); 
string date = "2009-02-25 16:13:00Z"; 
// Local .NET timeZone. 
DateTime localDateTime = DateTime.Parse(date); 
DateTime utcDateTime = localDateTime.ToUniversalTime(); 

// ID from: 
// "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zone" 
// See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.id.aspx 
string nzTimeZoneKey = "New Zealand Standard Time"; 
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey); 
DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone); 
+0

Если вы работаете в своем часовом поясе (en-NZ в этом случае), вам не нужно иметь дело с TimeZoneInfo. Это просто лишняя сложность. См. Мой ответ для более подробной информации. – 2009-06-08 07:45:20

+32

+1 для не предполагая, что сервер находится в Новой Зеландии – ajbeaven 2010-09-07 07:02:11

329

Для строк, таких как 2012-09-19 01:27:30.000, DateTime.Parse не может сказать, что часовой пояс дата и время являются с.

DateTime имеет Kind свойства, которое может иметь одну из трех опций зон:

  • неопределенных
  • Местного
  • Utc

ПРИМЕЧАНИЯЕсли вы желая представить дату/время, отличное от UTC или вашего местного времени e, тогда вы должны использовать DateTimeOffset.


Так что для кода в вашем вопросе:

DateTime convertedDate = DateTime.Parse(dateStr); 

var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified 

Вы говорите, что вы знаете, какой он есть, так сказать это.

DateTime convertedDate = DateTime.SpecifyKind(
    DateTime.Parse(dateStr), 
    DateTimeKind.Utc); 

var kind = convertedDate.Kind; // will equal DateTimeKind.Utc 

Теперь, когда система знает его в UTC время, вы можете просто позвонить ToLocalTime:

DateTime dt = convertedDate.ToLocalTime(); 

Это даст вам результат вы требуете.

1

Я столкнулся с этим вопросом, так как у меня возникла проблема с датами UTC, когда вы возвращаетесь через API twitter (созданное поле в статусе); Мне нужно преобразовать их в DateTime. Ни один из ответов/примеров кода в ответах на этой странице не был достаточным, чтобы я не мог заставить «String не был признан действительной ошибкой DateTime» (но это самое близкое, что я нашел, чтобы найти правильный ответ на SO)

Проводка по этой ссылке здесь, в случае, если это помогает кто-то другой - ответ мне нужен был обнаружен на этом блоге: http://www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ - в основном используют DateTime.ParseExact с форматом строки вместо DateTime.Parse

15

Я знаю, что это вопрос старше , но я столкнулся с подобной ситуацией, и я хотел поделиться тем, что нашел для будущих искателей, возможно, включая меня :).

DateTime.Parse() может быть сложным - см. here например.

Если DateTime исходит из веб-службы или другого источника с известным форматом, вы можете рассмотреть что-то вроде

DateTime.ParseExact(dateString, 
        "MM/dd/yyyy HH:mm:ss", 
        CultureInfo.InvariantCulture, 
        DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal) 

или, что еще лучше,

DateTime.TryParseExact(...) 

AssumeUniversal флаг сообщает парсеру, что дата/время уже UTC; комбинация AssumeUniversal и AdjustToUniversal говорит, что она не должна преобразовывать результат в «локальное» время, которое оно будет пытаться делать по умолчанию. (Я лично стараюсь работать исключительно с UTC на уровне бизнеса/приложения/службы), но в обход преобразования в местное время также ускоряется ситуация - на 50% и более в моих тестах, см. Ниже.)

Вот что мы делали раньше:

DateTime.Parse(dateString, new CultureInfo("en-US")) 

мы профилированные приложение и обнаружили, что DateTime.Parse представляет собой значительный процент использования процессора. (Кстати, CultureInfo конструктор был не значительный вклад в использование процессора.)

Так что я создал консольное приложение для разбора строка даты/времени 10000 раз различными способами. Итог:
Parse() 10 сек
ParseExact() (преобразование в местное) 20-45 мс
ParseExact() (не преобразовывая в местный) 10-15 мс
... и да, результаты Parse() находятся в секунд , тогда как остальные находятся в миллисекундах.

15

DateTime объекты имеют Kind из Unspecified по умолчанию, которые для целей ToLocalTime предполагается UTC.

Чтобы получить местное время в UnspecifiedDateTime объекта, поэтому просто нужно сделать это:

convertedDate.ToLocalTime(); 

Ступень изменения Kind в DateTime от Unspecified к UTC не является необходимым.Unspecified считается UTC для целей ToLocalTime: http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx

1
@TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local) 
Смежные вопросы