时区和对表进行分析

时间:2015-03-04 16:15:23

标签: ruby-on-rails-4 activerecord timezone

这种奇怪的行为最近引起了我的注意,当我在本地环境中测试我的Rails应用程序时,我使用around_filter将时区设置为注册用户(默认时区为UTC)。

我做的是我在我的应用中注册了一个新用户。我目前的时间是GMT-5(3月3日)晚上10点,这个用户的created_at时间被保存到数据库到UTC时间凌晨4点(3月4日)。现在,我知道这个时间是用时区设置保存在数据库中的,但问题出现了:

我使用图表来显示每日注册用户的可视化,当我调用以下函数告诉我过去几天注册的用户数量时:

from ||= Date.today - 1.month
to ||= Date.today
where(created_at: from..to).group('DATE(created_at)').count

可以说这个用户是在3月4日注册的,而事实上它是从我的角度在3月3日注册的。

我的问题是: 我应该如何通过created_at列调用函数和组的位置,以便正确影响日期(根据我的时区)?

或者我还应该采取其他不同的做法吗?

2 个答案:

答案 0 :(得分:1)

我不是rubyist,所以我会让别人给出具体的代码,但我可以从一般的算法角度来回答。

如果您将UTC存储在数据库中,则还需要按UTC查询。

在确定查询范围(fromto)时,您需要知道当地时区“今天”的开始和停止时间,并将每个时间转换为到UTC。

例如,我在美国太平洋时区,今天是2015年3月7日。

from: 2015-03-07T00:00:00-08:00  =  2015-03-07T08:00:00Z
  to: 2015-03-08T00:00:00-08:00  =  2015-03-08T08:00:00Z

如果你想减去你在示例中显示的月份,请在之前转换为UTC。并注意夏令时。无法保证偏移量不变。

此外,您还需要使用排除上限的半开区间范围。我相信Ruby,这是用三个点(...)代替两个(至少根据this)。

分组通常有点困难。我假设这是对数据库的查询,对吧?好吧,如果您要查询的数据库具有时区支持,那么您可以使用它在分组之前将日期转换为您的时区。像这样的东西(伪代码):

groupby(DATE(CONVERT_TZ(created_at,'UTC','America/Los_Angeles')))

由于你没有说明你正在使用什么数据库,我不能更具体。 CONVERT_TZ可用于MySQL,我相信Oracle和Postgres也都有时区支持。

答案 1 :(得分:1)

Date.today will default to your system's set timezone(顺便说一下,它应该始终是UTC,here's why)所以如果你想使用UTC,只要在rails设置为UTC时执行Time.zone.now.to_date

否则你应该

Time.use_zone('UTC') do
  Time.zone.now.to_date
end

在此之后,您应该通过执行object.created_at.in_time_zone('EST')
来显示created_at日期 在你当前的时区显示它