我正在制作一个时钟'网络应用。但是,我无法让EditorFor在LocalTime中显示时间。根据最佳实践,我将所有保存到数据库的内容保存为UTC(通过DateTimeOffset)。
有关如何在本地时间显示此内容并仍保存为UTC的任何建议吗?
视图模型
[DataType(DataType.Time)]
[DisplayFormat(DataFormatString = "{HH:mm}")]
public DateTimeOffset TimeIn { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{MM, DD, YY}")]
public DateTimeOffset DateIn { get; set; }
[DataType(DataType.Time)]
[DisplayFormat(DataFormatString = "{HH:mm}")]
public DateTimeOffset TimeOut { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{MM, DD, YY}")]
public DateTimeOffset DateOut { get; set; }
查看
<div class="form-group">
@Html.LabelFor(model => model.TimeOut, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.TimeOut, new { htmlAttributes = new { @class = "form-control" } })
@Html.EditorFor(model => model.DateOut, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.TimeOut, "", new { @class = "text-danger" })
</div>
</div>
任何帮助将不胜感激,如果您有任何其他希望帮助解决问题,请告诉我。谢谢!
答案 0 :(得分:0)
从另一个项目中,我从C#吐出UTC时间,然后让Javascript从浏览器/操作系统的时区信息转换为本地时间。
因此,为了吐出JS将要读取的格式,我在C#中使用它输出时间:
public enum Color {
RED("Red"), GREEN("Green"), BLACK("Black"), BLUE("Blue"), YELLOW("Yellow");
private final String display;
private Color(String display) {
this.display = display;
}
@Override
public String toString() {
return display;
}
public static EnumSet<Color> getSubSetOfValues() {
return EnumSet.of(RED, BLUE); // return Red and Green
//return EnumSet.range(GREEN, BLUE); // return Green, Black and Blue
}
}
这会给你: 2017/09/28 18:40:22 UTC
然后,将其输入Javascript:
DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm:ss") + " UTC")
这吐出: 2017年9月28日星期四,下午2:40
您也可以根据需要自定义JS输出。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString
要保存,您可能必须将时区传递给服务器,可能在隐藏字段中,以便在保存到数据库之前将其转换为Action中的UTC。
答案 1 :(得分:0)
日期和时间很糟糕。干净利落。有一件事并不明显,但你需要敏锐地意识到,像“当地时间”这样的概念是高度变化的。当您执行TimeOut.LocalTime
之类的操作时,您谈论的是本地服务器时间,这可能是,并且很可能 与用户的本地时间不同。首先,您需要定义您正在寻找的内容,而且更有可能是用户的时间,而不是服务器的内容。结果LocalTime
对你没用。
如果您关心用户的当地时间,那么您必须让他们提供给您。服务器无法识别此信息。您可以在每个日期和时间字段旁边提供时区下拉菜单,或者,如果用户经过身份验证,您可以让他们在其个人资料中设置它,然后将其用于他们提交的所有内容。
无论哪种方式,您将遇到的另一个问题是允许用户输入日期和时间。当您在客户端和服务器之间传输数据时,您正在处理字符串。 MVC中的模型绑定器有助于解析这些字符串值,以将它们绑定到更合适的类型,如DateTimeOffset
,但为了使其起作用,发布的值必须采用非常特定的格式,或者转换过程将失败。期望用户以非常特定的方式做某事当然是灾难的一个方法,所以你需要以某种方式向他们展示一个易于使用的界面,它仍然可以获得你需要的信息,而不会给用户任何机会搞砸它起来,因为有机会,用户将搞砸了。
出于这个原因,您最好的朋友是HTML5输入类型,具体为date
和time
。还有其他像datetime
,datetime-local
等,但这些在当前任何浏览器中都不受支持,实际上有被HTML5规范弃用的危险。几乎每个现代浏览器现在都支持某种形式的“日期”控制和“时间”控制(单独),即使它不受支持,用户仍然可以更容易地输入离散单位,如“日期”值和“时间” “正确值,而不是一个”datetime“值。
基于所有这些,我建议您通过以下方式更改视图模型:
[DataType(DataType.Time)]
public TimeSpan TimeIn { get; set; }
[DataType(DataType.Date)]
public DateTime DateIn { get; set; }
public string TimeZoneIn { get; set; }
[DataType(DataType.Time)]
public TimeSpan TimeOut { get; set; }
[DataType(DataType.Date)]
public DateTime DateOut { get; set; }
public string TimeZoneOut { get; set; }
然后,您可以添加一些辅助属性,如:
public DateTimeOffset InUtc =>
TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateIn, TimeZoneIn).Add(TimeIn).ToUniversalTime();
public DateTimeOffset OutUtc =>
TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateOut, TimeZoneOut).Add(TimeOut).ToUniversalTime();
另一件事。虽然您以UTC格式存储(也许尤其是因为您以UTC格式存储),但您仍需要至少保留时区部分,以便稍后转换回该时区。还应注意,如果您使用SQL Server作为持久性存储,DateTimeOffset
将转换为DATETIMEOFFSET
列类型,可以对时区部分进行编码。在这种情况下,无需转换为UTC,因为无论是以用户的本地时间,UTC还是其他方式存储,您都可以随时访问所需的任何时区。但是,任何其他数据库都只需要UTC日期时间,所以它确实会让你陷入困境。