在剃刀页面中使用日期和时间

在使用剃刀页面中使用日期和时间时,您需要呈现 基于任务要求的合适控制。在HTML5之前,开发人员 在很大程度上取决于第三方日期选择器库。现在,各种原生 browser options 存在,虽然他们喜欢 跨越现代浏览器的各种支持。这些包括选项 管理日期和时间,只是日期或时间,以及与之合作 一年中的一个月或一周。

DateTime输入

在剃刀页面中, input tag helper 呈现适当的价值 类型 基于通过通过该模型属性的数据类型的属性 asp-for 属性。

[BindProperty]
public DateTime DateTime { get; set; }
DateTime: <input class="form-control" asp-for="DateTime" />

生成的默认输入类型 DateTime properties is datetime-local in .NET Core 2.0 onwards, which is when Razor Pages was introduced. In ASP.NET Core 1.x and in MVC 5 and earlier, tag helpers and the strongly typed Html helpers would render the input type as datetime,但这从HTML5规范中删除,因为它从未由任何浏览器供应商实现。

在Chrome,Edge和Opera中, datetime-local 呈现控件,使用户能够选择日期和时间。这 格式化控制中的日期和时间的外观是决定的 基础操作系统的区域设置,值本身是 假设代表当地日期和时间,而不是通用时间:

如果您使用的是另一个浏览器(即11,Firefox,Safari),则控制器呈现出普通输入,其表现类似于文本输入。

When examining the rendered mark up, you see that the value has been formatted by the input tag helper to a 基于的表示 ISO 8601 standard:

DateTime-Local

这是HTML5控制所需的格式。 如果您尝试将值应用于控件,您应该牢记这一点 你自己,例如通过脚本。如果您需要生成适当格式化的 使用.NET的价值,您可以使用 “o”(或“o”)格式字符串, although you will need to set the Kind to Unspecified to ensure that 输出中不包含时区偏移量,因为 datetime-local 控制不支持它:

var dt = new DateTime(DateTime.Now.Ticks, DateTimeKind.Unspecified);
var isoDateString = dt.ToString("O");

默认情况下,格式化的字符串包含到的时间 毫秒,所以UI的时间选择器部分提供了设定时间,分钟, 秒和毫秒:

剃刀页面的DateTime

更常见的是,您只需要启用 用户指定时间的时间。你通过这个 格式化值传递给控件的时间部分。你可以 do this in one of two ways. You can use the DisplayFormat data 模型属性的注释属性 指定格式并确保在该值为时格式也适用 在“编辑模式”(表单控件):

[BindProperty, DisplayFormat(DataFormatString = "{0:yyyy-MM-ddTHH:mm}", ApplyFormatInEditMode = true)]
public DateTime DateTime { get; set; }

Alternatively, you can use the asp-format attribute on the 输入标签帮助本身:

DateTime: <input class="form-control" asp-for="DateTime"  asp-format="{0:yyyy-MM-ddTHH:mm}" />

剃刀页面的日期和时间

The default value for a DateTime in .NET is DateTime.MinValue, represented as 0001-01-01T00:00:00 在控制中。如果你不想要 最初显示值,您可以使绑定属性无效:

[BindProperty]
public DateTime? DateTime { get; set; }

然后控件将显示其默认设置:

Date And Time Inputs

支持使用本机控制的更广泛的浏览器而不是 第三方图书馆,您可以使用单独使用 date and time controls. A little more configuration is required in 要获取输入标签帮助器以呈现正确的控件:

[BindProperty, DataType(DataType.Date)]
public DateTime Date { get; set; }
[BindProperty, DataType(DataType.Time)]
public DateTime Time { get; set; }

Both properties are DateTime types, but the DataType 属性应用于它们以在渲染的输入中设置正确的类型。 The input tag helper supports both the DataType.Date and DataType.Time options and will render accordingly:

再一次,您可以通过将格式字符串应用于要么将格式字符串应用于此时 a DisplayFormat attribute on the model property or via the asp-format 标签助手上的属性。当值是 posted, the model binder successfully constructs DateTime types 随着时间部分设置到午夜的情况下 date input's value, and the date portion set to today in the case of the time input's value. You can combine the values to construct a new DateTime:

DateTime dt = Date.Add(Time.TimeOfDay);

协调世界时期

建议在应用程序中使用协调的世界时间(或UTC) 这需要日期和时间来存储或表示在时区不可知论 时尚。有关此内容的更多详细信息,您可以阅读 Rick Strahl在主题的综合职位。没有一个日期或时间 controls support the ISO 8601 representation of a UTC time value e.g. yyyy-MM-ddTHH:mm:ssZ (where Z is the time zone information, representing zero time zone offset, and therefore 将此值标识为UTC时间)。但是,您可能必须使用应用程序 此标准格式用于交换时间信息的位置。

在.NET Core 3.0应用程序或更早版本中,模型粘合剂将会 successfully create a DateTime value from a valid ISO 8601 UTC 时间字符串,但它将基于的设置生成当地时间 应用程序执行的服务器。

例如,在10月份上午占据02:15的价值 30th, 2020, UTC: 2020-10-30T02:15:00Z. The following image shows how the 模型粘合剂在设置服务器时解析此值 到太平洋时区:

The default DateTimeModelBinder is able to recognise and process date and time strings that include time zone information. 如果缺少时区,则粘合剂设置 Kind property of the resulting DateTime value to DateTimeKind.Unspecified. Other DateTimeKind values are Local (representing a local time) and Utc (a UTC time). Notice that the Kind in the image above is set to Local instead of Utc尽管存在这一事实,但鉴于存在这一情况,这显然是UTC的时间 Z 在字符串的末尾。粘合剂已将UTC的时间转换为当地时间, 基于服务器设置。正如我今天(十月三十日)所说的那样 太平洋白天时间适用于UTC值之前的7小时。 昨晚。明天,当夏令时拯救在美国西海岸, 在UTC之前产生的值将是8小时,因此解析值将会 再次代表不同的时间。为了获得UTC值,您需要 either use the ToUniversalTime() method on the parsed result:

或者您可以实现自己的模型活页夹来处理UTC时间字符串 在申请中在全球范围内。我将探索我的自定义模型粘合剂 下一篇关于相关任务的文章。

好消息是,来自.NET 5,这已经解决了,因此UTC 模型粘合剂的时间是正确处理的,而不需要任何 绑定值的额外处理:

None of the values have been adjusted, and the Kind is set to Utc automatically.

月份和周的投入

月和周输入类型当前由边缘,铬和 Opera. Where is it supported, the month 类型 provides a means for the user to 选择特定的月份和年份:

输入标签帮助器将渲染控制 类型 ="month" 有一点配置。这是通过使用的实现 DataType 属性过载,它采用表示自定义数据的字符串参数 type:

[BindPropertyDataType("month")] 
public DateTime Month { getset; }

The format of the input month's value is yyyy-MM. The input tag helper generates a suitable value successfully from a DateTime type. So you don't 需要应用任何格式字符串才能获得月份选择器 render correctly:

<input class="form-control" asp-for="Month" />

当值发布返回时,默认值 DateTimeModelBinder will bind this value to a DateTime, with the correct month and 一年,和当天设置为1。

The week input type will also render successfully just through setting a custom data type on a DateTime property:

[BindPropertyDataType("week")] 
public DateTime Week { getset; }

The valid format for the value is yyyy-Www, where the capital W is a literal "W" and ww represents the ISO 8601选定年份。 .NET中没有格式字符串 the week part of a DateTime, but the tag helper generates the 正确格式化的值 DateTime 类型 successfully:


However, the default DateTimeModelBinder is unable to bind that value back to a DateTime. You have a number of options. The most crude option is to access the value directly from the Request.Form collection, parse it as a string and generate a DateTime yourself:

public void OnPost()
{
    var week = Request.Form["Week"].First().Split("-W");
    Week = ISOWeek.ToDateTime(Convert.ToInt32(week[0]), Convert.ToInt32(week[1]), DayOfWeek.Monday);
}

这个例子使用了 IsoWeek效用 在.NET Core 3.0中添加的类。如果您正在使用.NET核心 2 project, you can use the Calendar.GetWeekOfYear() method, but 请注意,在某些边缘案例中, 它不会返回一年中的ISO 8601周.

You could also bind to a string instead of a DateTime. 您必须生成正确格式化的值,并解析结果:

[BindPropertyDataType("week")]
public string StringWeek { getset; }
 
public void OnGet()
{
    StringWeek = $"{DateTime.Now.Year}-W{ISOWeek.GetWeekOfYear(DateTime.Now)}";
}

或者,您可以实现自定义模型粘合剂或 类型转换器,两者都是优选的。我将在即将举行的情况下查看这些选择 articles.

概括

在绝大多数情况下,HTML5,输入标签助手和 default DateTimeModelBinder blend together to make working with 日期和时间容易在剃刀页面中。 HTML5的浏览器实现 输入以标准方式管理数据,同时以格式显示它 用户熟悉,减少开发人员对第三方的依赖 components.