处理时区和日期

时间:2016-03-03 03:12:01

标签: php mysql date datetime

我遇到了一个问题,就是根据日期(没时间)存储和检索信息并处理多个时区。

默认情况下,我的应用程序使用UTC,因此创建/更新时间都是UTC,而日期等PHP函数都使用UTC。

我的问题是:

我允许用户创建新闻项目,新闻项目有一个日期(没有时间,只有日期)。

应用程序使用UTC,我的用户在悉尼,所以我做的是在表单加载时我为澳大利亚/悉尼时区预先填充基于var r = new XMLHttpRequest(); r.open("POST", "path/to/api", true); r.onreadystatechange = function () { if (r.readyState != 4 || r.status != 200) return; alert("Success: " + r.responseText); }; r.send("banana=yellow"); 的日期字段这种方式今天就像他一样。到目前为止一切都很好。

当我将记录保存到数据库中(进入DATE字段)时,我使用他们输入的日期,如果他们说2016年3月3日,那么它将进入2016-03-03。

当它再次被拔出时,它显示对他们来说很好,但如果我做一个报告说"今天发布了多少新闻?",在我的报告(cron job)中它可能正在寻找另一个日期,因为如果这个人在清晨进入,那么2016年3月3日悉尼仍将是2016年3月2日的UTC,所以今天将会有0个。

它出现的解决方案是在存储时将日期转换回UTC,但是如何工作?...因为它只是一个没有时间的日期。

2016年3月2日00:00:00 UTC将于2016年3月2日10:00:00悉尼

所以..我不知道怎么解决这个问题,如果他们不必再输入时间,这似乎是多余的。

3 个答案:

答案 0 :(得分:0)

永远记住,储蓄时间规则因国家/地区而异,例如美国和欧盟。不仅时钟发生变化,而且时区变化的时间也不同。

过去我强迫当地时间12:00(中午)。使用时间值,可以使用标准转换例程。选择中午使得一切都远离任何午夜和储蓄时间问题,因为任何一个小时的滑动仍然会在同一天。

答案 1 :(得分:0)

最简单的方法是始终使用完整的UTC时间戳。

将传入日期直接转换为这些日期,并且在呈现时仅转换回可读的本地化格式。

这样你就有了一个坚实的参考点。数据库中的所有内容都在创建时准确记录(相对于1970年1月1日 - UTC)。

然后按创作顺序排列文章变得微不足道(无论作者从哪里发布)。计算过去24小时或特定日期(例如;七天前)添加了多少篇文章也更加容易 - 请注意这些示例如何不需要约会,只需秒数范围。

这也可以很容易地显示用户A"当"用户B"添加了一篇相对于用户A的时区的文章 - 您不需要查找用户B的时区来进行转换。

此外,为您的用户提供为文章添加时间的选项,但不要强制要求。有明智的默认(理想情况下是动态"现在")。这是更自然的,在构建报告时,应该能够消除吉尔伯特强调的午夜和夏令时异常。

答案 2 :(得分:0)

实际上听起来你已经正确地做事了。

"今天"的概念和"日期"是民间时间所涵盖的压延概念。您可以使用打印的日历在世界各地飞行,并且您不需要为UTC或时区调整它。在UTC"。

中,日期本身不能是"

但是,您可以说在绝对时间的域中,时区A中的日期不包括时区B所涵盖的相同瞬时时刻。时间,可能有两个不同的"今天"对地球有效。

从悉尼用户的角度来看,3月3日是发布日期。您可能会在3月2日在夏威夷同时发布另一位用户。

当然,您的过帐日期是项目过帐的民用日期。当您查询所发布的所有项目时,#34;今天",这是根据您在问的任何地方的民事日期。

如果这不是所需的行为,那么更改问题。而不是询问"今天发布的内容",请问"过去24小时内发布了什么?"为此,您确实需要存储帖子的完整的基于UTC的日期和时间(而不仅仅是日期)。那么你将从现在开始以不到24小时的UTC时间查询它。

一个有用的思考练习:如果用户在UTC时间23:59发布,你会怎么做,并在一分钟后运行查询?它应该包括结果 - 或不?如果当地时间23:59你的答案改变了,并且你在一分钟后在同一时区运行查询?通过思考将帮助您确定实际存储和查询的内容。

我还要说,在大多数情况下,您确实应该存储基于UTC的时间戳,但您可能希望将本地日期(或日期时间)存储在单独的字段中。这使您能够执行两种类型的查询。