Reputation: 107718
I'm trying to make a "better" distance_of_time_in_words
for rails and so far I have this: http://github.com/radar/dotiw.
However, at the moment it chokes on months + years, as shown by the specs. I'm at a complete loss! Help?
Code added by Pax so no-one else has to search through github:
module ActionView
module Helpers
module DateHelper
def distance_of_time_in_words_hash(from_time, to_time)
output = HashWithIndifferentAccess.new
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 = from_time - to_time
# Get a positive number.
distance *= -1 if distance < 0
while distance > 0
if distance > 100000000000000
elsif distance >= 31449600
output[I18n.t(:years, :default => "years")], distance =
distance.divmod(31449600)
elsif distance >= 2419200
output[I18n.t(:months, :default => "months")], distance =
distance.divmod(2419200)
elsif distance >= 604800
output[I18n.t(:weeks, :default => "weeks")], distance =
distance.divmod(604800)
elsif distance >= 86400
output[I18n.t(:days, :default => "days")], distance =
distance.divmod(86400)
elsif distance >= 3600
output[I18n.t(:hours, :default => "hours")], distance =
distance.divmod(3600)
elsif distance >= 60
output[I18n.t(:minutes, :default => "minutes")], distance =
distance.divmod(60)
else
output[I18n.t(:seconds, :default => "seconds")] = distance.to_i
distance = 0
end
end
output
end
def distance_of_time_in_words(from_time, to_time, include_seconds = false,
options = {}, output_options = {})
hash = distance_of_time_in_words_hash(from_time, to_time)
hash.delete(:seconds) if !include_seconds
# Remove all the values that are nil.
time_measurements = [
I18n.t(:years, :default => "years"),
I18n.t(:months, :default => "months"),
I18n.t(:weeks, :default => "weeks"),
I18n.t(:days, :default => "days"),
I18n.t(:hours, :default => "hours"),
I18n.t(:minutes, :default => "minutes"),
I18n.t(:seconds, :default => "seconds")].delete_if do |key|
hash[key].nil?
end
output = []
time_measurements.each do |key|
name = hash[key] > 1 ? key : key.singularize
output += ["#{hash[key]} #{name}"]
end
output.to_sentence(output_options)
end
end
end
end
Upvotes: 1
Views: 4214
Reputation: 94113
It looks like you're trying to get the time difference in terms of all applicable units (ie. "2 years, 4 months, 7 days" instead of "2 years" which Rails' distance_of_time_in_words
gives)?
If so, check out In Rails, display time between two dates in English, another SO question about displaying time differences. My answer there should give you a good starting point for what you seem to be trying to do, and it wouldn't be hard to extend the method to include hours, minutes and seconds.
Upvotes: 2
Reputation: 881113
We too are at a complete loss. Perhaps you could make our lives easier by:
Then maybe we'll be able to do a better job.
One thing I've noticed straight up: there are not 2,419,200 seconds in any month other than February (and then only in non-leap years). Similarly, no year has 364 days.
I think you need to rethink how you're calculating the intervals.
Assuming that your "words" version of the duration can handle a little inaccuracy, at a bare minimum you should be using the averages for those figures (taking into account that a year is 365.2425 days which should be close enough for your purposes):
Upvotes: 2