这种奇怪的行为最近引起了我的注意,当我在本地环境中测试我的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列调用函数和组的位置,以便正确影响日期(根据我的时区)?
或者我还应该采取其他不同的做法吗?
答案 0 :(得分:1)
我不是rubyist,所以我会让别人给出具体的代码,但我可以从一般的算法角度来回答。
如果您将UTC存储在数据库中,则还需要按UTC查询。
在确定查询范围(from
和to
)时,您需要知道当地时区“今天”的开始和停止时间,并将每个时间转换为到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日期
在你当前的时区显示它