2010-11-09 72 views
23

मैं सबसे अच्छा तरीका है निम्न उत्पादनकैसे रेल पर गहरे लाल रंग का उपयोग करते हुए एक मानव पठनीय समय सीमा उत्पन्न करने के लिए

<name> job took 30 seconds 
<name> job took 1 minute and 20 seconds 
<name> job took 30 minutes and 1 second 
<name> job took 3 hours and 2 minutes 
उत्पन्न करने के लिए खोजने की कोशिश कर रहा हूँ

मैं इस कोड शुरू कर दिया

def time_range_details 
    time = (self.created_at..self.updated_at).count 
    sync_time = case time 
    when 0..60 then "#{time} secs"  
    else "#{time/60} minunte(s) and #{time-min*60} seconds" 
    end 
end 

क्या कोई ऐसा करने का अधिक कुशल तरीका। यह कुछ सुपर सरल के लिए बहुत अनावश्यक कोड की तरह लगता है।

इसके लिए एक और इस्तेमाल होता है:

<title> was posted 20 seconds ago 
<title> was posted 2 hours ago 

इस के लिए कोड के लिए समान है, लेकिन इसके बजाय मैं का उपयोग Time.now:

def time_since_posted 
    time = (self.created_at..Time.now).count 
    ... 
    ... 
end 

उत्तर

50

आप कुछ और अधिक "सटीक" distance_of_time_in_words से, आप इन पंक्तियों के साथ कुछ लिख सकते हैं की जरूरत है:

def humanize secs 
    [[60, :seconds], [60, :minutes], [24, :hours], [1000, :days]].map{ |count, name| 
    if secs > 0 
     secs, n = secs.divmod(count) 
     "#{n.to_i} #{name}" 
    end 
    }.compact.reverse.join(' ') 
end 

p humanize 1234 
#=>"20 minutes 34 seconds" 
p humanize 12345 
#=>"3 hours 25 minutes 45 seconds" 
p humanize 123456 
#=>"1 days 10 hours 17 minutes 36 seconds" 
p humanize(Time.now - Time.local(2010,11,5)) 
#=>"4 days 18 hours 24 minutes 7 seconds" 

ओह , आपके सी पर एक टिप्पणी स्तोत्र:

(self.created_at..self.updated_at).count 

वास्तव में बुरा रास्ता अंतर पाने के लिए है। बस का उपयोग करें:

self.updated_at - self.created_at 
+0

बस उत्सुक, यह बुरा क्यों है? (self.created_at..self.updated_at)। स्वच्छ उत्तर के लिए धन्यवाद धन्यवाद! – csanz

+2

@csanz: उस मामले में '.count' दो टाइमस्टैम्प के बीच हर सेकेंड की सरणी के माध्यम से पुनरावृत्त करता है और उन्हें गिना जाता है। जैसे कि आप वास्तव में 50 से 100 के बीच सभी संख्याओं की गणना करके अभिव्यक्ति '100-50' के परिणाम की गणना करेंगे। –

+1

मैं डेटहेल्पर विधियों को प्राथमिकता देता हूं। यदि आप इसे अंग्रेजी में बदलने के लिए परेशान होने जा रहे हैं, तो आप शायद दिन और सेकंड को जोड़ना नहीं चाहते हैं। यह एक कृत्रिम परिशुद्धता है। –

23

वहाँ DateHelper में दो तरीकों है कि आप दे सकता है कर रहे हैं क्या आप चाहते हैं:

  1. time_ago_in_words

    time_ago_in_words(1234.seconds.from_now) #=> "21 minutes" 
    
    time_ago_in_words(12345.seconds.ago)  #=> "about 3 hours" 
    
  2. distance_of_time_in_words

    distance_of_time_in_words(Time.now, 1234.seconds.from_now) #=> "21 minutes" 
    
    distance_of_time_in_words(Time.now, 12345.seconds.ago)  #=> "about 3 hours" 
    
7

chronic_duration पठनीय करने के लिए सांख्यिक समय पार्स करता है और इसके विपरीत

0

वहाँ distance_of_time_in_words के साथ समस्या यह है अगर यू वहाँ 1 घंटे 30 मिनट पारित करेंगे इसके बारे में 2 घंटे

वापसी करेंगे

बस सहायक में जोड़ें:

PERIODS = { 
    'day' => 86400, 
    'hour' => 3600, 
    'minute' => 60 
    } 


def formatted_time(total) 
    return 'now' if total.zero? 

    PERIODS.map do |name, span| 
    next if span > total 
    amount, total = total.divmod(span) 
    pluralize(amount, name) 
    end.compact.to_sentence 
end 

मूल रूप से बस सेकंड में अपना डेटा पास करें।

1

आप दिन श्रृंखला के लिए सेकंड में महत्वपूर्ण अवधि को दिखाने के लिए चाहते हैं, तो एक विकल्प हो सकता है (के रूप में यह सबसे अच्छा प्रदर्शन करने के लिए नहीं है):

def human_duration(secs, significant_only = true) 
    n = secs.round 
    parts = [60, 60, 24, 0].map{|d| next n if d.zero?; n, r = n.divmod d; r}. 
    reverse.zip(%w(d h m s)).drop_while{|n, u| n.zero? } 
    if significant_only 
    parts = parts[0..1] # no rounding, sorry 
    parts << '0' if parts.empty? 
    end 
    parts.flatten.join 
end 
start = Time.now 
# perform job 
puts "Elapsed time: #{human_duration(Time.now - start)}" 

human_duration(0.3) == '0' 
human_duration(0.5) == '1s' 
human_duration(60) == '1m0s' 
human_duration(4200) == '1h10m' 
human_duration(3600*24) == '1d0h' 
human_duration(3600*24 + 3*60*60) == '1d3h' 
human_duration(3600*24 + 3*60*60 + 59*60) == '1d3h' # simple code, doesn't round 
human_duration(3600*24 + 3*60*60 + 59*60, false) == '1d3h59m0s' 

वैकल्पिक रूप से आप केवल अलग करना में रुचि हो सकती सेकेंड भाग जब इससे कोई फर्क नहीं पड़ता (एक और दृष्टिकोण भी प्रदर्शित करता है):

def human_duration(duration_in_seconds) 
    n = duration_in_seconds.round 
    parts = [] 
    [60, 60, 24].each{|d| n, r = n.divmod d; parts << r; break if n.zero?} 
    parts << n unless n.zero? 
    pairs = parts.reverse.zip(%w(d h m s)[-parts.size..-1]) 
    pairs.pop if pairs.size > 2 # do not report seconds when irrelevant 
    pairs.flatten.join 
end 

आशा है कि मदद करता है।

संबंधित मुद्दे