问题:Rails - 使用相同属性名称按日期分组返回不同的答案

date_start = Time.parse('11/08/2015').beginning_of_day
date_end = Time.parse('11/08/2015').end_of_day

created_at_day_tz = "date(created_at AT TIME ZONE \'UTC\'
                     AT TIME ZONE \'#{Time.zone.tzinfo.identifier}\')"

users = User.where("users.created_at BETWEEN ? AND ?", date_start, date_end)

按 created_at as created_at__ 天分组(仅限日期,分组属性的新名称)

grouped_with_timezone_day = users.group(created_at_day_tz).
  order(created_at_day_tz).
  select("#{created_at_day_tz} as created_at_day, count(*) as count")
# grouped_with_timezone_day.map {|u| [u.created_at_day, u.count] }
# => [[Tue, 11 Aug 2015, 186]]

按 created_at 分组为 created_at(仅限日期,分组属性的名称相同)

grouped_with_timezone = users.group(created_at_day_tz).
  order(created_at_day_tz).
  select("#{created_at_day_tz} as created_at, count(*) as count")
# grouped_with_timezone.map {|u| [u.created_at, u.count] }
# => [[Mon, 10 Aug 2015 21:00:00 BRT -03:00, 186]]

如果记录相同,为什么结果会不同?为什么一个结果带有时区,如 DateTime,而另一个结果只带有 Date?

activerecord 'casting' 到 DateTime with Timezone 因为 created_at 是这样定义的(顺便说一句,这使得日期在这种情况下不正确)?

解答

时间戳不正确 - 也就是说,它是 2015 年 8 月 11 日午夜 UTC - 它只是在您的当地时间显示。

对于created_atupdated_at,Rails 有一点特殊行为:

timestamps macro增加了两列,created_atupdated_at。如果这些特殊列存在,则由 Active Record 自动管理。

它总是将从查询返回的created_at视为时间戳。您的查询仅返回日期2015-08-11,它被解释为午夜。打印时,时间戳会显示在您所在地区的时区(我认为必须是-03:00),导致 11 日午夜前 3 小时。

当您将结果命名为created_at_day时,您可以避免 Rails 将其转换为时间戳并获得您期望的日期。

Logo

PostgreSQL社区为您提供最前沿的新闻资讯和知识内容

更多推荐