Рубин Бенин Вейл для ноль DateTime - PullRequest
0 голосов
/ 09 мая 2019

При сравнении DateTimes все сравниваемые объекты должны быть одного типа.Тем не менее, у меня есть набор данных, который имеет nil даты.Я хочу рассматривать эти даты как более старые (или, возможно, более новые), чем любая другая дата.Есть ли способ создать мягкое значение, которое будет сравниваться как более старое (или, альтернативно, более новое), чем любая другая дата?

пример:

data = [
  { name: :foo, timestamp: make_benign(some_valid_timestamp) },
  { name: :bar, timestamp: make_benign(nil)}
]

data.sort_by{|datum| datum[:timestamp]} #=> [<bar>, <foo>]
data.max_by {|datum| datum[:timestamp]} #=> <foo>
data.min_by {|datum| datum[:timestamp]} #=> <bar>

РЕДАКТИРОВАТЬ: Я застрял на ruby ​​1.9 для этой проблемы, поэтому решения для старых версий ruby ​​были бы хорошими.(Но новые решения также хороши для будущего использования)

1 Ответ

2 голосов
/ 09 мая 2019

Из документов требуется , а не , что «все объекты одного типа».В нем говорится:

Другой должен быть объектом даты или числовым значением в качестве астрономического юлианского числа дня.

Так что для доброкачественного значения, которое гарантированно будет раньше/ после любой даты, вы можете использовать -Float::INFINITY и Float::INFINITY соответственно.

DateTime.now > Float::INFINITY  #=> false
DateTime.now > -Float::INFINITY #=> true

РЕДАКТИРОВАТЬ:

Итак, нам нужно решение, которое работаетв Ruby 1.9 и Rails 3.2.9, да ...

Ну, причина, по которой вышесказанное не сработает, в том, что этот monkeypatch в ActiveSupport :

class DateTime
  def <=>(other)
    super other.to_datetime
  end
end

Это особенно проблематично.К сожалению, вам может понадобиться просто использовать " очень большое / маленькое число " вместо ...

Однако , если вы можете немного обновитьна Rails 3.2.13 (или примените обновленный monkeypatch вручную), где сигнатура метода была изменена на:

class DateTime
  def <=>(other)
    super other.kind_of?(Infinity) ? other : other.to_datetime
  end
end

...Тогда вы можете использовать Date::Infinity (TIL, это вещь) вместо Float::Infinity, и эта «исправленная» версия метода теперь обрабатывает его правильно:

DateTime.now > Date::Infinity.new  #=> false
DateTime.now > -Date::Infinity.new #=> true
...