Moment.js - 显示选定范围内关于用户时区的历史数据

Posted

技术标签:

【中文标题】Moment.js - 显示选定范围内关于用户时区的历史数据【英文标题】:Moment.js - Displaying historical data from selected range with regard of user timezone 【发布时间】:2017-09-14 23:25:38 【问题描述】:

我真的对正确显示历史数据感到困惑:

我有什么:

以“YYYY-MM-DD HH:mm:ss”格式和UTC+0(MariaDB - DateTime 类型)存储的数据库记录 Web 应用程序(使用 moment.js),允许用户选择两个日期之间的范围(不包括时间部分)

我需要什么:

要从选定范围内获取记录,但要考虑当前用户的时区(例如,他只选择 3 月 23 日的记录:在 DB 中,我有 3 月 22 日的记录,但在用户本地时区它已经3 月 23 日,所以如果我没记错的话,他也需要看看那张唱片) 正确处理 DST 废话 在结果记录中以正确的用户本地时间显示日期(就像过去那个时刻一样)

我希望得到某种指南,向我解释我必须采取哪些步骤来实现所有这些。谢谢!

【问题讨论】:

您需要提供您正在使用的内容的基础。最低限度,从和到日期字段、您使用的日期格式和预期结果。见How to create a minimal, complete and verifiable example 【参考方案1】:

在客户端代码中定义两个变量:

var startTime = moment().startOf('day').utc().format();
var untilTime = moment().add(1, 'day').startOf('day').utc().format();

您现在有了 UTC 格式的查询范围。通过表单发布或您拥有的任何机制将它们发送到服务器,然后运行查询。

查询时,使用半开范围:recordTime >= startTime AND recordTime < untilTime

当您将结果返回给客户端时,您将获得 UTC 格式的结果,因此请转换为本地时间,如下所示:

moment.utc(theData).local().format()

根据需要调整输入/输出格式。

【讨论】:

谢谢,但是像这样的情况呢: 1. 数据库上的记录日期为“2016-06-06 23:00:00”。 2. 当该事件发生时,在用户本地时间(比如说 utc+2)已经是 6 月 7 日 - “2016-06-07 01:00:00”。因此,在选择查看该记录的日期时,他会选择 2016-06-07,而不是 2016-06-06,并且该记录不会显示...我知道我可以添加或减去特定的偏移量,具体取决于用户时区,在查询记录之前,但是 DST 呢?那我怎么知道要选择什么偏移量呢? 我提供的代码已经可以处理这个问题。当您在客户端运行 moment() 时,您正在本地模式下工作,包括任何可能生效的时区偏移和 DST。您以当地时间计算当天的范围,然后将其转换为 UTC。在服务器端,您必须进行范围查询。在您给出的示例中,范围将从2016-06-07 00:00:002016-06-08 00:00:00 本地时间,从2016-06-06 23:00:002016-06-07 23:00:00 UTC。它必须是一个范围查询。您无法按日历日期检查是否完全相等。【参考方案2】:

下一次,存储到TIMESTAMP 而不是DATETIME

TIMESTAMP根据客户端的时区将要插入的日期+时间转换为UTC进行存储。随后的SELECT 会根据读者的时区重新转换。

这样,实现目标不需要任何代码(我认为)。

【讨论】:

这无济于事,因为时区是 Web 浏览器另一端用户的时区,而不是连接到数据库的用户帐户。 TIMESTAMP 可能仍然是一个不错的选择,只是 UTC 和会话时区之间的转换无济于事,除非相应地设置会话时区,并且从用户那里获取它可以是一种痛苦。 如果您想在存储日期时间时冻结 TZ,请使用DATETIME。 (将DATETIME 视为本地时钟的图片。)现在我不明白原来的问题。

以上是关于Moment.js - 显示选定范围内关于用户时区的历史数据的主要内容,如果未能解决你的问题,请参考以下文章

使用moment.js解析时如何忽略时区

如何使用moment-timezone.js获取客户端时区

JavaScript、时区和夏令时

在php中获取用户当前时区[重复]

如何使用 Moment JS 计算范围之间的给定工作日数?

moment.js 是单例吗?