2013-08-26 3 views
3

Я пытаюсь проанализировать форматированную дату и время в формате ISO8601 с помощью структуры DateTime .NET.Анализ даты и времени ISO8601 с помощью функции DateTime struct

Для того, чтобы дать полное представление о проблеме, я собираюсь выполнить тесты с использованием как .NET, так и JavaScript. Я сейчас в Британии (British Summer Time, UTC + 01: 00).

Мое понимание ISO8601 является то, что:

  • Когда строка с суффиксом "Z", время выражается в UTC.
  • Когда строка помечена символом «+/- hh: mm», время выражается в Местное время, когда «+/- hh: mm» выражает смещение от UTC.

Рассмотрим следующий ISO8601 формат даты/времени строки:

"1987-01-05T08:45:30.500+0100" 

Учитывая мои пунктов выше, эта строка выражает локальное время «08:45:30», а время UTC из "7:45:30"

Текущий TimeZone Test (.NET)

DateTime now = DateTime.Now; 
Console.WriteLine(now.ToLocalTime()); // 27/08/2013 12:02:43 
Console.WriteLine(now.ToUniversalTime()); // 27/08/2013 11:02:43 

Текущий TimeZone Test (JavaScript)

var now = new Date(Date.now()); 
now.toString(); // Tue Aug 27 2013 12:03:46 GMT+0100 (GMT Daylight Time) 
now.toUTCString(); // Tue, 27 Aug 2013 11:03:46 GMT 

Помимо несовершеннолетнего (минуты/секунды) различия между этими двумя примерами, они возвращаются именно то, что я ожидал бы для британского летнего времени (UTC + 01: 00). Минуты/секунды отличаются тем, что я не могу одновременно запускать тест .NET и JavaScript-тест ТОЧНО в то же время.

Так что теперь позволяет использовать мой ISO8601 дату/время отформатированную строку:

Синтаксический ISO8601 Format String (.NET)

DateTime dt = DateTime.Parse("1987-01-05T08:45:30.500+0100"); 
Console.WriteLine(dt.ToLocalTime()); // 05/01/1987 07:45:30 
Console.WriteLine(dt.ToUniversalTime()); // 05/01/1987 07:45:30 

Синтаксический ISO8601 Format String (JavaScript)

var dt = new Date("1987-01-05T08:45:30.500+0100"); 
dt.toString(); // Mon Jan 05 1987 07:45:30 GMT+0000 (GMT Standard Time) 
dt.toUTCString(); //Mon, 05 Jan 1987 07:45:30 GMT 

Это не похоже на пример, который показывает дату/время «сейчас». Почему это отображается, как будто я нахожусь в британском зимнем времени (UTC + 00: 00), когда примеры «сейчас» отображаются в британском летнем времени (UTC + 01: 00)?

Если я изменю настройки своего часового пояса, я получаю ожидаемые результаты для локального/универсального времени, но если они установлены на мое текущее время/зону, это, кажется, дает несогласованные результаты.

Редактировать: Короче говоря, это как если бы и .NET, и JavaScript игнорировали летнее/британское летнее время (UTC + 01: 00), когда я пытаюсь разобрать строку. Результат был бы правильным для зимы, а также правильным, когда я физически меняю свое время/зону ...но, как есть, это неверно на «any» Машина, которую я тестировал в Великобритании.

+0

Я думаю, что '+ 0100' игнорируется, это может зависеть от« региональных настроек »на локальном компьютере. Я проверил код, и он показал мне '07: 45: 30' против' 02: 45: 30' не так, как в вашем тесте. –

+0

Это то, что вы получаете для жизни/кодирования в часовом поясе UTC ... Parse * always * return local time, но в вашем случае в UTC и локальном - нет-op. –

+0

На самом деле ваш код должен появляться как 'Local: 05/01/1987 07: 45: 30' и' UTC: 05/01/1987 08: 45: 30', '+ 0100' - это просто указать, что время 'UTC', поэтому все локальное время будет« UTC time - 1 ». –

ответ

2

Великобритания использует летнее время (опережения свои часы на один час) летом (27 августа, ваш «сейчас» в примерах), но не зимой (5 января, с вашего разборе " 1987- 01-05 T08: 45: 30.500 + 0100 ").

На самом деле, зимой Великобритания использует UTC. У вашей машины, похоже, есть британский TimeZoneInfo. Вы можете проверить это с помощью TimeZoneInfo.Local.DisplayName (начиная с .NET 3.5) или TimeZone.CurrentTimeZone.StandardName (старый).

Вы можете проверить с помощью dt.IsDaylightSavingTime().

Дополнение

Мой ответ о .NET только (но, возможно, то же самое относится и к JavaScript?). Примеры, которые вы предоставляете, работают полностью, как ожидалось. Дата и время в январе 1987 года будут преобразованы в вашу местную зону, которая предположительно является британской, а в январе 1987 года Соединенное Королевство находилось в +0000, поскольку это была зима. Строка времени, которую вы дали, была отмечена +0100 (как если бы она была из Германии или какой-либо другой страны на один час к востоку от Великобритании), и это было подтверждено, когда строка была проанализирована. Дата лета 1987 года правильно изменилась бы по-другому, потому что летом 1987 года Британия (и все ЕЭС) наблюдали летнее время (летнее время).

Подводя итог: указатель смещения или спецификатор зоны +0100: учитывается при интерпретации времени. Это конвертируется в британское время на вашем компьютере. Если вы хотите конвертировать в UTC вместо преобразования в локальное время вашего компьютера, используйте перегрузку, которая принимает перечислимое число DateTimeStyles и включает флаг DateTimeStyles.AdjustToUniversal.

Если вы хотите значение, которое лучше представляет время и абсолютной зону, рассмотреть вопрос об использовании DateTimeOffset-структуры вместо DateTime. Вы также можете рассматривать время NODA вместо типов .NET.

+0

Это правильно. В конечном итоге я решил, что точка, которую я пытаюсь сделать, заключается в том, что ни .NET, ни JavaScript, похоже, не сохраняют смещение. Поэтому вы всегда получаете время UTC. Я думаю, причина в том, что если смещение было сохранено, это было бы несовместимо с машиной пользователей. то есть, если смещение было +0100, а часовой пояс пользователей был +0800, смещение (локальное/время) не было бы согласованным на машине пользователя ... если это имеет смысл? – series0ne

+0

@ series0ne Я думаю, что вы ошибаетесь. Попробуйте изменить строку '' 1987-01-05T08: 45: 30.500 + 0100 "' в, например. '' 1987-07-05T08: 45: 30.500 + 0100 "' (лето). *** Edit: *** Кроме того, за меньшую путаницу, попробуйте со строкой с зоной, которая далека от Великобритании, например '+ 1100' или что-то в этом роде. Рассматривается зона _is_. –

+0

Я редактировал весь вопрос, не могли бы вы взглянуть еще раз? Благодарю. – series0ne

0

ToLocalTime и ToUniversalTime учитывают летнее время и делают отличную работу. По крайней мере, в .Net, объект Date Javascript имеет недостатки, и я бы рекомендовал использовать moment.js и moment-timezone.js для преобразований в js.

Вот мой блок тестирования и результаты:

 var now = DateTime.Now; 
     Console.WriteLine(now.ToLocalTime()); 
     Console.WriteLine(now.ToUniversalTime()); 

     //Test 1 TimeZone UTC+1 London, etc.. 
     //current day 20th July = BST 

     /* 07/20/2015 01:06:43 
      07/20/2015 00:06:43*/ 

     //set day to 20th Januray UK winter time 

     /* 01/20/2015 01:07:55 
      01/20/2015 01:07:55*/ 

Для вас, чтобы получить описанные выше результаты в .NET вы должны были бы а) установить часовой пояс для UTC + 2 б) работать в сбой в ToLocalTime(), который с тех пор был исправлен, MSDN упоминает недостатки XP при конвертировании дат.

И, наконец, DateTime.Now возвращает локальное время, используя DateTime.Now.ToLocalTime() немного избыточно, и вы можете получить неожиданные результаты.

 Смежные вопросы

  • Нет связанных вопросов^_^