2016-03-03 98 views
0

我有一个问题让我的头根据日期(没有时间)存储和检索信息并处理多个时区。处理时区和日期

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

我的问题是这样的:

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

应用程序使用UTC,我的用户是在悉尼,所以我要做的就是加载窗体时我预填充基础的jS M Y澳大利亚/悉尼时区的日期字段,这样它显示为今天他。迄今为止都很好。

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

当它被再次拉出时,它对它们显示正常,但是如果我做了一个报告“今天发布了多少新闻项目?”,在我的报告(cron作业)中它可能正在寻找不同的日期,因为如果这个人在清晨进入,那么悉尼2016年3月3日仍然是UTC的2016年3月2日,因此今天会有0。

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

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

所以..我不知道如何解决这个他们无需同时输入一个时间,这似乎多余的。

回答

0

请务必记住,各国之间的储蓄时间规则各不相同,例如美国和欧盟。不仅仅是当时钟改变时,而是跨时区变化的时间。

在过去我强制当地时间12:00(中午)。使用时间值可以使用标准转换例程。选择中午让任何事情远离任何午夜和储蓄时间问题,因为任何一个小时的差错将仍然在同一天。

0

最简单的方法是始终使用全面UTC时间戳进行操作。

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

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

然后,按照创建的顺序排列文章(无论他们的作者发布在哪里)变得微不足道。计算在过去24小时内或在特定日期(例如:七天前)添加了多少文章也很容易 - 请注意这些示例不需要日期,只需几秒钟。

当“用户B”添加相对于用户A的时区的文章时,这还可以很容易地显示“用户A” - 您无需查找用户B的时区进行转换。

另外,给你的用户选择添加时间到他们的文章,但不要强制它。有一个明智的默认(理想情况下是一个动态的“现在”)。这是更自然的,并应建立报告时,消除吉尔伯特强调的午夜和DST异常。

+0

请小心绝对。任何时候你发现自己说*总是*,记住总有*规则的例外。在这种情况下,“始终使用UTC”的建议已经在互联网周围传播得如此之多以至于人们盲目追踪并经常遇到陷阱。确实存在UTC以外的时间更适合(或甚至需要)的情况。一个很好的例子是[* scheduling *](http://stackoverflow.com/a/19627330/634824)。你的其他观点是有效的 - 但请注意这一点。谢谢。 –

+0

谢谢马特。在任何情况下,我都遇到过多个时区是一个因素,UTC和时间戳是一个很好的方法,节省了很多痛苦。但是,我完全同意你的意思。 – CoderCreative

+0

@CoderCreative当用户在日历上选择2016年3月3日时,您会如何建议我将其转换为UTC时间戳?如果他们从一个月前选择了一个数据,例如2016年2月14日,那么该数据会变得微不足道。当您包含时间时,它会变得微不足道...... – Wizzard

0

它实际上听起来像你正在做的事情已经正确。

“今日”和“日期”的概念是压延概念,涵盖的域为民事时间。您可以使用打印的日历在世界各地飞行,而且您无需为UTC或时区调整它。日期本身不能以“UTC”。

但是,您可以说在的绝对时间的域中,时区A中的日期不涵盖时区B覆盖的相同瞬时时刻。在任何给定时间,都可以是地球上两种不同的“今天”。

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

当然,您的发布日期是该项目发布的民事日期。当您查询“今天”发布的所有商品时,这是基于您询问时所在的公民日期。

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

一个有助于的思维练习:如果用户在UTC时间23:59发帖并且一分钟后运行查询,应该怎么做?它是否应该包括结果 - 或者不?如果当地时间是23:59,您的答案是否会更改,并且您在一分钟后在同一时区运行查询?仔细考虑这一点将有助于您确定实际存储和查询的内容。

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