首页 > 解决方案 > 当存储为 UTC 时,如何全局序列化和反序列化 Date 与 DateTime?

问题描述

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

当从数据库中获取日期并通过 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 中的用户选择 2018 年 11 月 24 日的日期,当它往返于数据库并返回时,它将变为 2018 年 11 月 23 日(截断下午 6:00 的时间)。

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

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

标签: c#sql-serverdatetimeasp.net-web-apijson.net

解决方案


使用@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


推荐阅读