Class: ReeDatetime::DistanceOfTimeInWords

Inherits:
Object
  • Object
show all
Includes:
Ree::FnDSL
Defined in:
lib/ree_lib/packages/ree_datetime/package/ree_datetime/functions/distance_of_time_in_words.rb

Constant Summary collapse

MINUTES_IN_YEAR =
525600
MINUTES_IN_QUARTER_YEAR =
131400
MINUTES_IN_THREE_QUARTERS_YEAR =
394200
DEFAULT =
{
  include_seconds: false,
  locale: :en
}

Instance Method Summary collapse

Instance Method Details

#call(start_time, end_time, **opts) ⇒ Object

Raises:

  • (ArgumentError)


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/ree_lib/packages/ree_datetime/package/ree_datetime/functions/distance_of_time_in_words.rb', line 100

def call(start_time, end_time, **opts)
  opts = DEFAULT.merge(opts)

  distance_in_minutes = ((end_time.to_time.to_i - start_time.to_time.to_i) / 60.0).round
  distance_in_seconds = (end_time.to_time.to_i - start_time.to_time.to_i).round

  raise ArgumentError, "end_time small than start_time" if distance_in_seconds < 0
  
  case distance_in_minutes
  when 0..1
    return distance_in_minutes == 0 ?
           t('datetime.human.distance_in_words.less_than_x_minutes', count: 1, locale: opts[:locale], default_by_locale: :en) :
           t('datetime.human.distance_in_words.x_minutes', count: distance_in_minutes, locale: opts[:locale], default_by_locale: :en) unless opts[:include_seconds]

    case distance_in_seconds
    when 0..4   then t('datetime.human.distance_in_words.less_than_x_seconds', count: 5, locale: opts[:locale], default_by_locale: :en)
    when 5..9   then t('datetime.human.distance_in_words.less_than_x_seconds', count: 10, locale: opts[:locale], default_by_locale: :en)
    when 10..19 then t('datetime.human.distance_in_words.less_than_x_seconds',count: 20, locale: opts[:locale], default_by_locale: :en)
    when 20..39 then t('datetime.human.distance_in_words.half_a_minute', locale: opts[:locale], default_by_locale: :en)
    when 40..59 then t('datetime.human.distance_in_words.less_than_x_minutes', count: 1, locale: opts[:locale], default_by_locale: :en)
    else             t('datetime.human.distance_in_words.x_minutes', count: 1, locale: opts[:locale], default_by_locale: :en)
    end

  when 2...45           then t('datetime.human.distance_in_words.x_minutes', count: distance_in_minutes, locale: opts[:locale], default_by_locale: :en)
  when 45...90          then t('datetime.human.distance_in_words.about_x_hours', count: 1, locale: opts[:locale], default_by_locale: :en)
    # 90 mins up to 24 hours
  when 90...1440        then t('datetime.human.distance_in_words.about_x_hours',
                               count: (distance_in_minutes.to_f / 60.0).round, locale: opts[:locale], default_by_locale: :en)
    # 24 hours up to 42 hours
  when 1440...2520      then t('datetime.human.distance_in_words.x_days', count: 1, locale: opts[:locale], default_by_locale: :en)
    # 42 hours up to 30 days
  when 2520...43200     then t('datetime.human.distance_in_words.x_days', count: (distance_in_minutes.to_f / 1440.0).round, locale: opts[:locale], default_by_locale: :en)
    # 30 days up to 60 days
  when 43200...86400    then t('datetime.human.distance_in_words.about_x_months', count: (distance_in_minutes.to_f / 43200.0).round, locale: opts[:locale], default_by_locale: :en)
    # 60 days up to 365 days
  when 86400...525600   then t('datetime.human.distance_in_words.x_months', count: (distance_in_minutes.to_f / 43200.0).round, locale: opts[:locale], default_by_locale: :en)
  else
    start_year = start_time.year
    start_year += 1 if start_time.month >= 3
    end_year = end_time.year
    end_year -= 1 if end_time.month < 3
    leap_years = (start_year > end_year) ? 0 : (start_year..end_year).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 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
    remainder = (minutes_with_offset % MINUTES_IN_YEAR)
    distance_in_years = (minutes_with_offset.div MINUTES_IN_YEAR)

    if remainder < MINUTES_IN_QUARTER_YEAR
      t('datetime.human.distance_in_words.about_x_years', count: distance_in_years, locale: opts[:locale], default_by_locale: :en)
    elsif remainder < MINUTES_IN_THREE_QUARTERS_YEAR
      t('datetime.human.distance_in_words.over_x_years', count: distance_in_years, locale: opts[:locale], default_by_locale: :en)
    else
      t('datetime.human.distance_in_words.almost_x_years', count: distance_in_years + 1, locale: opts[:locale], default_by_locale: :en)
    end
  end
end