C# 当存储为UTC时,如何全局序列化和反序列化日期与日期时间?
在我的SQL Server数据库中,我将所有C# 当存储为UTC时,如何全局序列化和反序列化日期与日期时间?,c#,sql-server,datetime,asp.net-web-api,json.net,C#,Sql Server,Datetime,Asp.net Web Api,Json.net,在我的SQL Server数据库中,我将所有DateTime值存储为UTC。不过,在某些情况下,我并不关心时间,比如某个随机时区的用户使用日期选择器选择日期。在这些情况下,只存储为DatevsDateTime似乎更有意义 当从数据库中获取日期并通过Web API将其发送到Angular应用程序时,我希望确保我所有的DateTime值的格式能够使Angular知道它们是UTC日期并显示为本地时间,因此我将此添加到Web API中,以便在末尾添加“Z”: // Set all dates to UT
DateTime
值存储为UTC。不过,在某些情况下,我并不关心时间,比如某个随机时区的用户使用日期选择器选择日期。在这些情况下,只存储为Date
vsDateTime
似乎更有意义
当从数据库中获取日期并通过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'"
});
这是可行的,但问题是,这种转换也应用于我的日期
值。当一个日期从数据库拉入C#时,它们在DateTime
变量中,因为C#没有date
变量,所以它们的时间是午夜。因此,如果CST中的用户选择的日期是2018年11月24日,当它往返于数据库时,它就变成了2018年11月23日(下午6:00被截断)
如何防止这种行为?一些想法可以是:
- 我认为这在全球范围内是不可能的,因为我无法判断它是存储在C#DateTime变量中的
还是Date
值DateTime
DateTime
?
- 我认为这也行不通,因为即使我根据数据的来源存储时间,对于其他时区的用户来说,它是否仍然是错误的
使用@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
属性,但这至少让我松了一口气
向有棱角的用户发出警告。我最初尝试使用格式“yyyy-MM-dd”,但它必须将其解释为UTC,因为我在向用户显示日期时遇到了相同的问题。但将其改为“MM dd yyyy”还是有效的。请参见顺便说一句,您可以对ISO8601格式的日期使用DateTimeFormat“o”。当然,这对你的问题没有多大帮助。因为你使用的是JSON.NET,你可以在这些日期字段上使用[JsonConverter]属性。“我很想看看是否有更好的解决办法。”约翰,我考虑过这样做。如果可能的话,我更愿意在全球范围内处理。如果我真的这样做了,你知道该属性是否会覆盖全局IsoDateTimeConverter,以便我仍然可以对所有其他DateTime值使用全局转换器吗?我认为应该这样做,但不要让我这么认为。首先,你似乎对它感到困惑。第一个是特殊时区,第二个是日期/时间/日期时间和期间的字符串表示的标准规范。其次,如果您使用的是Sql Server,我认为您已经找到了正确的解决方案。如果您的类对
Date
和DateTime
使用了不同的数据类型来镜像数据库,那么您可以在全局配置中使用针对该类型的自定义转换器(与DateTime的其他转换器一起使用),并且您不需要这些属性。但是,由于它们使用相同的数据类型,您仍然需要某种属性来区分它们,以便能够全局应用转换器(例如,使用自定义协定解析程序)。因此,您不妨使用[JsonConverter]
属性直接应用转换器并跳过解析器。