首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ruby/Rails如何在DateTime范围内迭代数月?

Ruby/Rails如何在DateTime范围内迭代数月?
EN

Stack Overflow用户
提问于 2015-08-04 20:32:54
回答 2查看 2.3K关注 0票数 3

我试图从Rails表中的数据构建一个图表:每个时间片段的产品销售量。

由于图表应该能够显示最后一个小时(1分钟步骤)、最后一天(1小时步骤)、最后一周(1天步骤)、最后一个月(1天步骤)等,所以我试图通过对一系列DateTime对象进行迭代来减少代码重复:

代码语言:javascript
复制
# To prevent code-duplication, iterate over different time ranges.
times = {
    :hour=>{newer_than: 1.hour.ago, timestep: :minute},
    :day=>{newer_than: 1.day.ago, timestep: :hour},
    :week=>{newer_than: 1.week.ago, , timestep: :day},
    :month=>{newer_than: 1.week.ago, , timestep: :day}
}


products = Product.all

# Create symbols `:beginning_of_minute`, `:beginning_of_hour`, etc. These are used to group products and timestamps by.
times.each do|name, t| 
  t[:beginning_of] = ("beginning_of_" << t[:timestep].to_s).to_sym 
end 

graphs = times.map do |name, t|
   graphpoints = {}
   seconds_in_a_day = 1.day.to_f
   step_ratio = 1.send(t[:timestep]).ago.to_f / seconds_in_a_day
   time_enum = 1.send(t[:timestep]).ago.to_datetime.step(DateTime.now, step_ratio)
   time_enum.each do |timestep|
       graphpoints[time_moment.send(timehash[:beginning_of]).to_datetime] = []
   end

   # Load all products that are visible in this graph size
   visible_products = products.select {|p| p.created_at >= t.newer_than}
   # Group them per graph point
   grouped_products = visible_products.group_by {|item| item.created_at.send(timehash[:beginning_of]).to_datetime}

   graphpoints.merge!(grouped_products)

   {
      points: graphpoints,
      labels: graphpoints.keys
   }
end

此代码适用于所有具有固定大小(小时、日、周)的时间间隔。然而,几个月来,它使用的是30天的step_ratio:1.month / 1.day == 30。很明显,几个月的天数不是固定不变的。在我的脚本中,结果是一个月可能被“跳过”,因此从图中丢失。

如何解决这个问题呢?如何在几个月内反复迭代,同时记住月份中的不同天数?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-04 21:09:03

使用群日期宝石。例如(从文档中修改的示例):

代码语言:javascript
复制
visible_products = Product.where("created_at > ?", 1.week.ago).group_by_day

# {
#   2015-07-29 00:00:00 UTC => 50,
#   2013-07-30 00:00:00 UTC => 100,
#   2013-08-02 00:00:00 UTC => 34
# }

而且,这要快得多,因为您的分组/计数将由数据库本身完成,无需通过Product.all调用将所有记录传递给Rails代码,也不需要为每个记录创建ActiveRecord对象(甚至不相关)。

票数 2
EN

Stack Overflow用户

发布于 2016-12-05 06:41:51

如果您必须选择一个巨大数组的月份,只需在两个日期:类之间设置范围。

代码语言:javascript
复制
(1.year.ago.to_date..DateTime.now.to_date)).select{|date| date.day==1}.each do |date|
  p date
end
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31818781

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档