【问题标题】:get UTC DateTime from query string从查询字符串中获取 UTC 日期时间
【发布时间】:2018-05-25 05:31:57
【问题描述】:

假设我们有行动:

[HttpGet]
public Task<IActionResult> Foo(DateTime date)
{
    var utc = date.ToUniversalTime();
}

似乎 MVC 框架默认将 UTC DateTime 转换为 Local(在中间件中的某个位置)。如何关闭此行为并摆脱额外的转换?

UPD:

Chrome 开发者。控制台(网络选项卡)向我显示了这样的查询参数: date:2017-12-01T00:00:00.000Z

但在控制器中我看到: {01/12/2017 03:00:00}

【问题讨论】:

  • 你能发布一个通过网络传来的日期的手表值吗?
  • 我怀疑值在运输过程中发生了变化。您可以验证从客户端发送的日期值吗?它与您在控制器中看到的有什么不同?
  • @RossBush:见更新
  • 并且本机设置为UTC+3?
  • @RossBush: 完全正确

标签: c# asp.net asp.net-mvc asp.net-core


【解决方案1】:

DateTime 在需要基于时区的准确时间时不应使用。这就是DateTimeOffset 存在的原因。默认情况下,DateTime.KindDateTimeKind.Unspecified。换句话说,在发布之后,由你来决定它应该被解释为什么。问题是你真的只能假设DateTimeKind.Utc,因为这是你唯一可以正确解释为DateTime 的东西。发布用户的当地时间会让您束手无策,因为DateTimeKind.Local 实际上表示服务器的当地时间,通常与客户端的时间不同。

但是,即使在 HTML5 中,发布带有时区的完整日期时间几乎是不可能的。尽管存在datetimedatetime-local 等输入类型,但它们并未在任何主流浏览器中实现。如果您想发布带有时间和时区的日期,那么您实际上需要在视图模型上使用三个属性:

public DateTime Date { get; set; }
public TimeSpan Time { get; set; }
public string TimeZone { get; set; }

TimeZone 属性假定您将使用由来自TimeZoneInfo.GetSystemTimeZones() 的值组成的下拉列表。如果您想使用不同的设置,您将需要一些方法来映射到这些值/从这些值映射,因为这就是您必须在 C# 中使用以获得偏移量的全部内容。但是,您可以简单地允许用户发布偏移量,但这对用户不太友好,并且对某些用户来说可能很困难。特别是,他们不仅需要了解“与 UTC 偏移”的概念是什么意思,还需要考虑夏令时的当前状态,并根据实际日期调整偏移量。

无论如何,这些属性中的每一个都可以轻松映射到输入类型:date/timeselect/timeTimeZone 的情况下,取决于您是否使用下拉菜单或手动偏移条目。它们也都可以通过模型绑定器在帖子之后轻松映射回您的视图模型。然后,您只需要根据该信息创建一个DateTimeOffset,这就是您实际保留在实体类中的内容。

var offset = TimeZoneInfo
    .FindTimeZoneById(model.TimeZone)
    .GetUtcOffset(model.Date)
var dateTimeOffset = new DateTimeOffset(model.Date.Add(model.Time), offset);

【讨论】:

  • "这就是 DateTimeOffset 存在的原因。"但是 DateTimeOffset 也不提供基于时区的日期/时间;正如您稍后提到的,它仅在单个时间点捕获偏移量。我认为最好不要给人以 DateTimeOffset 包含实时时区的印象。也不清楚为什么在模型中将日期和时间分开。 (这样做会使您对 GetUtcOffset 的使用无效,IMO。) DateTime 可以处理其中任何一个。 重要的是要明确该模型是否旨在表示本地时间。
  • 您的最后一段代码看起来像是希望模型表示本地时间 - 但您没有提到重复或跳过的本地日期/时间值,或者它所在的情况最好使用本地日期/时间值与 UTC 时间戳。
  • 实际上,我对客户端时区并不真正感兴趣,而是我想将传递的 DateTime 视为 UTC(因为时间戳末尾的“Z”字母意味着它必须是世界标准时间)。我可以轻松配置 JSON.NET 序列化程序以这种方式处理 UTC 日期,但我不明白为什么没有办法说 MVC 默认情况下不转换为本地日期时间......
猜你喜欢
  • 2017-02-03
  • 1970-01-01
  • 2020-03-27
  • 2013-04-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
  • 2011-05-30
  • 2020-01-08
相关资源
最近更新 更多