Часовой пояс Azure и объект javascriptserializer

У меня есть приложение на основе прогнозов, работающее в Windows Azure ( http://ipredikt.com ). Насколько я могу судить, часы Azure синхронизированы с часовым поясом GMT. Вот проблема, с которой я сталкиваюсь:

Допустим, у меня есть поле БД с именем CreateDate типа DateTime, и я установил его значение на 10 июня 2011 г., 00:30. при создании нового прогноза. Если я загляну внутрь таблицы db, дата будет установлена ​​правильно. Я никак не трогаю и не изменяю это значение. Однако, когда я читаю значение с помощью нашего API, сериализую его и отправляю клиенту, я получаю дату со значением 09 июня 2011 г., 17:30. (DLL API также находится в облаке и, вероятно, совмещена с БД.)

Мой клиентский браузер работает в PST (тихоокеанский часовой пояс), и кажется, что разница в 7 часов связана с разницей между PST и GMT. Код API, используемый для сериализации значения, похож на этот:

System.Web.Script.Serialization.JavaScriptSerializer сериализатор = новый JavaScriptSerializer();

вернуть сериализатор. Сериализация (объект данных);

Это ошибка в объекте JavaScriptSerializer или есть способ исправить эту дельту? По сути, я не хочу, чтобы платформа .NET каким-либо образом вмешивалась в это значение, я просто хочу, чтобы поле БД просто возвращалось как есть.


person Archil Kublashvili    schedule 20.06.2011    source источник


Ответы (2)


Когда вы передаете объект DateTime в Azure, его вид равен Local.
(10 июня 2011 г., 00:30–7)

Однако при сохранении в базе данных информация о регионе теряется. Впоследствии при чтении этого поля из базы данных создается DateTime с регионом Utc (10 июня 2011 г., 00:30)

В конце концов, ваш клиент неправильно считывает дату и время.

Есть несколько вариантов решения этой проблемы.

1) Преобразование DateTime в DateTimeOffset в параметрах метода, а также в базе данных. Это гарантирует, что ваш локальный регион (т.е. PST) будет сохранен в БД.

2) Используйте DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified) - таким образом, тип DateTime не указан и впоследствии сохраняется как есть в БД.

var timeNow = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified);
serviceClient.SaveTime(timeNow);
var dateTime = serviceClient.GetTime();
person Boris Lipschitz    schedule 22.06.2011
comment
Все это имеет общий смысл, и я чувствую, что именно это и происходит. Тем не менее, я попробовал решение 2, которое вы предлагаете, но безуспешно. Я пробовал все варианты DateTimeKind как при сохранении, так и при чтении из БД, но все равно получаю дельту на клиенте. На самом деле, я не уверен, зачем мне что-то указывать при сохранении значения даты и времени в БД. Когда я смотрю в таблицу, значение равно 2011-06-10 00:00:00.000 (я использовал только 12:30 в приведенном выше примере, чтобы избежать путаницы, но я установил время на 00:00). Поэтому при чтении я пробовал Local, Utc и Unspecified, но все равно получаю дельту -7. - person Archil Kublashvili; 22.06.2011
comment
В следующем примере я использую wcf, и на стороне sql azure есть структура сущностей. var timeNow = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified); serviceClient.SaveTime(timeNow); var dateTime = serviceClient.GetTime(); полученное значение dateTime имеет значение Kind равно Unspecified. И это работает на моей машине - person Boris Lipschitz; 23.06.2011
comment
Я принял во внимание то, что вы сказали о датах Azure, и решил проблему в самом javascript, выполнив следующее: var dd = new Date($idDueDate.val()); oPrediction.DueDate = новая дата (dd.toUTCString()); перед фактическим сохранением в БД. Даты менялись Azure точно так, как вы описали выше. Спасибо всем. - person Archil Kublashvili; 28.06.2011

Предположительно, в сериализованном ответе Json появляется дата в формате «миллисекунды с начала эпохи», которая также должна включать информацию о часовом поясе, которую браузер затем принимает во внимание при отображении даты относительно местного часового пояса.

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

Даты .NET имеют свойство «Вид». Если это не указано, предполагается UTC. Сериализатор должен учитывать свойство «Вид» при сериализации. Попробуйте проверить это свойство вашего объекта перед сериализацией и изменить его на DateTimeKind.Local.

http://msdn.microsoft.com/en-us/library/system.datetime.kind.aspx

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

person Ash Eldritch    schedule 20.06.2011
comment
Довольно точно, но если я правильно помню, вам нужно установить его в DateTimeKind.Unspecified, чтобы время не менялось при сериализации/десериализации через границы часовых поясов. - person David Steele; 20.06.2011
comment
Когда я проверяю свойство Kind на своем объекте перед сериализацией, для него устанавливается значение Unspecified. - person Archil Kublashvili; 22.06.2011