c# - ASP.NET 4.6 MVC 如何返回包含具有正确时区的日期时间数据的 Json 结果?

标签 c# asp.net json asp.net-mvc .net-4.6

我希望返回一个包含从数据库查询的日期时间的 Json 结果。在我的本地机器上测试没有任何问题,但是,在发布到生产服务器后,所有日期时间都提前 3 小时显示。我认为这是由于服务器位于另一个时区。

需要帮助来解决这个问题。

数据库中的数据(MS SQL):

StartDt: 2019-07-02 04:00:00.000

Controller.cs:

 [HttpGet]
        public ActionResult GetAll()
        {
            CalendarModel calendarModel = new CalendarModel();

            var calendarEvents = from cal in db.Calendar
                                 orderby cal.created descending
                                 select cal;


            return Json(calendarEvents, JsonRequestBehavior.AllowGet);
        }

从我的计算机获取的 Json 结果:

[
    {
        //some data
        "startDt": "/Date(1562054400000)/",
        //some data
    },

上面的日期时间被解析为“2019-07-02T04:00:00.000-04:00”,这是正确的。

从生产服务器获取的 Json 结果(从同一数据库查询):

[
    {
        //some data
        "startDt": "/Date(1562065200000)/",
        //some data
    },

这个日期时间是“2019-07-02T07:00:00.000-04:00”,这是错误的。

--------更新我的解决方案--------

感谢@TommasoBertoni的回答启发了我这个问题的关键原因是由于默认的Unspecified DateTime Kind但是变成了local 在 Json 序列化时。所以只需要将DateTime Kind设置为UTC即可解决,但注意前端解析DateTime也需要将其设置为UTC否则会被认为默认为 local

Controller.cs:

 [HttpGet]
public ActionResult GetAll()
        {
            CalendarModel calendarModel = new CalendarModel();

            var calendarEvents = from cal in db.Calendar
                                 orderby cal.created descending
                                 select cal;
            //Add this
            foreach (var item in calendarEvents)
            {
                item.startDt = DateTime.SpecifyKind(item.startDt, DateTimeKind.Utc);
            }

            return Json(calendarEvents, JsonRequestBehavior.AllowGet);
        }

.js (使用 moment.js 库)

//parse it as utc
  moment.utc(startDt).format("YYYY-MM-DDTHH:mm:ss")

最佳答案

问题是 ASP.NET 使用 custom Microsoft JSON date format ,它将 DateTime 值编码为 /Date(ticks)/,其中 ticks 表示自纪元 (UTC) 以来的毫秒数。
因此,1989 年 11 月 29 日凌晨 4:55:30,在 UTC 中被编码为 /Date(628318530718)/(更多信息请参见 here)。

例子:

  • Microsoft JSON 日期格式:/Date(1563464520158)/
  • ISO 8601 格式:2019-07-18T15:42:02.4592008Z

如果 DateTime 有一个 Unspecified 类型,它将被假定为 Local 并且该值将被转换为 UTC 以获得自纪元以来的刻度。

这种 json 格式仍在 MVC 中使用,但不在 Web API 中:这意味着当您在 Controller 中并使用 Json 序列化结果时(...) 您将获得非 ISO 格式,但如果您在 ApiController 中,默认序列化程序是 Json.NET,它支持 ISO 8601 格式并获得'转换 DateTime 值。

因此,要修复此行为,要么切换到 Web API,要么如果您想继续使用 MVC Controller ,您可以查看这些问题的答案:

...或者您可以在 json 序列化之前强制 DateTime Kind 为 Utc,但我不建议这样做。


class TestRepo
{
    public IEnumerable<DateTime> GetDates()
    {
        var now = DateTime.Now;

        // Use DateTime instances with different Kind
        // showing that it doesn't impact the serialization format.
        var utc = DateTime.SpecifyKind(new DateTime(now.Ticks), DateTimeKind.Utc);
        var local = DateTime.SpecifyKind(new DateTime(now.Ticks), DateTimeKind.Local);
        var unspecified = DateTime.SpecifyKind(new DateTime(now.Ticks), DateTimeKind.Unspecified);

        return new DateTime[] { utc, local, unspecified };
    }
}
// MVC controller
public class MVCValuesController : Controller
{
    public ActionResult Index()
    {
        IEnumerable<DateTime> dates = new TestRepo().GetDates();
        return Json(dates, JsonRequestBehavior.AllowGet);
    }
}

// json result:
[
    "/Date(1563465361835)/", // <-- Utc
    "/Date(1563458161835)/", // <-- Local
    "/Date(1563458161835)/"  // <-- Unspecified
]
// Web API controller
public class ValuesController : ApiController
{
    public IEnumerable<DateTime> Get()
    {
        IEnumerable<DateTime> dates = new TestRepo().GetDates();
        return dates;
    }
}

// json result:
[
    "2019-07-18T15:56:03.6401158Z",      // <-- Utc
    "2019-07-18T15:56:03.6401158+02:00", // <-- Local
    "2019-07-18T15:56:03.6401158"        // <-- Unspecified
]

关于c# - ASP.NET 4.6 MVC 如何返回包含具有正确时区的日期时间数据的 Json 结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57092326/

相关文章:

c# - 如何在 ActionLink 的字符串部分添加换行符?

php - 如何从 MySQL 创建对 Google Chart 友好的 JSON 数组?

c# - 在 Unity3d 中翻转 3D 游戏对象

c# - 字符串缺少终止符 : "

c# - ASP.NET C# + Nhibernate HTTP 模块 (Session per request) - 限制请求类型

json - 将嵌套的主干关系模型序列化/反序列化为 JSON

javascript - JSON.parse 如何管理 'undefined' ?

c# - 基础连接已关闭。无法与远程服务器建立信任关系

c# - 在 C# 中实例化实现 .NET 接口(interface)的 IronPython 类型

c# - ASP.NET 中用户控件和页面的通用基类