В Rails время отображения между двумя датами на английском языке
В проекте Rails я хочу найти разницу между двумя датами, а затем отобразить ее на естественном языке. Что-то вроде
>> (date1 - date2).to_natural_language
"3 years, 2 months, 1 week, 6 days"
В основном this для рубина.
Google и Rails API ничего не обнаружили. Я нашел некоторые вещи, которые дадут вам разницу в одной единице (т.е. Сколько недель между двумя датами), но не то, что точно рассчитает годы, месяцы, недели и дни вместе.
Ответы
Ответ 1
Другие ответы могут не дать того типа выходных данных, который вы ищете, потому что вместо строки лет, месяцев и т.д. Помощники Rails просто показывают наибольшую единицу. Если вы ищете что-то более сломанное, здесь есть еще один вариант. Вставьте этот метод в помощника:
def time_diff_in_natural_language(from_time, to_time)
from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
distance_in_seconds = ((to_time - from_time).abs).round
components = []
%w(year month week day).each do |interval|
# For each interval type, if the amount of time remaining is greater than
# one unit, calculate how many units fit into the remaining time.
if distance_in_seconds >= 1.send(interval)
delta = (distance_in_seconds / 1.send(interval)).floor
distance_in_seconds -= delta.send(interval)
components << pluralize(delta, interval)
# if above line give pain. try below one
# components << interval.pluralize(delta)
end
end
components.join(", ")
end
И тогда в представлении вы можете сказать что-то вроде:
<%= time_diff_in_natural_language(Time.now, 2.5.years.ago) %>
=> 2 years, 6 months, 2 days
Данный метод сводится только к дням, но при желании его можно легко расширить, добавив меньшие единицы.
Ответ 2
Модуль ActionView
Rails включает два метода, которые могут делать то, что вам нужно:
Ответ 3
Я попробовал решение Daniel и нашел несколько неправильных результатов для нескольких тестовых примеров из-за того, что он неправильно обрабатывает переменное число дней, найденных в месяцы:
> 30.days < 1.month
=> false
Итак, например:
> d1 = DateTime.civil(2011,4,4)
> d2 = d1 + 1.year + 5.months
> time_diff_in_natural_language(d1,d2)
=> "1 year, 5 months, 3 days"
Следующее даст вам правильное количество {лет, месяцев, дней, часов, минут, секунд}:
def time_diff(from_time, to_time)
%w(year month day hour minute second).map do |interval|
distance_in_seconds = (to_time.to_i - from_time.to_i).round(1)
delta = (distance_in_seconds / 1.send(interval)).floor
delta -= 1 if from_time + delta.send(interval) > to_time
from_time += delta.send(interval)
delta
end
end
> time_diff(d1,d2)
=> [1, 5, 0, 0, 0, 0]
Ответ 4
distance_of_time_in_words
является наиболее точным здесь. Ответ Даниэля неправдоподобен: 2,5 года назад он должен был производить ровно 2 года, 6 месяцев. Проблема заключается в том, что месяцы содержат 28-31 день, а годы могут быть прыжками.
Мне хотелось бы знать, как это исправить: (
Ответ 5
DateHelper#distance_of_time_in_words
Ответ 6
def date_diff_in_natural_language(date_from, date_to)
components = []
%w(years months days).each do |interval_name|
interval = 1.send(interval_name)
count_intervals = 0
while date_from + interval <= date_to
date_from += interval
count_intervals += 1
end
components << pluralize(count_intervals, interval_name) if count_intervals > 0
end
components.join(', ')
end