从查询字符串获取UTC日期时间

Dzm*_*voi 5 c# asp.net asp.net-mvc asp.net-core

假设我们有行动:

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

似乎默认情况下,MVC框架将UTC DateTime转换为Local(中间件中的某处)。如何关闭此行为并摆脱其他转换?

UPD:

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

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

Chr*_*att 1

DateTime当需要准确的基于时区的时间时不应使用。这就是DateTimeOffset存在的原因。默认情况下,DateTime.KindDateTimeKind.Unspecified. 换句话说,发布后由您决定应将其解释为什么。问题是你实际上只能假设DateTimeKind.Utc,因为这是你唯一可以DateTime正确解释的事情。发布用户的本地时间会让您陷入困境,因为DateTimeKind.Local实际上意味着服务器的本地时间,通常与客户端的本地时间不同。

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

public DateTime Date { get; set; }
public TimeSpan Time { get; set; }
public string TimeZone { get; set; }
Run Code Online (Sandbox Code Playgroud)

TimeZone属性假设您将使用由 中的值组成的下拉列表TimeZoneInfo.GetSystemTimeZones()。如果您想使用不同的设置,则需要某种方法来映射到这些值或从这些值进行映射,因为这就是您在 C# 中需要使用的所有方法来获取偏移量。但是,您可以简单地允许用户发布偏移量,但这对用户不太友好,并且对于某些用户来说可能很困难。特别是,他们不仅需要了解“UTC 偏移”概念的含义,还需要考虑夏令时的当前状态并根据实际日期调整该偏移。

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

var offset = TimeZoneInfo
    .FindTimeZoneById(model.TimeZone)
    .GetUtcOffset(model.Date)
var dateTimeOffset = new DateTimeOffset(model.Date.Add(model.Time), offset);
Run Code Online (Sandbox Code Playgroud)