【问题标题】:timezones and doing analytics on tables时区和对表进行分析
【发布时间】:2015-05-05 17:33:40
【问题描述】:

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

我所做的是在我的应用中注册了一个新用户。我当前的时间是格林威治标准时间 5 点(3 月 3 日)晚上 10 点,并且该用户的 created_at 时间已保存到数据库中的世界标准时间凌晨 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 日注册的。

我的问题是: 我应该如何调用 where 函数并按 created_at 列分组,以便正确影响日期(根据我的时区)?

或者还有其他我应该做的不同的事情吗?

【问题讨论】:

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


    【解决方案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 都支持时区。

    【讨论】:

      【解决方案2】:

      Date.todaywill 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 日期
      在您当前的时区显示它

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-19
        • 2013-10-08
        • 1970-01-01
        相关资源
        最近更新 更多