Как я могу рассчитать количество недель с указанной даты в Ruby?

Цель

Я пытаюсь рассчитать расстояние в неделях с заданной даты, не прыгая через обручи. Я бы предпочел сделать это на простом Ruby, но ActiveSupport, безусловно, является приемлемой альтернативой.

Мой код

Я написал следующее, которое, похоже, работает, но мне кажется, что это долгий путь.

require 'date'

DAYS_IN_WEEK = 7.0 

def weeks_since date_string
  date  = Date.parse date_string
  days  = Date.today - date
  weeks = days / DAYS_IN_WEEK
  weeks.round 2
end

weeks_since '2015-06-15'
#=> 32.57

#weeks_since ActiveSupport принимает в качестве аргумента количество недель, поэтому он не не подходит для этого варианта использования. Рубиновый класс Date, похоже, также не имеет ничего важного. .

Альтернативы?

Есть ли лучшее встроенное решение или известный алгоритм для расчета количества недель, разделяющих пару дат? Я не пытаюсь играть в гольф с кодом, поскольку читабельность превосходит краткость, а просто пытаюсь узнать, поддерживает ли Ruby изначально тот тип арифметики дат, который я закодировал вручную.


person Todd A. Jacobs    schedule 29.01.2016    source источник
comment
Недели не начинаются в один и тот же день во всем мире. Какое определение вы берете? Или под неделей вы на самом деле имеете в виду дни/7? Например, исходя из недели, начинающейся с понедельника, 30 января 2016 г. и 31 января 2016 г. относятся к одной и той же неделе, но исходя из недели, начинающейся с воскресенья, они относятся к разным неделям.   -  person sawa    schedule 29.01.2016
comment
Используя время, это будет (t2 - t1) / 604800. Что (60 * 60 * 24 * 7) = 1 неделя в секундах. в противном случае ваше решение также будет делать то же самое.   -  person engineersmnky    schedule 29.01.2016
comment
@sawa Я думаю, что он определяет неделю в гораздо более чистом смысле 7 последовательных дней.   -  person engineersmnky    schedule 29.01.2016
comment
@engineersmnky Ты прав. Я определяю недели как блоки из 7 последовательных дней, а не рабочие недели или календарные недели.   -  person Todd A. Jacobs    schedule 29.01.2016
comment
Вы могли бы сказать, расстояние в метрах или время в неделях, но не расстояние в неделях. :-)   -  person Cary Swoveland    schedule 29.01.2016
comment
если вы просто имеете в виду 7-дневные приращения, как это делает код, который у вас есть, я не вижу ничего плохого в коде, который у вас есть, или каких-либо причин для его улучшения.   -  person jrochkind    schedule 29.01.2016


Ответы (3)


Может быть проще преобразовать даты во время, а затем разделить разницу во времени на неделю. Вы можете round сделать это, как хотите, или ceil.

def weeks_since(date_string)
  time_in_past = Date.parse(date_string).to_time
  now = Time.now
  time_difference = now - time_in_past
  (time_difference / 1.week).round(2)
end
person Marcus Hoile    schedule 14.03.2018

in_weeks (Rails 6.1+)

В Rails 6.1 представлены новые методы преобразования ActiveSupport::Duration, такие как в_секундах, in_minutes, в_часах, в_днях, в_неделях, в_месяцах и in_years.

В результате теперь ваша проблема может быть решена как:

date_1 = Time.parse('2020-10-18 00:00:00 UTC')
date_2 = Time.parse('2020-08-13 03:35:38 UTC') 

(date_2 - date_1).seconds.in_weeks.to_i.abs
# => 9

Вот ссылка на соответствующий PR.

person Marian13    schedule 19.10.2020

person    schedule
comment
Хорошо, я вижу Date# step определен, но даже после прочтения документации я не уверен, почему ваш пример работает. - person Todd A. Jacobs; 30.01.2016
comment
Date#step принимает другой объект Date и число. Он вернет объект Enumerator, состоящий из разницы в днях между этими двумя датами. Date#upto(some_date) эквивалентно Date#step(some_date, 1). - person sbs; 30.01.2016
comment
Полезно отметить, что второй аргумент относится к количеству дней на шаг. Это плохо задокументировано как Руби 2.4.1. - person Todd; 27.08.2017
comment
Точнее, первый должен быть Date.parse(str).step(Date.today, 7).count - 1, чтобы (Date.current - 7.days).step(Date.current, 7).count - 1 == 1 - person estani; 08.06.2021