JSON日期序列化和时区

时间:2013-01-20 18:15:51

标签: .net json datetime timezone json.net

我在使用JSON序列化对象在客户端浏览器上显示正确日期时遇到问题。用户可以定义他们想要查看数据的时区。鉴于此,我将UTC日期转换为服务器上用户的时区。然后我想通过JSON将日期/时间(已经转换为定义的时区)序列化到浏览器。

看起来很简单,但是我一直在使用的JSON序列化程序严重破坏了我的日期。服务器为UTC,客户端位于Central(-6)。即使我将DateTime.Kind指定为未指定,日期也会被调整(-12小时)。

不知何故,.NET知道客户端浏览器所在的时区以及服务器处于什么时区,即使我已根据用户的全局设置和设置调整了时间,它也取消了我的日期/时间-6日期的种类是未指明的。如何让JSON序列化程序不尝试调整我的日期?

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));

ISO日期似乎有效,但我无法使用它们,因为我有第三方控件需要较旧的Microsoft格式...这会调整我的时区。

3 个答案:

答案 0 :(得分:4)

当您尝试控制偏移时,请不要依赖DateTimeKind.Unspecified。它有一些通常被解释为Unspecified == Local的怪癖。让Json.Net专门编码正确的偏移量(无论ISO或MS格式)的唯一方法是将DateTimeOffset而不是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)\/"

现在希望你会发现你正在使用的javascript控件将尊重偏移并适当地应用它。如果没有,则问题的其余部分特定于您正在使用的控件。

答案 1 :(得分:2)

以下是对我所处的确切情况的长期讨论。http://www.telerik.com/community/forums/aspnet-mvc/grid/grids-and-dates.aspx

最重要的是,如果您使用的是Microsoft JSON日期格式,它将始终将UTC中的日期反映为UTC时间为1/1/1970的毫秒数(滴答)。由于Kendo Grid控件将JS中的滴答日期实例化为UTC,因此我无法将时间自动转换为服务器上的本地时间并通过JSON将其发送到Kendo Grid。显示此日期时,它会自动将值转换为浏览器的本地时区。

从服务器显示我的服务器转换日期值的唯一方法是通过JSON将日期作为字符串发送给客户端。

答案 2 :(得分:0)

我们也遇到了这个问题。如您所知,问题实际上发生在客户端。通过在网格中使用请求结束处理程序,您可以将日期转换回UTC。在此处找到的示例:

http://www.kendoui.com/code-library/mvc/grid/using-utc-time-on-both-client-and-server-sides.aspx