2009-06-30 31 views
12

在Rails項目中,我想查找兩個日期之間的差異,然後以自然語言顯示。喜歡的東西在Rails中,以英文顯示兩個日期之間的時間

>> (date1 - date2).to_natural_language 
"3 years, 2 months, 1 week, 6 days" 

基本上this紅寶石。

谷歌和Rails API還沒有發現任何東西。我發現有些東西會給你一個單位的差異(即兩個日期之間有多少星期),但沒有一個能準確計算出幾年,幾個月,幾周,幾天的東西。

回答

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 

給出的方法只下降到天,但可以很容易地擴展到更小的加單位如果需要。

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 
相關問題