Часова зона на Azure и обект на javascriptserializer

Имам базирано на прогнози приложение, което е на Windows Azure ( http://ipredikt.com). От това, което мога да кажа, часовникът на Azure е синхронизиран с часовата зона GMT. Ето един проблем, който срещам:

Да приемем, че имам поле в DB, ​​наречено CreateDate от тип DateTime и задам стойността му на 10 юни 2011 г., 00:30 ч. когато се създаде нова прогноза. Ако надникна в db таблицата, датата е правилно зададена. Не пипам и не променям тази стойност по никакъв начин. Въпреки това, когато прочета стойността с нашия API, сериализирам я и я изпратя на клиента, получавам дата със стойност 09 юни 2011 г., 17:30 ч. (API dll също живее в облака и вероятно е съвместно с DB.)

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

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

връщане serializer.Serialize(dataObject);

Това грешка в обекта на JavaScriptSerializer ли е или има трик за коригиране на тази делта? По принцип не искам рамката .NET да се намесва в тази стойност по никакъв начин, просто искам полето DB да се връща както е.


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


Отговори (2)


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

Когато обаче го запишете в базата данни, информацията за региона се губи. Впоследствие, когато чете това поле от базата данни, то създава DateTime с Utc регион (10 юни 2011 г., 00:30 ч. 0)

В крайна сметка вашият клиент чете датата и часа неправилно.

Има няколко възможности за разрешаване на този проблем.

1) Преобразувайте DateTime в DateTimeOffset в параметрите на метода, както и в базата данни. Това ще гарантира, че вашият локален регион (т.е. PST) ще бъде записан в db

2) Използвайте DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified) - по този начин видът на DateTime е неуточнен и впоследствие се запазва както е в db.

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 както при запазване, така и при четене от DB, но все още получавам делта на клиента. Всъщност не съм сигурен защо трябва да посочвам нещо, когато записвам стойност за дата и час в DB. Когато погледна в таблицата, стойността е 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()); преди действителното записване в db. Датите се променяха от Azure точно както описахте по-горе. Благодаря на всички. - person Archil Kublashvili; 28.06.2011

Това, което вероятно идва в сериализирания Json отговор, е дата във формат „милисекунди от епохата“ и трябва също да включва информация за часовата зона, която след това браузърът взема предвид, когато показва датата спрямо местната часова зона.

Всичко това е правилно поведение, така че няма грешка. Просто изглежда, че не искате това поведение във вашия случай.

.NET датите имат свойство "Вид". Ако това не е посочено, се приема UTC. Сериализаторът трябва да вземе предвид свойството "Kind" при сериализиране. Опитайте да проверите това свойство на вашия обект преди сериализирането и да го промените на 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