在Rails中查询日期范围

10

我有一个作用域(scope),可以查询今天的通话记录。根据这个作用域,我可以计算今天通话的数量。

我的日期是以UTC格式存储的,但Rails会转换成我所在地的时区。我想做的是找到今天00:00到23:59之间的所有通话记录。

作用域:

scope :today, where("DATE(transfer_date) BETWEEN ? AND ?", Time.zone.now.utc.beginning_of_day, Time.zone.now.utc.end_of_day)

irb输出:(由于UTC而捕获的调用)

irb(main):010:0> Call.last.transfer_date
  Call Load (0.9ms)  SELECT "calls".* FROM "calls" ORDER BY "calls"."id" DESC LIMIT 1
=> Sun, 07 Oct 2012 19:45:00 CDT -05:00
irb(main):011:0> 

irb(main):011:0> Call.last.transfer_date.utc
  Call Load (1.3ms)  SELECT "calls".* FROM "calls" ORDER BY "calls"."id" DESC LIMIT 1
=> 2012-10-08 00:45:00 UTC

我正在尝试找出如何查询今天00:00到23:59之间的通话记录。迄今为止,尝试使用和不使用UTC、区域等作用域都不起作用。它继续基于UTC拉取范围,这包括昨天的通话记录(如果使用本地时区格式化,则是昨天)。

我该如何在这两个时间之间查询以获得正确的输出?我有点迷失在这里。


请问您能否把问题表述清楚一些?这意味着您给定了哪个模型的范围,并且在底部您没有写明今天的范围。 - Paritosh Singh
3个回答

19
您可以使用一个独占范围。
scope :today, where(:transfer_date => Date.today...Date.tomorrow)

在SQL中,A..B将触发BETWEEN操作符,它是包含的(包括范围边界值A和B)。 SELECT "calls".* FROM "calls" WHERE "calls"."transfer_date" BETWEEN $1 AND $2。A..B将触发类似于transfer_rate >= today AND transfer_rate <= tomorrow的操作,同样是包含的。 - Žarko Milošević

7

我通过以下方式重写了我的作用域,以弥补UTC时间差:

scope :today, where("transfer_date BETWEEN ? AND ?", Time.zone.now.beginning_of_day, Time.zone.now.end_of_day)

0
也许这有点过度,但我建议使用一个获取时间范围并查询数据库的帮助方法。例如:
# Gets time range for x number timeunits ago
  def time_range(unit, timeunit = nil)
    if timeunit == "weeks"
      now = Time.zone.now.beginning_of_week
    elsif timeunit == "months"
      now = Time.zone.now.beginning_of_month
    else
      now = Time.zone.now.beginning_of_day
    end
    # Ex: time_range(0, "days") --> Get the time range for today  between the beginning of today and the beginning of tommorow - 1 second
    now - unit.send(timeunit)..now + 1.send(timeunit) - 1.seconds - unit.send(timeunit)
  end

将帮助您请求时间范围。因此,当您请求类似以下内容时;

time_range(0, "days")

它将返回0天前(今天)的时间范围;

Wed, 07 Sep 2016 00:00:00 UTC +00:00..Wed, 07 Sep 2016 23:59:59 UTC +00:00

然后你只需要查询数据库对象,并使用以下语句计算范围内的所有内容:

Calls.where(transfer_date: time_range(unit, timeunit)).count

这很好,感谢你的示例,但是我几年前最终选择了一个简单的lambda作用域 :) - nulltek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接