คุณจะทำอย่างไรเวลาญาติใน Rails?


220

ฉันเขียนแอปพลิเคชั่น Rails แต่ดูเหมือนจะไม่สามารถหาเวลาที่สัมพันธ์กันได้เช่นถ้ามีการกำหนดเวลาที่แน่นอนสามารถคำนวณได้ "30 วินาทีก่อน" หรือ "2 วันก่อน" หรือถ้านานกว่าหนึ่งเดือน "9/1/2551" เป็นต้น


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
Michael Kohl

19
คุณไม่จำเป็นต้องใช้ 'active_support' หากคุณอยู่ในคอนโซลทางรถไฟ มีวิธีคอนโซลที่เรียกhelperว่าคุณสามารถโทรและเข้าถึงวิธีการเหล่านี้ helper.time_ago_in_words(timestamp)
Matt Polito

2
เพียงแค่ fyi ถ้าคุณต้องการสิ่งนี้ใน irb หรือ Ruby ธรรมดา ๆ ให้ทำ: require 'active_support/core_ext' ก่อนอื่นจากนั้นคุณก็พร้อมสำหรับการใช้งาน7.days.agoและโครงสร้างอื่น ๆ ที่คล้ายคลึงกัน
likethesky

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 ออกจากกล่อง ดังนั้นฉันคิดว่าโพสต์นี้เป็นทับทิมมากกว่า อย่างไรก็ตามในคำถามที่แท้จริงมีการพูดถึงราง
Jonke

Rails เป็นเฟรมเวิร์กของเว็บและภาษาที่ใช้คือทับทิม ดังนั้นจึงเป็นเรื่องปกติที่จะได้รหัสทับทิมจากคำถามเกี่ยวกับราง แม้ว่า ruby ​​มาตรฐานจะไม่รวม ActiveRecord แต่ก็รองรับเพียงคำสั่ง "gem install activerecord"
MickaelFM

7
คุณสามารถใส่สุดท้ายreturnบรรทัดภายในcaseภายใต้คำสั่งelseและลบทั้งหมดของreturns
sawa

2
มีคนบอกได้+99 +800 +180000ไหมว่าทำไมมี
Gaurav Shah

+99 เพราะสิ้นสุด "ชั่วโมงที่แล้ว" สิ้นสุดที่ 7100 ซึ่งสั้นกว่า 100 วินาทีสองชั่วโมง ในทำนองเดียวกัน +800 ตั้งแต่ 172000 นั้นสั้นเพียง 800 วินาทีของสองวัน (172800 วินาที) และอื่น ๆ
Fred

22

เพียงชี้แจงโซลูชันของ Andrew Marshall เพื่อใช้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 ที่นำเข้าตามค่าเริ่มต้น

NB มันไม่ใช่ "ทางรถไฟ" ที่จะนำเข้าผู้ช่วยเหลือเข้าไปในตัวควบคุมของคุณ ผู้ช่วยเหลือมีไว้เพื่อช่วยในการดู time_ago_in_wordsวิธีการก็ตัดสินใจที่จะเป็นมุมมองของนิติบุคคลในMVCสาม (ฉันไม่เห็นด้วย แต่เมื่ออยู่ในกรุงโรม ... )


20

เกี่ยวกับอะไร

30.seconds.ago
2.days.ago

หรืออย่างอื่นที่คุณกำลังยิงเพื่อ?


19
นี่คือสิ่งที่ย้อนกลับจากคำถามที่ระบุ
xaxxon

12

คุณสามารถใช้ตัวดำเนินการทางคณิตศาสตร์เพื่อทำเวลาสัมพัทธ์

Time.now - 2.days 

จะให้คุณ 2 วันที่ผ่านมา


10
คุณรู้เกี่ยวกับ 2.days.ago หรือไม่?
webmat

2
มีวิธีการจดชวเลขสำหรับ 'Time.now + 2.days' หรือไม่
Stefan

23
@NixNinja: 2.days.sinceหรือ2.days.from_now
Brian Donovan

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
นี่คือการปรับปรุงใหม่ของผู้ช่วย distance_of_time_in_words: api.rubyonrails.com/classes/ActionView/Helpers/ …
สิทธิ์ Hutchins

2
ซึ่งหมายความว่าคุณไม่ควรใช้มันและคุณควรใช้ built-in
xaxxon

ดูเหมือนว่าจะดีสำหรับฉันอย่างสมบูรณ์ มันช่วยให้คุณปรับแต่งส่วนที่เหลือของสตริง เช่น "3 วินาทีก่อน" กับ "3 วินาทีก่อน"
raidfive

#{diff_seconds/360}#{diff_seconds/3600}ควรจะเป็น ฉันแก้ไขมันแล้ว
Femaref

7

เนื่องจากคำตอบส่วนใหญ่ที่นี่แนะนำtime_ago_in_words time_ago_in_words

แทนที่จะใช้:

<%= time_ago_in_words(comment.created_at) %>

ใน Rails ต้องการ:

<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

มีวิธีการที่มีประโยชน์เช่นเมื่อวาน, วันพรุ่งนี้, วันที่เริ่มต้นของ _ วัน _ สัปดาห์, เป็นต้น

ตัวอย่าง:

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

1

ฉันเขียนอัญมณีที่ทำสิ่งนี้กับวัตถุ Rails ActiveRecord ตัวอย่างใช้ created_at แต่จะทำงานกับ updated_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)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.