Come si fa il tempo relativo in Rails?


220

Sto scrivendo un'applicazione Rails, ma non riesco a trovare come fare il tempo relativo, ad esempio se viene data una determinata classe Time, può calcolare "30 secondi fa" o "2 giorni fa" o se è più lungo di un mese "9/1/2008", ecc.


1
"calcolare" sembra essere la parola sbagliata, volevi dire "uscita"?
Lulalala,

Risposte:


366

Sembra che tu stia cercando il time_ago_in_wordsmetodo (o distance_of_time_in_words), da ActiveSupport. Chiamalo così:

<%= time_ago_in_words(timestamp) %>

4
Suggerimenti per un principiante rubino su come eseguire questo in irb? Corro: richiedo 'active_support' e quindi prova 'time_ago_in_words (Time.now)' ma la funzione non è stata trovata.
cboettig,

2
@cboettig Non fa parte di ActiveSupport, è definito in ActionView::Helpers::DateHelper.
Michael Kohl,

19
non è necessario richiedere 'active_support' se ci si trova in una console di rotaie. esiste un metodo console chiamato helperche è possibile chiamare e accedere a questi metodi. helper.time_ago_in_words(timestamp)
Matt Polito,

2
Cordiali saluti, se vuoi questo in irb, o semplicemente Ruby, fai un: require 'active_support/core_ext' Primo, e poi sei pronto per usare 7.days.agoe altri costrutti simili.
likethesky,

1
grande! sono appena arrivato qui in attesa di un codice di esempio e l'ho trovato. Adoro rubino e binari
Marcelo Biffara,

53

Ho scritto questo, ma devo controllare i metodi esistenti menzionati per vedere se sono migliori.

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, ho letto il primo rubino e il rubino non ha ActiveSupport pronto all'uso. Quindi penso che questo post sia più rubino. Tuttavia, nella domanda reale si parla di binari.
Jonke,

Rails è un framework web e la lingua di base è ruby. Quindi è normale ottenere del codice ruby ​​su una domanda di binari. Anche se il ruby ​​standard non include ActiveRecord, è supportato solo con un comando "gem install activerecord".
MickaelFM,

7
Puoi inserire l'ultima returnriga all'interno dell'istruzione casesotto elsee rimuovere tutte le returns.
Sawa,

2
qualcuno può dire perché c'è +99 +800 +180000?
Gaurav Shah,

+99 perché la fine di "un'ora fa" termina a 7100, ovvero 100 secondi in meno di due ore. Allo stesso modo, +800, poiché 172000 è 800 secondi meno di due giorni (172800 secondi) e così via.
Fred,

22

Giusto per chiarire la soluzione di Andrew Marshall per l'utilizzo di time_ago_in_words
(per Rails 3.0 e Rails 4.0)

Se sei in vista

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

Se sei in un controller

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

I controller non hanno il modulo ActionView :: Helpers :: DateHelper importato per impostazione predefinita.

NB Non è "il modo di guida" per importare gli helper nei controller. Gli helper sono utili per le visualizzazioni. Il metodo time_ago_in_words è stato deciso di essere un'entità vista nella triade MVC . (Non sono d'accordo ma quando a Roma ...)


20

Che dire

30.seconds.ago
2.days.ago

O qualcos'altro per cui stavi sparando?


19
questo è all'indietro da ciò che la domanda sta affermando.
xaxxon,

12

È possibile utilizzare gli operatori aritmetici per eseguire il tempo relativo.

Time.now - 2.days 

Ti darà 2 giorni fa.


10
Conoscevi 2.days.ago?
webmat,

2
esiste un metodo abbreviato per `Time.now + 2.days '?
Stefan,

23
@NixNinja: 2.days.sinceoppure2.days.from_now
Brian Donovan,

5
questo è all'indietro da ciò che la domanda stava ponendo. time_ago_in_words è la risposta alla domanda.
xaxxon,

Grazie mille.
Jigar Bhatt,

10

Qualcosa del genere avrebbe funzionato.

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
Questa è essenzialmente una reimplementazione dell'helper
Grant Hutchins,

2
il che significa che non dovresti usarlo e dovresti usare il built-in
xaxxon il

Questo mi sembra perfettamente perfetto. Ti consente di personalizzare il resto delle stringhe. ovvero "3 secondi fa" vs "3s ago"
raidfive,

#{diff_seconds/360}dovrebbe essere #{diff_seconds/3600}. L'ho modificato.
Femaref,

7

Poiché la maggior parte delle risposte qui suggerisce time_ago_in_words .

Invece di usare :

<%= time_ago_in_words(comment.created_at) %>

In Rails, preferisci:

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

insieme a una libreria jQuery http://timeago.yarp.com/ , con codice:

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

Vantaggio principale: memorizzazione nella cache

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


1
in realtà, non è il time_ago_in_wordsmomento S
23

6

Dai un'occhiata ai metodi di istanza qui:

http://apidock.com/rails/Time

Questo ha metodi utili come ieri, domani, inizio_di_settimana, fa, ecc.

Esempi:

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


1

Se stai creando un'applicazione Rails, dovresti usarla

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

Questo ti dà l'ora o la data nel fuso orario con cui hai configurato l'applicazione Rails.

Ad esempio, se si configura l'applicazione per l'utilizzo di UTC, Time.zone.nowsarà sempre in orario UTC (ad esempio, non sarà influenzato dalla modifica dell'ora legale britannica).

Il calcolo del tempo relativo è semplice, ad es

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.