在LocalTime

时间:2017-09-28 17:58:07

标签: c# asp.net-mvc

我正在制作一个时钟'网络应用。但是,我无法让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>

任何帮助将不胜感激,如果您有任何其他希望帮助解决问题,请告诉我。谢谢!

2 个答案:

答案 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输入类型,具体为datetime。还有其他像datetimedatetime-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日期时间,所以它确实会让你陷入困境。