当存储为UTC时,如何全局序列化和反序列化Date vs DateTime?

时间:2018-11-24 13:01:33

标签: c# sql-server datetime asp.net-web-api json.net

在我的SQL Server数据库中,我将所有DateTime值存储为UTC。但是,在某些情况下,我不关心时间,例如某个随机时区中的用户使用DatePicker选择日期时。在这些情况下,将它们存储为DateDateTime似乎更有意义。

当从数据库中获取日期并通过Web API将其发送到Angular应用程序时,我想确保所有DateTime值的格式都可以使Angular知道它们是UTC日期,并且显示为本地时间,因此我将其添加到Web API中以在末尾添加“ Z”:

// Set all dates to UTC
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new IsoDateTimeConverter
{
    DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
});

这有效,但是问题在于此转换也同样适用于我的Date值。当日期从数据库中拉到C#时,它们在DateTime变量中,因为C#没有Date变量,因此它们的时间为午夜。因此,如果CST中的用户选择的日期为11/24/2018,则当它往返于数据库并返回时,它将变为11/23/2018(下午6:00的时间被截断)。

如何防止这种行为?一些想法可能是:

  1. 有条件地应用IsoDateTimeConverter吗?
    • 我认为这在全球范围内都是不可能的,因为我无法确定它是存储在C#DateTime变量中的Date还是DateTime值。
  2. 将SQL Server中的数据类型更改为DateTime吗?
    • 我也不认为这行得通,因为即使我根据数据的来源存储时间,对于其他时区的用户来说还是不对吗?

1 个答案:

答案 0 :(得分:1)

使用@John的建议,我创建了一个自定义IsoDateTimeConverter:

public class DateConverter : IsoDateTimeConverter
{
    public DateConverter()
    {
        DateTimeFormat = "MM-dd-yyyy";
    }
}

并手动将其应用于每个Date值,该值将覆盖我添加到Web API配置中的全局转换器。

[JsonConverter(typeof(DateConverter))]
public System.DateTime StartDate { get; set; }

我仍然希望有一种全局的处理方式,而不是必须将属性应用于每个Date属性,但这至少使我感到困惑。

向Angular用户发出警告。我最初尝试使用格式“ yyyy-MM-dd”,但是它必须将其解释为UTC,因为在向用户显示日期时我遇到了同样的问题。不过将其更改为“ MM-dd-yyyy”也可以。参见https://github.com/angular/material2/issues/6111