title: Ruby/Rails how to iterate months over a DateTime range?
body: <p>I am trying to build a graph from data in a Rails table: The amount of sold products per time-fragment.</p>
  
  <p>Because the graph should be able to show the last hour(in 1-minute steps), the last day (in 1-hour steps), the last week (in 1-day steps), the last month (in 1-day steps), etc, I am trying to reduce the code duplication by iterating over a range of DateTime objects:</p>
  
  <pre><code># To prevent code-duplication, iterate over different time ranges.
  times = {
      :hour=&gt;{newer_than: 1.hour.ago, timestep: :minute},
      :day=&gt;{newer_than: 1.day.ago, timestep: :hour},
      :week=&gt;{newer_than: 1.week.ago, , timestep: :day},
      :month=&gt;{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_" &lt;&lt; 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 &gt;= 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
  </code></pre>
  
  <p>This code works great for all time-intervals that have a constant size (hour,day,week). For months, however, it uses a step_ratio of 30 days: <code>1.month / 1.day == 30</code>. Obviously, the amount of days that months has is not constant. In my script, this has the result that a month might be 'skipped' and therefore missing from the graph.</p>
  
  <p>How can this problem be solved? How to iterate over months while keeping the different amount of days in the months in mind?</p>