铁路TimeWithZone与日期

时间:2014-12-18 12:31:06

标签: ruby-on-rails ruby

我的模型中有这个方法:

def date_ranges
  reservations = Reservation.where(["transport_id =?", transport_id])
  reservations = reservations.where(['id <> ?', id]) if !id.nil?
  reservations.map { |e| e.reservation_start..e.reservation_end }
end

它运行得很好(感谢StackOverflow的一些帮助)。

我的reservation_startreservation_end列属于date类型。这是我的迁移:

class CreateReservations < ActiveRecord::Migration
  def change
    create_table :reservations do |t|
      t.references :user, index: true
      t.references :transport, index: true

      t.date :reservation_start
      t.date :reservation_end
      t.timestamps
    end
  end
end

如果我在从date列类型迁移到datetime类型后尝试运行此方法,则会收到错误消息:

can't iterate from ActiveSupport::TimeWithZone

即使我将方法中的代码更改为:

,它仍然无法正常工作
reservations.map do |e|
  e.reservation_start.to_datetime..e.reservation_end.to_datetime
end

1 个答案:

答案 0 :(得分:1)

不幸的是,如果要迭代DateTime范围,则范围应该具有至少1天的粒度。因此,似乎错误出现在您使用#date_ranges的地方,而不是在方法本身

由于您正在使用ActiveSupport::TimeWithZone(这是使用datetime SQL类型时获得的对象类型),您可以获得比日期更精确的内容 - 您还有时间

所以取决于你如何使用这个方法。

您有两种方法可以解决此问题:

  1. 将代码更改为以下内容:

     reservations.map do |e|
       e.reservation_start.to_date..e.reservation_end.to_date
     end
    

    这样你就会失去时间精确度,只能回到日期。

  2. 更改您使用#date_ranges方法的方式。可能最好的方法是让它返回[begin_date, end_date]的数组。

     def date_ranges
       Reservation.where(transport_id: transport_id).pluck(:reservation_start, :reservation_end)
     end
    

    根据您使用范围的方式,您可以解决这个问题:

    • 如果您要检查特定时间是否在任何给定的日期范围内,您可以执行以下操作:

      date_ranges.any? { |date_range| date_range.cover?(my_time) }
      
    • 如果您要显示日期:

      date_ranges.each do |date_range|
        # display the date range
      end