【问题标题】:Letting users choose timezone for scheduling system: Problem with returning today on server让用户为调度系统选择时区:今天在服务器上返回的问题
【发布时间】:2021-05-10 16:02:35
【问题描述】:

我在节点(客户端和服务器 API)中创建的调度系统有问题。我的服务器是 UTC。

由于我希望我的时区与用户所在的任何地方保持一致,因此我根据用户提供的公司地址向用户建议了一个时区。目的是让用户能够从世界任何地方查看他们的日程安排详细信息,并且仍然可以看到相同的日期。例如。用户业务位于英国,他们安排在晚上 8 点进行预订。然后用户去亚洲度假,登录系统,仍然看到指定为晚上 8 点的预订,并且可以使用日历安排更多预订,然后可以在英国查看在国外时指定的日期。

到目前为止,这一直运行良好。我在注册时针对用户保存用户时区。我将日期存储在 postgres 数据库中没有时区。从数据库中检索时,我正在使用

date = moment(fetcheddate).tz(usertimezone, true);

当我在服务器/客户端边界工作时(并且期待一个时区),我正在使用:

date = moment(receiveddate).tz(usertimezone);

这可确保所有日期在使用时始终处于业务时区,明确目标是所有日期始终作为时刻对象读取,时间始终设置为 00:00:00。

在服务器上,我的业务逻辑大量使用 Moment 加/减; isSame/isBefore/isAfter 来生成该调度系统内部工作的新日期。

现在的问题。有时,我需要知道今天是什么日子。例如。在服务器上,我通过结束当前保存的大宗预订、设置为“昨天”并从“今天”开始新的大宗预订来更改大宗预订。 .

更详细地查看“更改块预订”场景:在服务器上,我通过调用 moment 生成“今天”,并转换为业务时区,使用 moment startOf('day') 删除时间信息。

今天 = moment().tz(usertimezone).startOf('day');

然后,我将我的新 blockbooking 对象的 startdate 设置为今天的值。

现在,如果用户与业务时区位于同一时区,那么这将完美运行。但是,如果他们当时在不同时区的国外工作,那么我会遇到问题,即我的开始日是外出的一天。

例如,我当前的预订保存信息的开始日期可能是“2021-02-06 00:00:00”。我选择在同一天(2 月 6 日)在国外更改此预订。我希望我的新开始日期也等于 6 号。但是,使用 today = moment().tz(usertimezone).startOf('day') 会导致我将 2 月 5 日作为我的新开始日期,这是一天。

我不能仅仅依靠使用 moment() 来获取正确的日期,因为服务器是 UTC。我能想到的唯一解决方案是使用

从客户端传递浏览器时区
moment.tz.guess(); 

但我不确定我是否可以完全相信这种完整功能的调用,因为似乎可能存在许多错误。例如。 Return timezone name with Moment's guess().

我确信必须有一个我没有想到的解决方案。也许我选择使用业务时区来同步日期时间是一个问题。我认为在服务器边界传递没有时区的日期将适用于大多数功能,并且可能会简化事情,尽管我不确定。但我想我仍然遇到在 UTC 服务器上生成“今天”日期的问题。

有人对此有任何想法吗?我错过了什么?

更新:根据要求,我的主要问题是如何在服务器中获取“今天”的日期值,使其等于浏览器中的“今天”。然后必须将服务器中的“今天”日期与设置为用户业务时区的日期进行比较。或者,如果您有绕过此问题的替代实现,那么这也是可以接受的

【问题讨论】:

  • 抱歉我的冗长问题。我看看能不能调整我本质上是想问,“当服务器在 UTC 并且用户在国外,并且他们当前的时区与他们存储的业务时区不同时,我如何才能从服务器获得今天的准确表示”关于以 UTC 存储所有内容,我的理解是在安排未来的约会时,您应该在将日期保存到数据库时省略时区信息。这有助于夏令时。
  • 我开始怀疑解决方案是否是在客户端生成“今天”,并在没有时区信息的请求中传递这个,然后在服务器上添加业务时区信息......

标签: javascript node.js date timezone momentjs


【解决方案1】:

当用户来自不同时区时如何设计?

  1. 在您的数据库中以 UTC 格式存储日期时间。
  2. 用户注册后,当他们登录到您的 Web 应用程序时,要求他们选择一个时区。这可以是他们用户帐户的个人资料页面的一部分。将此时区存储在每个用户的数据库中。
  3. 在 UTC 时区与其他服务通信,例如网络应用程序。

示例 1:

用户通过个人资料选择 UTC-8 作为他的时区。而且,他正在预订 03-Feb-2021 20:00:00(显然是他的时区)。现在,Web 应用程序将通过 API 作为 04-Feb-2021 04:00:00 发送/通信,并且非常简单,后端将按原样存储它 - 04-Feb-2021 04:00:00.

现在,假设用户注销并重新登录并检查他的日历,现在 Web 应用程序将再次调用 HTTP API 以获取该预订,并且后端将响应预订日期为 04-Feb-2021 04 :00:00.

现在,Web 应用程序的工作是找出(从配置文件数据,例如存储在浏览器本地存储或会话存储中)用户选择的 UTC-8 时区并进行转换并显示用户重新预订为 - 03-Feb-2021 20:00:00


示例 2:

用户预订了一个网络研讨会(我们来看这个例子),该研讨会将于 2021 年 2 月 15 日 14:00:00 开始 UTC+8 中的强>。预订是使用网络应用程序完成的,因此网络应用程序将事件开始时间发送为 15-Feb-2021 06:00:00,该时间存储在 数据库 中。 p>

现在用户旅行到一个新的时区,比如说,UTC+10,并使用保存在 profile 部分更新他的时区数据库

更新他的时区后,他检查了自己的日程安排,网络应用程序(转换后)告诉他活动将于 2021 年 2 月 15 日 16:00:00 开始,这对于用户来说是正确

因为在现实世界中,网络研讨会将从 - 2021 年 2 月 15 日 06:00:00 UTC == 2021 年 2 月 15 日 14:00:00 UTC+8 == 2021 年 2 月 15 日16:00:00 UTC+10

因此,没有人会错过这次网络研讨会,居住在 UTC 的人们、居住在 UTC+8 的人们以及居住在 UTC+10 将在同一时间参加


案例 3,本地事件

在创建事件时,让用户选择/标记一个事件为本地事件,当他们这样做时,存储事件详细信息,UTC 日期时间事件的时区 ID 在数据库中对照表中的每个事件记录。

要在网络应用中显示此事件,您需要将事件的UTC日期时间事件的时区详细信息发送到前端。而且,无论用户将来是否前往不同的时区,前端始终可以在事件所在的时区显示事件。

【讨论】:

  • 我需要考虑一下。在一种情况下,如果一个位置更改了它的 IANA 时区(不确定这有多大可能),并且用户相应地更新了他们的时区,那么存储 UTC 将导致向用户显示不同的日期以用于未来的相关日期。例如。如果原始时区是 +8 而新的新时区是 +10,那么由于存储在 UTC 中,日期现在在一天中的某个时间点可能会有所不同。
  • 如果 IANA 时区发生变化,那么他们所有的块预订(重复事件)现在都在错误的时间,他们需要全部更改或删除它们并重新开始。因为早上 8 点的约会总是早上 8 点的约会。我应该补充一点,这是一个基于业务地址的物理服务调度系统。 IE。不是虚拟的。但是,我确实同意这是一个非常不寻常的边缘情况,即使发生也不太可能经常发生
  • 是的,这是个问题。还有查看发票历史数据的问题。您需要知道每个约会/预约预约的时区。使用我当前的设置,我只需要将时区信息与本地日期一起存储,并在 db 请求上绑定值,然后在客户端再次绑定。您可以使用时区条目上的日期来执行此操作,但这开始变得混乱。
  • 这是一篇关于整个过程的不错的文章。虽然我希望他能正确地参加经常性事件。 codeblog.jonskeet.uk/2019/03/27/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-08
  • 1970-01-01
相关资源
最近更新 更多