如何分组,计算和映射日期范围? [关闭]

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何分组,计算和映射日期范围? [关闭]相关的知识,希望对你有一定的参考价值。

我正在制定一个预订模型,可以在任意时间段内租用物品,每个物品每天最大预订量(基本上是物品的数量)。显然,我想检查一个项目是否可用于预订,或者是否在预订之前已达到最大容量。我想在Booking模型中创建一个方法,它返回一个包含所有不可用日期和项目的对象数组,以便所需的输出为:

[ {rentalitem_id: 1, unavailable: '01-03-2018'},
  {rentalitem_id: 2, unavailable: '02-03-2018'},
  {rentalitem_id: 1, unavailable: '01-03-2018'} ]

然后我可以使用JSON渲染方法,以便在我的前端(Vue.js)中访问它,在那里我可以简单地禁用相应项目的所有日期。当然,我还会在处理预订时验证后端是否有日期。

第一个问题:您如何看待这个想法?也许有更优雅的解决方案如何实现这一目标?

到目前为止,我写的预订模型中的方法如下所示:

class Booking < ApplicationRecord

 ...

   scope :future_bookings, -> (time) { where("rental_start >= ?", time) }

 ...

   def self.item_unavailable
      sorted_booking = future_bookings(Time.now).map do |booking|
         { rentalitem_id: booking.rentalitem_id,
           dates: ((booking.rental_start.to_date..booking.rental_end.to_date).map{ |date| date.strftime("%b %d %y") }).to_a }
      end
      merged_bookings = sorted_booking.group_by{ |key| key[:rentalitem_id]}.each do |_, value|
          value.map!{ |arr| arr[:dates] }
      end
   end
end

因此,基本上我会映射所有未来的预订,创建一个变量,包括rentalitem_idrental_startrental_end之间的所有日期。之后,我将这些结果分组为rentalitem_id,以便merged_bookings现在返回预订项目的所有日期:

# { 1=>[["Feb 28 18", "Mar 01 18", "Mar 02 18", "Mar 03 18"], ["Mar 01 18", "Mar 02 18", "Mar 03 18", "Mar 04 18", "Mar 05 18"]], 2=>[["Mar 01 18", "Mar 02 18"], ["Mar 02 18", "Mar 03 18"], ["Mar 02 18", "Mar 03 18", "Mar 04 18"]] }

我们的想法是计算整个数组中的所有相交日期,并在达到相应租赁项目的最大容量时返回日期,而应从rentalitem模型查询最大容量。然而,我被困在这里并尝试了我能想象到的所有动作。我想过使用inject来返回不可用的值,但在此之前我需要计算相交日期?

让我们假设第一个rentalitem每天最多可以预订两次,比3月1日不可用。此外,假设第二个rentalitem每天最多可以预订三次。因此,在示例后的3月2日它应该不可用。

我非常感谢这里的一些帮助:-)

答案

我创建了一个RentalItemAvailability类,通过rental_item和日期,以检查给定日期的可用性,而不是试图制作一些非常奇怪的东西,弄清楚如何通过一系列日期实现相同的...类似于:

class RentalItemAvailability
  delegate :maximum_capacity_per_day, :bookins, to: :@rental_item

  def initialize(rental_item, date)
    @rental_item = rental_item
    @date = date
  end

  def available?
    bookings_on_date < maximum_capacity_per_day
  end

  def bookins_on_date
    bookins
     .where('rental_start between :date and :date and rental_end between :date and :date', @date).count
  end
end      

这样您就可以每天验证并将rental_item标记为可用/不可用

另一答案

我相信你要求修改item_unavailable以返回每个项目/日期的计数。为此,您可能希望基于item_id在ruby中构建哈希,其中包含日期和计数。像这样的东西:

{
  1: {
    "Feb 28 18": 1,
    "Mar 01 18": 2
  }
}

另一种方法是为每个日期存储单独的预订(而不是具有开始和结束日期)。这最终将成为更多的记录,但我相信这将是一种更直观的方法。查询类似于上面哈希的结果的示例:

future_bookings.group(:rentalitem_id, :date).count
# {[1, "date_from_db"]=>2, [2, "date2_from_db"]=>1}

以上是关于如何分组,计算和映射日期范围? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何创建 SQL 查询来计算按日期分组和连接的项目? [关闭]

如何对连续范围进行分组(mysql 5.7)

如何按特定日期范围(例如小时、日、月)对数据进行分组?

如何使用Laravel按日期分组和统计记录?

日期选择器对话框在片段中不起作用[关闭]

如何从日期范围中获取所有天数并按这些天数分组?