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.

John Topley
quelle
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) %>
Ben Scofield
quelle
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
Matthias Winkelmann
quelle
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 ...)

SEO
quelle
20

Wie wäre es mit

30.seconds.ago
2.days.ago

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

Honza
quelle
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.

TonyLa
quelle
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
Gordon Wilson
quelle
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/

Rahul garg
quelle
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
Davogone
quelle
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

Brett Shollenberger
quelle
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)
Zack Xu
quelle