Skip to content

Commit

Permalink
Merge pull request #5927 from avakhov/distance_of_time_in_words-swap
Browse files Browse the repository at this point in the history
Distance of time in words should work correctly if from_time > to_time
  • Loading branch information
jeremy committed Apr 24, 2012
2 parents f7ddbaa + 7322bd4 commit 4afdd97
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 16 deletions.
33 changes: 19 additions & 14 deletions actionpack/lib/action_view/helpers/date_helper.rb
Expand Up @@ -67,8 +67,9 @@ module DateHelper
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
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_minutes = (((to_time - from_time).abs)/60).round
distance_in_seconds = ((to_time - from_time).abs).round
from_time, to_time = to_time, from_time if from_time > to_time
distance_in_minutes = ((to_time - from_time)/60.0).round
distance_in_seconds = (to_time - from_time).round

I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
case distance_in_minutes
Expand All @@ -94,18 +95,22 @@ def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, o
when 43200..86399 then locale.t :about_x_months, :count => 1
when 86400..525599 then locale.t :x_months, :count => (distance_in_minutes.to_f / 43200.0).round
else
fyear = from_time.year
fyear += 1 if from_time.month >= 3
tyear = to_time.year
tyear -= 1 if to_time.month < 3
leap_years = (fyear > tyear) ? 0 : (fyear..tyear).count{|x| Date.leap?(x)}
minute_offset_for_leap_year = leap_years * 1440
# Discount the leap year days when calculating year distance.
# e.g. if there are 20 leap year days between 2 dates having the same day
# and month then the based on 365 days calculation
# the distance in years will come out to over 80 years when in written
# english it would read better as about 80 years.
minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
if from_time.acts_like?(:time) && to_time.acts_like?(:time)
fyear = from_time.year
fyear += 1 if from_time.month >= 3
tyear = to_time.year
tyear -= 1 if to_time.month < 3
leap_years = (fyear > tyear) ? 0 : (fyear..tyear).count{|x| Date.leap?(x)}
minute_offset_for_leap_year = leap_years * 1440
# Discount the leap year days when calculating year distance.
# e.g. if there are 20 leap year days between 2 dates having the same day
# and month then the based on 365 days calculation
# the distance in years will come out to over 80 years when in written
# english it would read better as about 80 years.
minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
else
minutes_with_offset = distance_in_minutes
end
remainder = (minutes_with_offset % 525600)
distance_in_years = (minutes_with_offset / 525600)
if remainder < 131400
Expand Down
24 changes: 22 additions & 2 deletions actionpack/test/template/date_helper_test.rb
Expand Up @@ -125,13 +125,33 @@ def test_distance_in_words_with_dates
start_date = Date.new 1982, 12, 3
end_date = Date.new 2010, 11, 30
assert_equal("almost 28 years", distance_of_time_in_words(start_date, end_date))
assert_equal("almost 28 years", distance_of_time_in_words(end_date, start_date))
end

def test_distance_in_words_with_integers
assert_equal "less than a minute", distance_of_time_in_words(59)
assert_equal "1 minute", distance_of_time_in_words(59)
assert_equal "about 1 hour", distance_of_time_in_words(60*60)
assert_equal "less than a minute", distance_of_time_in_words(0, 59)
assert_equal "1 minute", distance_of_time_in_words(0, 59)
assert_equal "about 1 hour", distance_of_time_in_words(60*60, 0)
assert_equal "about 3 years", distance_of_time_in_words(10**8)
assert_equal "about 3 years", distance_of_time_in_words(0, 10**8)
end

def test_distance_in_words_with_times
assert_equal "1 minute", distance_of_time_in_words(30.seconds)
assert_equal "1 minute", distance_of_time_in_words(59.seconds)
assert_equal "2 minutes", distance_of_time_in_words(119.seconds)
assert_equal "2 minutes", distance_of_time_in_words(1.minute + 59.seconds)
assert_equal "3 minutes", distance_of_time_in_words(2.minute + 30.seconds)
assert_equal "44 minutes", distance_of_time_in_words(44.minutes + 29.seconds)
assert_equal "about 1 hour", distance_of_time_in_words(44.minutes + 30.seconds)
assert_equal "about 1 hour", distance_of_time_in_words(60.minutes)

# include seconds
assert_equal "half a minute", distance_of_time_in_words(39.seconds, 0, true)
assert_equal "less than a minute", distance_of_time_in_words(40.seconds, 0, true)
assert_equal "less than a minute", distance_of_time_in_words(59.seconds, 0, true)
assert_equal "1 minute", distance_of_time_in_words(60.seconds, 0, true)
end

def test_time_ago_in_words
Expand Down

0 comments on commit 4afdd97

Please sign in to comment.