使用 nodatime 将时区传递到 Web api 调用中

Passing a time zone into a web api call from moment with nodatime

我快要疯狂处理日期时间问题和网络了。

我在中央时区托管了一个 Web 服务器。当东部时区的客户尝试使用我的应用程序在给定的一天安排一个项目时,他们传递了(例如)3/14/2015 的值。当我们将代码传回发送到网络的模型时 api,我们坚持使用类似下面的代码。

moment.utc($("#mydatepicker").val).hour(0).minute(0).second(0)).toISOString();

这会产生如下字符串:

2015-03-14T04:00:00.000Z

当项目在 Web api 的服务器上转换回时,它会转换为

3/13/2015 11:00:00 PM

逻辑然后剥离时间,您可以从这里看到发生了什么。由于我去掉了时间,现在是前一天,这是保存到数据库中的值。

我需要知道一些方法来将值从时刻发送到网络 api 最好作为客户端时区中的 ZonedDateTime。然后我可以将它转换为 UTC 以便在数据库中持久化。

我看过一些关于使用 NodaTime.Serialization.JsonNet 的事情,但我不清楚如何将它与 Moment 一起使用并在网络上来回传递它 api/ajax。

我首先将所有日期和时间作为 UTC 时间发送到服务器。如果您只存储 UTC 时间,那么您应该能够显示在客户端安排的正确时间。

当您在客户端创建您的时刻时,您是否先 运行 将其发送到服务器端之前将其输出 .toDate() ?您 运行 在服务器端使用什么代码?它是 .Net WebApi 吗?

I need to know some way to send a value from moment, into the web api preferrably as a ZonedDateTime in the client's time zone. I can then convert it to UTC for persistance in the DB.

如果这是你想要的,那么:

  • 在您的 moment.js 代码中,使用 .format() 而不是 .toISOString(),这仍然会给您一个 ISO8601 字符串,但会包含本地偏移量而不是将其设置为 UTC。

  • 在您的 ASP.Net 代码中,将您的值定义为 DateTimeOffset(或 noda OffsetDateTime)而不是 DateTime

但是,我不认为那真的是你想要的。对于日期和时间,context 非常重要。在这里,你说你正在从日期选择器中选择一个日期。当你这样做时 - 用户选择什么时间?在大多数情况下,他们不会选择时间——他们只是在选择日期。但是由于 JavaScript Date 对象实际上是一个 "date + time" 对象,它指定午夜作为默认时间。 Moment在这方面也好不到哪里去。

真的,当您只是谈论日历日期时,转换为 UTC 没有逻辑意义。您 可能 应该通过网络发送的字符串值应该只是一个完整的日期,如 "2015-03-14" 中那样。我的猜测是,无论如何,这就是您要开始的。如果没有,则执行 moment.utc(yourvalue).format("YYYY-MM-DD") 以获取它。 (此处使用 UTC 只是避免当地时区问题的一种方式,例如巴西在 spring 之后的一天不存在午夜。)

这对应于您的 .NET 代码中的 NodaTime LocalDate 类型。如果您不使用 Noda Time,您可以将类型定义为 DateTime 并忽略时间部分。在您的数据库中,如果有可用的日期类型,则使用它。例如,SQL 服务器具有 date 类型。

我还鼓励您观看我的 Pluralsight 课程,Date and Time Fundamentals - 其中涵盖了其中的许多问题。

关于在 WebAPI 中使用 NodaTime.Serialization.JsonNet(因此您可以直接使用 LocalDate),在您的 WebApiConfig.cs 文件中,像这样连接它:

config.Formatters.JsonFormatter.SerializerSettings
                 .ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);

那么应该就可以了。