2009-06-30 3 views
12

एक रेल परियोजना में मैं दो तिथियों के बीच अंतर ढूंढना चाहता हूं और फिर इसे प्राकृतिक भाषा में प्रदर्शित करना चाहता हूं। जैसेरेल में, अंग्रेजी में दो तिथियों के बीच समय प्रदर्शित करें

>> (date1 - date2).to_natural_language 
"3 years, 2 months, 1 week, 6 days" 
माणिक के लिए

मूल रूप से this कुछ।

Google और रेल एपीआई कुछ भी नहीं बदला है। मुझे कुछ चीजें मिली हैं जो आपको एक इकाई में अंतर प्रदान करती हैं (यानी, दो तिथियों के बीच कितने सप्ताह) लेकिन ऐसा कुछ नहीं जो सटीक रूप से वर्षों, महीनों, हफ्तों, दिनों की गणना करेगा।

उत्तर

20

अन्य उत्तर के प्रकार देना नहीं हो सकता है आउटपुट जिसे आप ढूंढ रहे हैं, क्योंकि वर्षों, महीनों, आदि की स्ट्रिंग देने के बजाय, टी वह रेल मददगार बस सबसे बड़ी इकाई दिखाते हैं। यदि आप कुछ और टूटा हुआ खोज रहे हैं, तो यहां एक और विकल्प है। एक सहायक में इस विधि चिपका:

def time_diff_in_natural_language(from_time, to_time) 
    from_time = from_time.to_time if from_time.respond_to?(:to_time) 
    to_time = to_time.to_time if to_time.respond_to?(:to_time) 
    distance_in_seconds = ((to_time - from_time).abs).round 
    components = [] 

    %w(year month week day).each do |interval| 
    # For each interval type, if the amount of time remaining is greater than 
    # one unit, calculate how many units fit into the remaining time. 
    if distance_in_seconds >= 1.send(interval) 
     delta = (distance_in_seconds/1.send(interval)).floor 
     distance_in_seconds -= delta.send(interval) 
     components << pluralize(delta, interval) 
    end 
    end 

    components.join(", ") 
end 

और फिर एक दृश्य में आप कह सकते हैं की तरह कुछ:

<%= time_diff_in_natural_language(Time.now, 2.5.years.ago) %> 
=> 2 years, 6 months, 2 days 

दिया विधि केवल दिनों के लिए नीचे चला जाता है, लेकिन आसानी से किया जा सकता है छोटे में जोड़ने के लिए बढ़ा वांछित अगर इकाइयां।

+0

यह वास्तव में आशाजनक लग रहा है। दुर्भाग्य से मैं # <ऑब्जेक्ट: 0x389a0 @controller = # > "त्रुटि (कंसोल में) के लिए" अपरिभाषित विधि 'बहुवचन' प्राप्त कर रहा हूं। –

+0

ऐसा इसलिए है क्योंकि बहुवचन एक एक्शन व्यू सहायक विधि है: http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html। यदि आप स्क्रिप्ट/कंसोल में 'एक्शन व्यू :: हेल्पर्स :: टेक्स्टहेल्पर' शामिल करते हैं, तो बहुवचन परिभाषित किया जाएगा।जैसा कि उत्तर में बताया गया है, आपको विधि को एक सहायक सहायक (ऐप/हेल्पर्स में) में चिपका देना चाहिए और फिर इसे एक दृश्य से देखें। –

51

रेल 'ActionView मॉड्यूल दो तरीकों से कर सकते हैं कि शामिल है कि तुम क्या आवश्यकता होती है:

+0

+1 मुझे इसे मारो। – Pesto

+0

+1 जो मैं देख रहा था –

+0

में सप्ताह नहीं हैं ... –

2
+0

यह वास्तव में अच्छा है (और मुझे परेशान है कि मुझे पहले यह नहीं मिला), लेकिन यह अभी भी मुझे केवल एक मोटा अनुमान देता है। यानी, यह मुझे "3 महीने" देगा, न कि "3 महीने, 4 दिन"। –

3

distance_of_time_in_words यहां सबसे सटीक है। डैनियल का जवाब वास्तव में गलत है: 2.5 साल पहले ठीक 2 साल, 6 महीने का उत्पादन करना चाहिए। मुद्दा यह है कि महीनों में 28-31 दिन होते हैं, और वर्षों में छलांग लग सकती है।

मैं मुझे पता था कि यह :(

7

मैं Daniel's solution की कोशिश की ठीक करने का तरीका और कुछ परीक्षण मामलों के लिए कुछ गलत परिणाम मिल गया है, तथ्य यह है कि इसे सही ढंग से में पाया दिनों की चर संख्या से हैंडल नहीं करता की वजह से इच्छा महीने:

> 30.days < 1.month 
    => false 

तो, उदाहरण के लिए:

> d1 = DateTime.civil(2011,4,4) 
> d2 = d1 + 1.year + 5.months 
> time_diff_in_natural_language(d1,d2) 
=> "1 year, 5 months, 3 days"

निम्नलिखित आप {वर्ष, माह, दिन, घंटे, मिनट, सेकंड} की सही संख्या दे देंगे:

def time_diff(from_time, to_time) 
    %w(year month day hour minute second).map do |interval| 
    distance_in_seconds = (to_time.to_i - from_time.to_i).round(1) 
    delta = (distance_in_seconds/1.send(interval)).floor 
    delta -= 1 if from_time + delta.send(interval) > to_time 
    from_time += delta.send(interval) 
    delta 
    end 
end 
> time_diff(d1,d2) 
=> [1, 5, 0, 0, 0, 0]

0
def date_diff_in_natural_language(date_from, date_to) 
    components = [] 
    %w(years months days).each do |interval_name| 
    interval = 1.send(interval_name) 
    count_intervals = 0 
    while date_from + interval <= date_to 
     date_from += interval 
     count_intervals += 1 
    end 
    components << pluralize(count_intervals, interval_name) if count_intervals > 0 
    end 
    components.join(', ') 
end 
संबंधित मुद्दे