Як у вас є відносний час у Rails?


220

Я пишу заявку на Rails, але не можу знайти спосіб відносного часу, тобто, якщо задано певний часовий клас, він може обчислити "30 секунд тому" або "2 дні тому" або якщо це більше місяця "9/1/2008" тощо.


1
"обчислити", здається, неправильне слово, ти мав на увазі "вихід"?
lulalala

Відповіді:


366

Здається, ви шукаєте time_ago_in_wordsметод (або distance_of_time_in_words) від ActiveSupport. Назвіть це так:

<%= time_ago_in_words(timestamp) %>

4
Підказки для рубінового новачка про те, як запустити це в irb? Я запускаю: вимагаю "active_support", а потім спробуйте "time_ago_in_words (Time.now)", але функція не знайдена.
cboettig

2
@cboettig Це не частина ActiveSupport, визначена в ActionView::Helpers::DateHelper.
Майкл Коль

19
вам не потрібно вимагати "active_support", якщо ви знаходитесь на консолі рейки. існує консольний метод, helperякий можна називати і отримувати доступ до цих методів. helper.time_ago_in_words(timestamp)
Метт Політо

2
Просто фій, якщо ви хочете цього в irb або звичайному Ruby, просто зробіть: require 'active_support/core_ext' Спочатку, а потім все готово до використання 7.days.agoта інших подібних конструкцій.
лікетський

1
чудово! Я щойно приїхав сюди, очікуючи зразкового коду і знайшов це. Я люблю рубін та рейки
Marcelo Biffara

53

Я написав це, але треба перевірити існуючі методи, щоб побачити, чи кращі вони.

module PrettyDate
  def to_pretty
    a = (Time.now-self).to_i

    case a
      when 0 then 'just now'
      when 1 then 'a second ago'
      when 2..59 then a.to_s+' seconds ago' 
      when 60..119 then 'a minute ago' #120 = 2 minutes
      when 120..3540 then (a/60).to_i.to_s+' minutes ago'
      when 3541..7100 then 'an hour ago' # 3600 = 1 hour
      when 7101..82800 then ((a+99)/3600).to_i.to_s+' hours ago' 
      when 82801..172000 then 'a day ago' # 86400 = 1 day
      when 172001..518400 then ((a+800)/(60*60*24)).to_i.to_s+' days ago'
      when 518400..1036800 then 'a week ago'
      else ((a+180000)/(60*60*24*7)).to_i.to_s+' weeks ago'
    end
  end
end

Time.send :include, PrettyDate

1
Хм, я прочитав перший рубін, а в рубіні немає ActiveSupport поза коробкою. Тому я вважаю, що цей пост є більш рубіновим. Однак у актуальному питанні є згадка про рейки.
Йонке

Rails - це веб-структура, а основна мова - рубін. Тож нормально отримати якийсь рубіновий код на питання про рейки. Навіть якщо стандартний рубін не включає ActiveRecord, він підтримується лише командою "встановити gem install activerecord".
MickaelFM

7
Ви можете поставити останній returnрядок у caseоператорі під elseта видалити всі returns.
sawa

2
хтось може сказати, чому є +99 +800 +180000?
Гаурав Шах

+99, оскільки кінець "години тому" закінчується на рівні 7100, що на 100 секунд не вистачає двох годин. Аналогічно +800, оскільки 172000 - не більше 800 секунд на два дні (172800 секунд) тощо.
Фред

22

Просто для уточнення рішення Ендрю Маршалла щодо використання time_ago_in_words
(для Rails 3.0 та Rails 4.0)

Якщо ви переглядаєте

<%= time_ago_in_words(Date.today - 1) %>

Якщо ви в контролері

include ActionView::Helpers::DateHelper
def index
  @sexy_date = time_ago_in_words(Date.today - 1)
end

Контролери не мають модуля ActionView :: Helpers :: DateHelper, який імпортується за замовчуванням.

Примітка. Не імпортувати помічників у свої контролери - це не "рейковий шлях". Помічники допомагають переглядати. Метод time_ago_in_words було вирішено стати об'єктом перегляду в тріаді MVC . (Я не згоден, але коли в Римі ...)


20

А як на рахунок

30.seconds.ago
2.days.ago

Або щось інше, по якому ви знімали?


19
це відстає від того, про що йдеться в питанні.
xaxxon

12

Ви можете використовувати арифметичні оператори для відносного часу.

Time.now - 2.days 

Подарую вам 2 дні тому.


10
Ви знали про 2.days.ago?
вебмат

2
чи існує скорочений метод для `Time.now + 2.days '?
Стефан

23
@NixNinja: 2.days.sinceабо2.days.from_now
Брайан Донован

5
це відстає від того, що задавали питання. time_ago_in_words - це відповідь на питання.
xaxxon

Дуже дякую
Jigar Bhatt

10

Щось подібне спрацювало б.

def relative_time(start_time)
  diff_seconds = Time.now - start_time
  case diff_seconds
    when 0 .. 59
      puts "#{diff_seconds} seconds ago"
    when 60 .. (3600-1)
      puts "#{diff_seconds/60} minutes ago"
    when 3600 .. (3600*24-1)
      puts "#{diff_seconds/3600} hours ago"
    when (3600*24) .. (3600*24*30) 
      puts "#{diff_seconds/(3600*24)} days ago"
    else
      puts start_time.strftime("%m/%d/%Y")
  end
end

11
Це, по суті, повторне реалізація помічника відстань_обіця_в_слова: api.rubyonrails.com/classes/ActionView/Helpers/…
Грант Хатчінс

2
це означає, що ви не повинні використовувати його, і ви повинні використовувати вбудований
xaxxon

Це здається мені прекрасно. Це дозволяє налаштувати решту рядків. тобто "3 секунди тому" vs "3s тому"
рейдфів

#{diff_seconds/360}повинно бути #{diff_seconds/3600}. Я це відредагував.
Femaref

7

Оскільки найбільш відповідь тут пропонує time_ago_in_words .

Замість використання:

<%= time_ago_in_words(comment.created_at) %>

У Рейлах віддайте перевагу:

<abbr class="timeago" title="<%= comment.created_at.getutc.iso8601 %>">
  <%= comment.created_at.to_s %>
</abbr>

разом із бібліотекою jQuery http://timeago.yarp.com/ з кодом:

$("abbr.timeago").timeago();

Основна перевага: кешування

http://rails-bestpractices.com/posts/2012/02/10/not-use-time_ago_in_words/


1
власне, time_ago_in_wordsне час S
23tux

6

Погляньте на методи екземпляра тут:

http://apidock.com/rails/Time

Тут є корисні методи, такі як вчора, завтра, begin_of_week, назад тощо.

Приклади:

Time.now.yesterday
Time.now.ago(2.days).end_of_day
Time.now.next_month.beginning_of_month

1

Я написав самоцвіт, який робить це для об'єктів Rails ActiveRecord. У прикладі використовується create_at, але він також працюватиме оновлений_at або що-небудь з класом ActiveSupport :: TimeWithZone.

Просто встановіть дорогоцінний камінь і зателефонуйте на метод «досить» у вашому екземплярі TimeWithZone.

https://github.com/brettshollenberger/hublot


1

Якщо ви створюєте додаток Rails, вам слід скористатися

Time.zone.now
Time.zone.today
Time.zone.yesterday

Це дає вам час або дату в часовому поясі, з яким ви налаштували свою програму Rails.

Наприклад, якщо ви налаштуєте свою програму на використання UTC, вона Time.zone.nowзавжди буде в часі UTC (на зміну Британського літнього часу, наприклад, це не вплине).

Розрахувати відносний час досить просто, наприклад

Time.zone.now - 10.minute
Time.zone.today.days_ago(5)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.