2013-01-20 15 views
10

Mam problemy wyświetlające poprawną datę w przeglądarce klienta przy użyciu serializowanego obiektu JSON. Użytkownik może zdefiniować strefę czasową, w której chce wyświetlać dane. Biorąc to pod uwagę, konwertuję datę UTC na strefę czasową użytkownika na serwerze. Następnie chcę serializować datę/czas (które są już konwertowane na ich określoną strefę czasową) do przeglądarki przez JSON.Serializacja daty JSON i strefy czasowe

Wydaje się to proste, jednak serializatory JSON, z których korzystałem, bardzo źle podsumowywały moje daty. Serwer znajduje się w systemie UTC, a klient jest w trybie centralnym (-6). Terminy są dostosowywane (-12 godzin), mimo że określam DateTime.Kind to Unspecified.

W jakiś sposób .NET wie, w jakiej strefie czasowej znajduje się przeglądarka klienta oraz w jakiej strefie czasowej znajduje się serwer i neguje -6 od moich dat/czasów, mimo że już skorygowałem czas według ustawień globalnych użytkownika i ustawić rodzaj dat, które będą nieokreślone. Jak mogę uzyskać serializatory JSON, aby NIE próbować dopasowywać dat?

List<ErrorGridModel> models = Mapper.Map<ErrorCollection, List<ErrorGridModel>>(errors); 
foreach (ErrorGridModel m in models) 
{ 
    //convert UTC dates to user local dateTime - split out date vs. time for grouping & splitting columns 
    DateTime dtLocal = TimeZoneInfo.ConvertTimeFromUtc(m.ErrorDate, this.AppContext.User.TimeZoneInfo); 
    m.ErrorDate = new DateTime(dtLocal.Year, dtLocal.Month, dtLocal.Day, 0, 0, 0, DateTimeKind.Unspecified); 
    m.ErrorTime = new DateTime(1900, 1, 1, dtLocal.Hour, dtLocal.Minute, dtLocal.Second, DateTimeKind.Unspecified); 
} 
IQueryable<ErrorGridModel> dataSource = models.AsQueryable(); 
return new ContentResult() { Content = JsonConvert.SerializeObject(dataSource.ToDataSourceResult(request), new JsonSerializerSettings() { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat }), ContentType = "application/json" }; 
//return Json(dataSource.ToDataSourceResult(request)); 

daty ISO wydaje się działać, ale nie mogę ich używać jak mam 3rd kontrole firm, które chcą starszego formatu Microsoft ... który dostosowuje strefy czasowe na mnie.

+0

To nie jest odpowiedź na Twój problem, ale jeśli chcesz przesunąć datę logikę do JavaScript - sprawdź moment.js http://momentjs.com/ –

Odpowiedz

1

Oto długa dyskusja na temat dokładnej sytuacji, że byłem w. http://www.telerik.com/community/forums/aspnet-mvc/grid/grids-and-dates.aspx

Konkluzja, jeśli używasz format daty Microsoft JSON, to zawsze będzie odzwierciedlać datę w UTC jako liczbę milisekund (kleszcze) od 1/1/1970 UTC. Nie ma sposobu, aby automatycznie przekonwertować czas na lokalny na serwerze i wysłać to, co powinno być w dół przez JSON do Kendo Grid, ponieważ kontrola Kendo Grid tworzy datę od ticks w JS jako UTC. Podczas wyświetlania tej daty, nastąpi automatyczna konwersja wartości do lokalnej strefy czasowej przeglądarki.

Jedynym sposobem na wyświetlenie wartości daty konwersji mojego serwera z serwera jest wysłanie daty przez JSON jako ciąg do klienta.

+1

Twój link do kendo jest zepsuty, masz dobry link ... mający ten sam problem tutaj. – felickz

4

Kiedy próbujesz kontrolować przesunięcia, nie polegaj na DateTimeKind.Unspecified. Ma kilka dziwactw, które często są interpretowane jako Unspecified == Local. Jedynym sposobem, aby Json.Net specjalnie zakodować poprawne przesunięcie (bez względu na format ISO lub MS), jest przekazanie go jako DateTimeOffset zamiast DateTime.

// Start with the UTC time, for example your m.ErrorDate. 
// Here I demonstrate with UtcNow. Any DateTime with .Kind = UTC is ok. 
var dt = DateTime.UtcNow; 

// Use the appropriate time zone, here I demonstrate with EST. 
var tzi = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); 

// Get the offset from UTC for the time zone and date in question. 
var offset = tzi.GetUtcOffset(dt); 

// Get a DateTimeOffset for the date, and adjust it to the offset found above. 
var dto = new DateTimeOffset(dt).ToOffset(offset); 

// Serialize to json 
var json = JsonConvert.SerializeObject(dto, new JsonSerializerSettings 
    { 
     DateFormatHandling = DateFormatHandling.MicrosoftDateFormat, 
    }); 


// The json should now contain the correct time and offset information. 
// For example, "\/Date(1358789156229-0500)\/" 

Teraz mam nadzieję, że okaże się, że kod JavaScript kontrole używasz uhonoruje offset i stosuje się go w odpowiedni sposób. Jeśli nie, to reszta problemu jest specyficzna dla używanej kontroli.

+0

Cóż, Spróbowałem twojego pomysłu. +1 dla dobrego pomysłu. Niestety, Kendo Grid (kontrola 3rd-party), której używam, nie działa z informacją offsetową :(Moim ostatnim pomysłem jest ewentualnie stworzyć mój własny konwerter dat i przekazać go do JSON.NET.Następnie moje daty są konwertowane po stronie serwera do żądanej strefy czasowej użytkownika zostanie przekazana za pośrednictwem JSON bez .NET, automatycznie dostosowując czasy do mnie. –

+0

@BillChristenson Powinieneś przeczytać [ten artykuł] (http://onabai.wordpress.com/2012/09/28/kendoui- tips-and-tricks-on-dates-in-a-grid /) Autor opisuje, jak radzić sobie z datami w sieciach kendo.Pokazuje również, jak możesz zaakceptować formatowanie daty w formacie ISO [tutaj] (http://onabai.wordpress.com/2012/09/27/kendoui-supporting-iso-8601-dates/), co byłoby o wiele lepszym IMHO niż przy użyciu formatu daty microsoft. –

+0

Tak, czytałem te blogi. Używam obwolut serwera AJAX/JSON MVC, który jest inną implementacją niż używa. Nie chcę też modyfikować ich plików .js, jeśli uda mi się uciec. Dam wam znać, jak działa mój niestandardowy konwerter JSON.NET. Zbliżam się do ukończenia tego. –