Wie macht man die relative Zeit in Rails?


220

Ich schreibe eine Rails-Anwendung, kann aber anscheinend nicht herausfinden, wie die relative Zeit zu berechnen ist. Wenn eine bestimmte Zeitklasse angegeben ist, kann sie "vor 30 Sekunden" oder "vor 2 Tagen" berechnen oder länger als einen Monat dauern "01.09.2008" usw.


1
'berechnen' scheint das falsche Wort zu sein, meinten Sie 'Ausgabe'?
Lulalala

Antworten:


366

Klingt so, als würden Sie nach der time_ago_in_wordsMethode (oder distance_of_time_in_words) von ActiveSupport suchen. Nennen Sie es so:

<%= time_ago_in_words(timestamp) %>

4
Tipps für einen Rubin-Neuling, wie man das in irb laufen lässt? Ich führe aus: benötige 'active_support' und versuche dann 'time_ago_in_words (Time.now)', aber die Funktion wird nicht gefunden.
cboettig

2
@cboettig Es ist nicht Teil von ActiveSupport, es ist definiert in ActionView::Helpers::DateHelper.
Michael Kohl

19
Sie müssen 'active_support' nicht benötigen, wenn Sie sich in einer Rails-Konsole befinden. Es gibt eine Konsolenmethode namens helper, mit der Sie diese Methoden aufrufen und darauf zugreifen können. helper.time_ago_in_words(timestamp)
Matt Polito

2
Nur zu Ihrer Information, wenn Sie dies in irb oder einfach in Ruby möchten, machen Sie einfach Folgendes: require 'active_support/core_ext' Zuerst, und dann sind Sie bereit, 7.days.agoandere ähnliche Konstrukte zu verwenden.
likethesky

1
großartig! Ich bin gerade hierher gekommen und habe einen Beispielcode erwartet und diesen gefunden. Ich liebe Rubin und Schienen
Marcelo Biffara

53

Ich habe dies geschrieben, muss aber die vorhandenen Methoden überprüfen, um festzustellen, ob sie besser sind.

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
Hum, ich habe zuerst Ruby gelesen und Ruby hat ActiveSupport nicht sofort verfügbar. Ich denke, dieser Beitrag ist mehr rubinrot. In der eigentlichen Frage werden jedoch Schienen erwähnt.
Jonke

Rails ist ein Webframework und die zugrunde liegende Sprache ist Ruby. Es ist also normal, auf einer Rails-Frage einen Ruby-Code zu erhalten. Auch wenn Standard-Ruby ActiveRecord nicht enthält, wird es nur mit dem Befehl "gem install activerecord" unterstützt.
MickaelFM

7
Sie können die letzte returnZeile in die caseAnweisung unter einfügen elseund alle returns entfernen .
Sawa

2
kann jemand sagen warum es gibt +99 +800 +180000?
Gaurav Shah

+99, weil das Ende von "vor einer Stunde" bei 7100 endet, was 100 Sekunden weniger als zwei Stunden ist. In ähnlicher Weise ist +800, da 172000 800 Sekunden weniger als zwei Tage (172800 Sekunden) ist, und so weiter.
Fred

22

Nur um Andrew Marshalls Lösung für die Verwendung von time_ago_in_words
(für Rails 3.0 und Rails 4.0) zu verdeutlichen

Wenn Sie in einer Ansicht sind

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

Wenn Sie sich in einem Controller befinden

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

In Controllern ist das Modul ActionView :: Helpers :: DateHelper standardmäßig nicht importiert.

NB Es ist nicht "der Schienenweg", Helfer in Ihre Controller zu importieren. Helfer sind für helfende Ansichten. Die Methode time_ago_in_words wurde als Ansichtsentität in der MVC- Triade festgelegt. (Ich stimme nicht zu, aber wenn in Rom ...)


20

Wie wäre es mit

30.seconds.ago
2.days.ago

Oder etwas anderes, für das Sie gedreht haben?


19
Dies ist rückwärts von dem, was die Frage besagt.
Xaxxon

12

Sie können die arithmetischen Operatoren verwenden, um die relative Zeit zu berechnen.

Time.now - 2.days 

Wird Ihnen vor 2 Tagen geben.


10
Wussten Sie schon über 2.days.ago?
Webmat

2
Gibt es eine Kurzmethode für "Time.now + 2.days"?
Stefan

23
@NixNinja: 2.days.sinceoder2.days.from_now
Brian Donovan

5
Dies ist rückwärts von dem, was die Frage gestellt hat. time_ago_in_words ist die Antwort auf die Frage.
Xaxxon

Vielen vielen Dank.
Jigar Bhatt

10

So etwas würde funktionieren.

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
Dies ist im Wesentlichen eine Neuimplementierung des Hilfsprogramms
Grant Hutchins

2
Das bedeutet , Sie sollten es nicht verwenden , und Sie sollten die eingebaute in Verwendung
xaxxon

Das scheint mir vollkommen in Ordnung zu sein. Sie können den Rest der Zeichenfolgen anpassen. dh "vor 3 Sekunden" vs "vor 3 Sekunden"
raidfive

#{diff_seconds/360}sollte sein #{diff_seconds/3600}. Ich habe es bearbeitet.
Femaref

7

Da schlägt die meiste Antwort hier time_ago_in_words vor .

Anstatt zu verwenden:

<%= time_ago_in_words(comment.created_at) %>

In Rails bevorzugen Sie:

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

zusammen mit einer jQuery-Bibliothek http://timeago.yarp.com/ mit Code:

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

Hauptvorteil: Caching

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


1
Eigentlich ist es time_ago_in_wordsnicht Zeit S
23tux

6

Schauen Sie sich hier die Instanzmethoden an:

http://apidock.com/rails/Time

Dies hat nützliche Methoden wie gestern, morgen, Beginn der Woche, vor usw.

Beispiele:

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

1

Ich habe ein Juwel geschrieben, das dies für Rails ActiveRecord-Objekte tut. Das Beispiel verwendet created_at, funktioniert jedoch auch mit updated_at oder anderen Elementen mit der Klasse ActiveSupport :: TimeWithZone.

Einfach installieren und die 'hübsche' Methode auf Ihrer TimeWithZone-Instanz aufrufen.

https://github.com/brettshollenberger/hublot


1

Wenn Sie eine Rails-Anwendung erstellen, sollten Sie diese verwenden

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

Dies gibt Ihnen Zeit oder Datum in der Zeitzone an, mit der Sie Ihre Rails-Anwendung konfiguriert haben.

Wenn Sie beispielsweise Ihre Anwendung für die Verwendung von UTC konfigurieren, befindet sie Time.zone.nowsich immer in UTC-Zeit (dies wird beispielsweise nicht durch die Änderung der britischen Sommerzeit beeinflusst).

Die Berechnung der relativen Zeit ist einfach, z

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.