dotiw 3.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DOTIW
4
+ module Methods
5
+ def distance_of_time_in_words_hash(from_time, to_time, options = {})
6
+ from_time = from_time.to_time if !from_time.is_a?(Time) && from_time.respond_to?(:to_time)
7
+ to_time = to_time.to_time if !to_time.is_a?(Time) && to_time.respond_to?(:to_time)
8
+
9
+ DOTIW::TimeHash.new(nil, from_time, to_time, options).to_hash
10
+ end
11
+
12
+ def distance_of_time(seconds, options = {})
13
+ options[:include_seconds] ||= true
14
+ _display_time_in_words DOTIW::TimeHash.new(seconds, nil, nil, options).to_hash, options
15
+ end
16
+
17
+ def distance_of_time_in_words(from_time, to_time = 0, include_seconds_or_options = {}, options = {})
18
+ if include_seconds_or_options.is_a?(Hash)
19
+ options = include_seconds_or_options
20
+ else
21
+ options[:include_seconds] ||= !!include_seconds_or_options
22
+ end
23
+ return distance_of_time(from_time, options) if to_time == 0
24
+
25
+ hash = distance_of_time_in_words_hash(from_time, to_time, options)
26
+ _display_time_in_words(hash, options)
27
+ end
28
+
29
+ def time_ago_in_words(from_time, include_seconds_or_options = {})
30
+ distance_of_time_in_words(from_time, Time.current, include_seconds_or_options)
31
+ end
32
+
33
+ private
34
+
35
+ def _display_time_in_words(hash, options = {})
36
+ options.reverse_merge!(
37
+ include_seconds: false
38
+ ).symbolize_keys!
39
+
40
+ include_seconds = options.delete(:include_seconds)
41
+ hash.delete(:seconds) if !include_seconds && hash[:minutes]
42
+
43
+ options[:except] = Array.wrap(options[:except]).map!(&:to_sym) if options[:except]
44
+ options[:only] = Array.wrap(options[:only]).map!(&:to_sym) if options[:only]
45
+
46
+ # Remove all the values that are nil or excluded. Keep the required ones.
47
+ hash.delete_if do |key, value|
48
+ value.nil? || value.zero? ||
49
+ options[:except]&.include?(key) ||
50
+ (options[:only] && !options[:only].include?(key))
51
+ end
52
+
53
+ i18n_scope = options.delete(:scope) || DOTIW::DEFAULT_I18N_SCOPE
54
+ if hash.empty?
55
+ fractions = DOTIW::TimeHash::TIME_FRACTIONS
56
+ fractions &= options[:only] if options[:only]
57
+ fractions -= options[:except] if options[:except]
58
+
59
+ I18n.with_options locale: options[:locale], scope: i18n_scope do |locale|
60
+ # e.g. try to format 'less than 1 days', fallback to '0 days'
61
+ return locale.translate :less_than_x,
62
+ distance: locale.translate(fractions.first, count: 1),
63
+ default: locale.translate(fractions.first, count: 0)
64
+ end
65
+ end
66
+
67
+ output = []
68
+ I18n.with_options locale: options[:locale], scope: i18n_scope do |locale|
69
+ output = hash.map { |key, value| locale.t(key, count: value) }
70
+ end
71
+
72
+ options.delete(:except)
73
+ options.delete(:only)
74
+ highest_measures = options.delete(:highest_measures)
75
+ highest_measures = 1 if options.delete(:highest_measure_only)
76
+ output = output[0...highest_measures] if highest_measures
77
+
78
+ options[:words_connector] ||= I18n.translate :'datetime.dotiw.words_connector',
79
+ default: :'support.array.words_connector',
80
+ locale: options[:locale]
81
+ options[:two_words_connector] ||= I18n.translate :'datetime.dotiw.two_words_connector',
82
+ default: :'support.array.two_words_connector',
83
+ locale: options[:locale]
84
+ options[:last_word_connector] ||= I18n.translate :'datetime.dotiw.last_word_connector',
85
+ default: :'support.array.last_word_connector',
86
+ locale: options[:locale]
87
+
88
+ output.to_sentence(options)
89
+ end
90
+ end
91
+ end # DOTIW
@@ -1,25 +1,25 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module DOTIW
4
4
  class TimeHash
5
- TIME_FRACTIONS = [:seconds, :minutes, :hours, :days, :months, :years]
6
-
7
- attr_accessor :distance, :smallest, :largest, :from_time, :to_time
8
-
9
- def initialize(distance, from_time = nil, to_time = nil, options = {})
10
- self.output = ActiveSupport::OrderedHash.new
11
- self.options = options
12
- self.distance = distance
13
- self.from_time = from_time || Time.now
14
- self.to_time = to_time || (@to_time_not_given = true && self.from_time + self.distance.seconds)
15
- self.smallest, self.largest = [self.from_time, self.to_time].minmax
16
- self.to_time += 1.hour if @to_time_not_given && self.smallest.dst? && !self.largest.dst?
17
- self.to_time -= 1.hour if @to_time_not_given && !self.smallest.dst? && self.largest.dst?
18
- self.smallest, self.largest = [self.from_time, self.to_time].minmax
19
- self.distance ||= begin
5
+ TIME_FRACTIONS = %i[seconds minutes hours days weeks months years].freeze
6
+
7
+ attr_reader :distance, :smallest, :largest, :from_time, :to_time
8
+
9
+ def initialize(distance, from_time, to_time = nil, options = {})
10
+ @output = {}
11
+ @options = options
12
+ @distance = distance
13
+ @from_time = from_time || Time.current
14
+ @to_time = to_time || (@to_time_not_given = true && @from_time + distance.seconds)
15
+ @smallest, @largest = [@from_time, @to_time].minmax
16
+ @to_time += 1.hour if @to_time_not_given && smallest.dst? && !largest.dst?
17
+ @to_time -= 1.hour if @to_time_not_given && !smallest.dst? && largest.dst?
18
+ @smallest, @largest = [@from_time, @to_time].minmax
19
+ @distance ||= begin
20
20
  d = largest - smallest
21
- d -= 1.hour if self.smallest.dst? && !self.largest.dst?
22
- d += 1.hour if !self.smallest.dst? && self.largest.dst?
21
+ d -= 1.hour if smallest.dst? && !largest.dst?
22
+ d += 1.hour if !smallest.dst? && largest.dst?
23
23
  d
24
24
  end
25
25
 
@@ -30,16 +30,16 @@ module DOTIW
30
30
  output
31
31
  end
32
32
 
33
- private
34
- attr_accessor :options, :output
33
+ private
34
+
35
+ attr_reader :options, :output
35
36
 
36
37
  def build_time_hash
37
38
  if accumulate_on = options.delete(:accumulate_on)
38
39
  accumulate_on = accumulate_on.to_sym
39
- if accumulate_on == :years
40
- return build_time_hash
41
- end
42
- TIME_FRACTIONS.index(accumulate_on).downto(0) { |i| self.send("build_#{TIME_FRACTIONS[i]}") }
40
+ return build_time_hash if accumulate_on == :years
41
+
42
+ TIME_FRACTIONS.index(accumulate_on).downto(0) { |i| send("build_#{TIME_FRACTIONS[i]}") }
43
43
  else
44
44
  while distance > 0
45
45
  if distance < 1.minute
@@ -48,10 +48,12 @@ module DOTIW
48
48
  build_minutes
49
49
  elsif distance < 1.day
50
50
  build_hours
51
- elsif distance < 28.days
51
+ elsif distance < 7.days
52
52
  build_days
53
- else # greater than a month
54
- build_years_months_days
53
+ elsif distance < 28.days
54
+ build_weeks
55
+ else # greater than a week
56
+ build_years_months_weeks_days
55
57
  end
56
58
  end
57
59
  end
@@ -61,43 +63,67 @@ module DOTIW
61
63
 
62
64
  def build_seconds
63
65
  output[:seconds] = distance.to_i
64
- self.distance = 0
66
+ @distance = 0
65
67
  end
66
68
 
67
69
  def build_minutes
68
- output[:minutes], self.distance = distance.divmod(1.minute)
70
+ output[:minutes], @distance = distance.divmod(1.minute.to_i)
69
71
  end
70
72
 
71
73
  def build_hours
72
- output[:hours], self.distance = distance.divmod(1.hour)
74
+ output[:hours], @distance = distance.divmod(1.hour.to_i)
73
75
  end
74
76
 
75
77
  def build_days
76
- output[:days], self.distance = distance.divmod(1.day) if output[:days].nil?
78
+ output[:days], @distance = distance.divmod(1.day.to_i) unless output[:days]
79
+ end
80
+
81
+ def build_weeks
82
+ output[:weeks], @distance = distance.divmod(1.week.to_i) unless output[:weeks]
77
83
  end
78
84
 
79
85
  def build_months
80
- build_years_months_days
86
+ build_years_months_weeks_days
81
87
 
82
88
  if (years = output.delete(:years)) > 0
83
89
  output[:months] += (years * 12)
84
90
  end
85
91
  end
86
92
 
87
- def build_years_months_days
93
+ def build_years_months_weeks_days
88
94
  months = (largest.year - smallest.year) * 12 + (largest.month - smallest.month)
89
95
  years, months = months.divmod(12)
90
96
 
91
97
  days = largest.day - smallest.day
92
98
 
99
+ weeks, days = days.divmod(7)
100
+
93
101
  # Will otherwise incorrectly say one more day if our range goes over a day.
94
102
  days -= 1 if largest.hour < smallest.hour
95
103
 
96
104
  if days < 0
97
- # Convert the last month to days and add to total
105
+ # Convert a week to days and add to total
106
+ weeks -= 1
107
+ days += 7
108
+ end
109
+
110
+ if weeks < 0
111
+ # Convert the last month to a week and add to total
98
112
  months -= 1
99
- last_month = largest.advance(:months => -1)
100
- days += Time.days_in_month(last_month.month, last_month.year)
113
+ last_month = largest.advance(months: -1)
114
+ days_in_month = Time.days_in_month(last_month.month, last_month.year)
115
+ weeks += days_in_month / 7
116
+ days += days_in_month % 7
117
+ if days >= 7
118
+ days -= 7
119
+ weeks += 1
120
+ end
121
+
122
+ if weeks == -1
123
+ months -= 1
124
+ weeks = 4
125
+ days -= 4
126
+ end
101
127
  end
102
128
 
103
129
  if months < 0
@@ -108,11 +134,12 @@ module DOTIW
108
134
 
109
135
  output[:years] = years
110
136
  output[:months] = months
137
+ output[:weeks] = weeks
111
138
  output[:days] = days
112
139
 
113
- total_days, self.distance = distance.abs.divmod(1.day)
140
+ total_days, @distance = distance.abs.divmod(1.day.to_i)
114
141
 
115
- [total_days, self.distance]
142
+ [total_days, @distance]
116
143
  end
117
144
  end # TimeHash
118
145
  end # DOTIW
@@ -1,5 +1,5 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module DOTIW
4
- VERSION = "3.0"
4
+ VERSION = '5.0.0'
5
5
  end
@@ -1,13 +1,17 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe "A better distance_of_time_in_words" do
6
- include ActionView::Helpers::DateHelper
7
- include ActionView::Helpers::TextHelper
8
- include ActionView::Helpers::NumberHelper
5
+ describe 'A better distance_of_time_in_words' do
6
+ if defined?(ActionView)
7
+ include ActionView::Helpers::DateHelper
8
+ include ActionView::Helpers::TextHelper
9
+ include ActionView::Helpers::NumberHelper
10
+ else
11
+ include DOTIW::Methods
12
+ end
9
13
 
10
- START_TIME = "01-08-2009".to_time
14
+ START_TIME = '01-08-2009'.to_time
11
15
 
12
16
  before do
13
17
  I18n.locale = :en
@@ -15,269 +19,314 @@ describe "A better distance_of_time_in_words" do
15
19
  allow(Time.zone).to receive(:now).and_return(START_TIME)
16
20
  end
17
21
 
18
- describe "distance of time" do
19
- fragments = [
20
- [0.5.minutes, "30 seconds"],
21
- [4.5.minutes, "4 minutes and 30 seconds"],
22
- [5.minutes.to_i, "5 minutes"],
23
- [10.minutes.to_i, "10 minutes"],
24
- [1.hour.to_i, "1 hour"],
25
- [1.hour + 30.seconds, "1 hour and 30 seconds"],
26
- [4.weeks.to_i, "28 days"],
27
- [24.weeks.to_i, "5 months and 15 days"]
28
- ]
29
- fragments.each do |number, result|
22
+ describe 'distance of time' do
23
+ [
24
+ [0.5.minutes, '30 seconds'],
25
+ [4.5.minutes, '4 minutes and 30 seconds'],
26
+ [5.minutes, '5 minutes'],
27
+ [10.minutes, '10 minutes'],
28
+ [1.hour, '1 hour'],
29
+ [1.hour + 30.seconds, '1 hour and 30 seconds'],
30
+ [4.weeks, '4 weeks'],
31
+ [4.weeks + 2.days, '4 weeks and 2 days'],
32
+ [24.weeks, '5 months, 2 weeks, and 1 day']
33
+ ].each do |number, result|
30
34
  it "#{number} == #{result}" do
31
35
  expect(distance_of_time(number)).to eq(result)
32
36
  end
33
37
  end
34
38
 
35
- describe "with options" do
36
- it "except:seconds should skip seconds" do
37
- expect(distance_of_time(1.2.minute, except: 'seconds')).to eq("1 minute")
38
- expect(distance_of_time(2.5.hours + 30.seconds, except: 'seconds')).to eq("2 hours and 30 minutes")
39
+ describe 'with options' do
40
+ it 'except:seconds should skip seconds' do
41
+ expect(distance_of_time(1.2.minute, except: 'seconds')).to eq('1 minute')
42
+ expect(distance_of_time(2.5.hours + 30.seconds, except: 'seconds')).to eq('2 hours and 30 minutes')
39
43
  end
40
44
 
41
- it "except:seconds har higher presedence than include_seconds:true" do
45
+ it 'except:seconds has higher precedence than include_seconds:true' do
42
46
  expect(distance_of_time(1.2.minute, include_seconds: true, except: 'seconds')).to eq('1 minute')
43
47
  end
44
48
  end
45
-
46
49
  end
47
50
 
48
- describe "hash version" do
49
- describe "giving correct numbers of" do
50
-
51
- [:years, :months, :days, :minutes, :seconds].each do |name|
51
+ describe 'hash version' do
52
+ describe 'giving correct numbers of' do
53
+ %i[years months weeks days minutes seconds].each do |name|
52
54
  describe name do
53
- it "exactly" do
55
+ it 'exactly' do
54
56
  hash = distance_of_time_in_words_hash(START_TIME, START_TIME + 1.send(name))
55
57
  expect(hash[name]).to eq(1)
56
58
  end
57
59
 
58
- it "two" do
60
+ it 'two' do
59
61
  hash = distance_of_time_in_words_hash(START_TIME, START_TIME + 2.send(name))
60
62
  expect(hash[name]).to eq(2)
61
63
  end
62
64
  end
63
65
  end
64
66
 
65
- it "should be happy with lots of measurements" do
66
- hash = distance_of_time_in_words_hash(START_TIME,
67
- START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds)
67
+ it 'should be happy with lots of measurements' do
68
+ hash = distance_of_time_in_words_hash(
69
+ START_TIME,
70
+ START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds
71
+ )
68
72
  expect(hash[:years]).to eq(1)
69
73
  expect(hash[:months]).to eq(2)
70
- expect(hash[:days]).to eq(3)
71
- expect(hash[:hours]).to eq(4)
72
- expect(hash[:minutes]).to eq(5)
73
- expect(hash[:seconds]).to eq(6)
74
+ expect(hash[:weeks]).to eq(3)
75
+ expect(hash[:days]).to eq(4)
76
+ expect(hash[:hours]).to eq(5)
77
+ expect(hash[:minutes]).to eq(6)
78
+ expect(hash[:seconds]).to eq(7)
74
79
  end
75
80
  end
76
81
  end
77
82
 
78
- describe "real version" do
79
- it "debe hablar español" do
80
- expect(distance_of_time_in_words(START_TIME, START_TIME + 1.days, :locale => :es)).to eq("un día")
81
- expect(distance_of_time_in_words(START_TIME, START_TIME + 5.days, :locale => :es)).to eq("5 días")
83
+ describe 'real version' do
84
+ it 'debe hablar español' do
85
+ expect(distance_of_time_in_words(START_TIME, START_TIME + 1.days, locale: :es)).to eq('un día')
86
+ expect(distance_of_time_in_words(START_TIME, START_TIME + 5.days, locale: :es)).to eq('5 días')
82
87
  end
83
88
 
84
89
  it "deve parlare l'italiano" do
85
- expect(distance_of_time_in_words(START_TIME, START_TIME + 1.days, true, :locale => :it)).to eq("un giorno")
86
- expect(distance_of_time_in_words(START_TIME, START_TIME + 5.days, true, :locale => :it)).to eq("5 giorni")
90
+ expect(distance_of_time_in_words(START_TIME, START_TIME + 1.days, true, locale: :it)).to eq('un giorno')
91
+ expect(distance_of_time_in_words(START_TIME, START_TIME + 5.days, true, locale: :it)).to eq('5 giorni')
87
92
  end
88
93
 
89
- fragments = [
90
- [START_TIME, START_TIME + 5.days + 3.minutes, "5 days and 3 minutes"],
91
- [START_TIME, START_TIME + 1.minute, "1 minute"],
92
- [START_TIME, START_TIME + 3.years, "3 years"],
93
- [START_TIME, START_TIME + 10.years, "10 years"],
94
- [START_TIME, START_TIME + 10.years, "10 years"],
95
- [START_TIME, START_TIME + 3.hour, "3 hours"],
96
- [START_TIME, START_TIME + 13.months, "1 year and 1 month"],
94
+ [
95
+ [START_TIME, START_TIME + 5.days + 3.minutes, '5 days and 3 minutes'],
96
+ [START_TIME, START_TIME + 1.minute, '1 minute'],
97
+ [START_TIME, START_TIME + 3.years, '3 years'],
98
+ [START_TIME, START_TIME + 10.years, '10 years'],
99
+ [START_TIME, START_TIME + 8.months, '8 months'],
100
+ [START_TIME, START_TIME + 3.hour, '3 hours'],
101
+ [START_TIME, START_TIME + 13.months, '1 year and 1 month'],
97
102
  # Any numeric sequence is merely coincidental.
98
- [START_TIME, START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds, "1 year, 2 months, 3 days, 4 hours, 5 minutes, and 6 seconds"],
99
- ["2009-3-16".to_time, "2008-4-14".to_time, "11 months and 2 days"],
100
- ["2009-3-16".to_time + 1.minute, "2008-4-14".to_time, "11 months, 2 days, and 1 minute"],
101
- ["2009-4-14".to_time, "2008-3-16".to_time, "1 year and 29 days"],
102
- ["2009-2-01".to_time, "2009-3-01".to_time, "1 month"],
103
- ["2008-2-01".to_time, "2008-3-01".to_time, "1 month"]
104
- ]
105
- fragments.each do |start, finish, output|
103
+ [START_TIME, START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds, '1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds'],
104
+ ['2009-3-16'.to_time, '2008-4-14'.to_time, '11 months and 2 days'],
105
+ ['2009-3-16'.to_time + 1.minute, '2008-4-14'.to_time, '11 months, 2 days, and 1 minute'],
106
+ ['2009-4-14'.to_time, '2008-3-16'.to_time, '1 year, 4 weeks, and 1 day'],
107
+ ['2009-2-01'.to_time, '2009-3-01'.to_time, '1 month'],
108
+ ['2008-2-01'.to_time, '2008-3-01'.to_time, '1 month'],
109
+ [Date.parse('31.03.2015').to_time, Time.parse('01.03.2016'), '10 months, 4 weeks, and 2 days'],
110
+ [Date.new(2014, 1, 31), Date.new(2014, 3, 1), '4 weeks and 1 day'],
111
+ ['2008-2-01'.to_time, '2008-3-01'.to_time, '1 month'],
112
+ ['2014-1-31'.to_time, '2014-3-01'.to_time, '4 weeks and 1 day'],
113
+ ['2014-1-31'.to_time, '2014-3-02'.to_time, '4 weeks and 2 days'],
114
+ ['2016-1-31'.to_time, '2016-3-01'.to_time, '4 weeks and 2 days'],
115
+ ['2016-1-31'.to_time, '2016-3-02'.to_time, '1 month']
116
+ ].each do |start, finish, output|
106
117
  it "should be #{output}" do
107
118
  expect(distance_of_time_in_words(start, finish, true)).to eq(output)
119
+ expect(distance_of_time_in_words(finish, start, true)).to eq(output)
120
+ end
121
+ end
122
+
123
+ [
124
+ [Time.zone.now, Time.zone.now + 1.day - 1.minute, '23 hours and 59 minutes'],
125
+ [Time.zone.now, Time.zone.now + 15.days - 1.minute, '14 days, 23 hours, and 59 minutes'],
126
+ [Time.zone.now, Time.zone.now + 29.days - 1.minute, '28 days, 23 hours, and 59 minutes'],
127
+ [Time.zone.now, Time.zone.now + 30.days - 1.minute, '29 days, 23 hours, and 59 minutes'],
128
+ [Time.zone.now, Time.zone.now + 31.days - 1.minute, '30 days, 23 hours, and 59 minutes'],
129
+ [Time.zone.now, Time.zone.now + 32.days - 1.minute, '31 days, 23 hours, and 59 minutes'],
130
+ [Time.zone.now, Time.zone.now + 33.days - 1.minute, '32 days, 23 hours, and 59 minutes']
131
+ ].each do |start, finish, output|
132
+ it "should be #{output}" do
133
+ expect(distance_of_time_in_words(start, finish, accumulate_on: 'days')).to eq(output)
134
+ end
135
+ end
136
+
137
+ [
138
+ [Time.at(1), Time.at(100), '1 minute'],
139
+ [DateTime.now, DateTime.now + 1.minute, '1 minute'],
140
+ [Date.new(2000, 1, 2), Date.new(2000, 1, 3), '1 day'],
141
+ [Time.at(DateTime.now), DateTime.now + 1.minute, '1 minute']
142
+ ].each do |start, finish, output|
143
+ it "should be #{output}" do
144
+ expect(distance_of_time_in_words(start, finish)).to eq(output)
108
145
  end
109
146
  end
110
147
 
111
- describe "accumulate on" do
112
- fragments = [
148
+ describe 'accumulate on' do
149
+ [
113
150
  [START_TIME,
114
151
  START_TIME + 10.minute,
115
152
  :seconds,
116
- "600 seconds"],
153
+ '600 seconds'],
117
154
  [START_TIME,
118
155
  START_TIME + 10.hour + 10.minute + 1.second,
119
156
  :minutes,
120
- "610 minutes and 1 second"],
157
+ '610 minutes and 1 second'],
121
158
  [START_TIME,
122
- START_TIME + 2.day + 10000.hour + 10.second,
159
+ START_TIME + 2.day + 10_000.hour + 10.second,
123
160
  :hours,
124
- "10048 hours and 10 seconds"],
161
+ '10048 hours and 10 seconds'],
125
162
  [START_TIME,
126
- START_TIME + 2.day + 10000.hour + 10.second,
163
+ START_TIME + 2.day + 10_000.hour + 10.second,
127
164
  :days,
128
- "418 days, 16 hours, and 10 seconds"],
165
+ '418 days, 16 hours, and 10 seconds'],
166
+ [START_TIME,
167
+ START_TIME + 2.day + 10_000.hour + 10.second,
168
+ :weeks,
169
+ '59 weeks, 5 days, 16 hours, and 10 seconds'],
129
170
  [START_TIME,
130
- START_TIME + 2.day + 10000.hour + 10.second,
171
+ START_TIME + 2.day + 10_000.hour + 10.second,
131
172
  :months,
132
- "13 months, 22 days, 16 hours, and 10 seconds"],
133
- ["2015-1-15".to_time, "2016-3-15".to_time, :months, "14 months"]
134
-
135
- ]
136
- fragments.each do |start, finish, accumulator, output|
173
+ '13 months, 3 weeks, 1 day, 16 hours, and 10 seconds'],
174
+ ['2015-1-15'.to_time, '2016-3-15'.to_time, :months, '14 months']
175
+ ].each do |start, finish, accumulator, output|
137
176
  it "should be #{output}" do
138
- expect(distance_of_time_in_words(start, finish, true, :accumulate_on => accumulator)).to eq(output)
177
+ expect(distance_of_time_in_words(start, finish, true, accumulate_on: accumulator)).to eq(output)
139
178
  end
140
179
  end
141
180
  end # :accumulate_on
142
181
 
143
- describe "without finish time" do
182
+ describe 'without finish time' do
144
183
  # A missing finish argument should default to zero, essentially returning
145
184
  # the equivalent of distance_of_time in order to be backwards-compatible
146
185
  # with the original rails distance_of_time_in_words helper.
147
- fragments = [
148
- [5.minutes.to_i, "5 minutes"],
149
- [10.minutes.to_i, "10 minutes"],
150
- [1.hour.to_i, "1 hour"],
151
- [4.weeks.to_i, "28 days"],
152
- [24.weeks.to_i, "5 months and 15 days"]
153
- ]
154
- fragments.each do |start, output|
186
+ [
187
+ [5.minutes.to_i, '5 minutes'],
188
+ [10.minutes.to_i, '10 minutes'],
189
+ [1.hour.to_i, '1 hour'],
190
+ [6.days.to_i, '6 days'],
191
+ [4.weeks.to_i, '4 weeks'],
192
+ [24.weeks.to_i, '5 months, 2 weeks, and 1 day']
193
+ ].each do |start, output|
155
194
  it "should be #{output}" do
156
195
  expect(distance_of_time_in_words(start)).to eq(output)
157
196
  end
158
197
  end
159
198
  end
160
-
161
199
  end
162
200
 
163
- describe "with output options" do
164
- fragments = [
201
+ describe 'with output options' do
202
+ [
165
203
  # Any numeric sequence is merely coincidental.
166
204
  [START_TIME,
167
- START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds,
168
- { :words_connector => " - " },
169
- "1 year - 2 months - 3 days - 4 hours - 5 minutes, and 6 seconds"],
205
+ START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
206
+ { words_connector: ' - ' },
207
+ '1 year - 2 months - 3 weeks - 4 days - 5 hours - 6 minutes, and 7 seconds'],
170
208
  [START_TIME,
171
209
  START_TIME + 5.minutes + 6.seconds,
172
- { :two_words_connector => " - " },
173
- "5 minutes - 6 seconds"],
210
+ { two_words_connector: ' - ' },
211
+ '5 minutes - 6 seconds'],
174
212
  [START_TIME,
175
- START_TIME + 4.hours + 5.minutes + 6.seconds,
176
- { :last_word_connector => " - " },
177
- "4 hours, 5 minutes - 6 seconds"],
213
+ START_TIME + 4.hours + 5.minutes + 6.seconds,
214
+ { last_word_connector: ' - ' },
215
+ '4 hours, 5 minutes - 6 seconds'],
178
216
  [START_TIME,
179
217
  START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds,
180
- { :except => "minutes" },
181
- "1 year, 2 months, 3 days, 4 hours, and 6 seconds"],
218
+ { except: 'minutes' },
219
+ '1 year, 2 months, 3 days, 4 hours, and 6 seconds'],
182
220
  [START_TIME,
183
221
  START_TIME + 1.hour + 1.minute,
184
- { :except => "minutes"}, "1 hour"],
222
+ { except: 'minutes' }, '1 hour'],
185
223
  [START_TIME,
186
224
  START_TIME + 1.hour + 1.day + 1.minute,
187
- { :except => ["minutes", "hours"]},
188
- "1 day"],
225
+ { except: %w[minutes hours] },
226
+ '1 day'],
189
227
  [START_TIME,
190
228
  START_TIME + 1.hour + 1.day + 1.minute,
191
- { :only => ["minutes", "hours"]},
192
- "1 hour and 1 minute"],
229
+ { only: %w[minutes hours] },
230
+ '1 hour and 1 minute'],
193
231
  [START_TIME,
194
- START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds,
195
- { :vague => true },
196
- "about 1 year"],
232
+ START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
233
+ { except: 'minutes' },
234
+ '1 year, 2 months, 3 weeks, 4 days, 5 hours, and 7 seconds'],
197
235
  [START_TIME,
198
- START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds,
199
- { :vague => "Yes please" },
200
- "about 1 year"],
201
- [START_TIME,
202
- START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds,
203
- { :vague => false },
204
- "1 year, 2 months, 3 days, 4 hours, 5 minutes, and 6 seconds"],
205
- [START_TIME,
206
- START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds,
207
- { :vague => nil },
208
- "1 year, 2 months, 3 days, 4 hours, 5 minutes, and 6 seconds"],
209
- [START_TIME,
210
- START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds,
211
- { :except => "minutes" },
212
- "1 year, 2 months, 3 days, 4 hours, and 6 seconds"],
213
- [START_TIME,
214
- START_TIME + 1.hour + 2.minutes + 3.seconds,
215
- { :highest_measure_only => true },
216
- "1 hour"],
236
+ START_TIME + 1.hour + 2.minutes + 3.seconds,
237
+ { highest_measure_only: true },
238
+ '1 hour'],
217
239
  [START_TIME,
218
240
  START_TIME + 1.hours + 2.minutes + 3.seconds,
219
- { :highest_measures => 1 },
220
- "1 hour"],
241
+ { highest_measures: 1 },
242
+ '1 hour'],
221
243
  [START_TIME,
222
244
  START_TIME + 2.year + 3.months + 4.days + 5.hours + 6.minutes + 7.seconds,
223
- { :highest_measures => 3 },
224
- "2 years, 3 months, and 4 days"],
245
+ { highest_measures: 3 },
246
+ '2 years, 3 months, and 4 days'],
225
247
  [START_TIME,
226
248
  START_TIME + 2.year + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
227
- { :highest_measures => 2 },
228
- "2 years and 25 days"],
249
+ { highest_measures: 2 },
250
+ '2 years and 3 weeks'],
229
251
  [START_TIME,
230
252
  START_TIME + 4.days + 6.minutes + 7.seconds,
231
- { :highest_measures => 3 },
232
- "4 days, 6 minutes, and 7 seconds"],
253
+ { highest_measures: 3 },
254
+ '4 days, 6 minutes, and 7 seconds'],
233
255
  [START_TIME,
234
256
  START_TIME + 1.year + 2.weeks,
235
- { :highest_measures => 3 },
236
- "1 year and 14 days"],
257
+ { highest_measures: 3 },
258
+ '1 year and 2 weeks'],
237
259
  [START_TIME,
238
260
  START_TIME + 1.days,
239
- { :only => [:years, :months] },
240
- "less than 1 month"],
261
+ { only: %i[years months] },
262
+ 'less than 1 month'],
241
263
  [START_TIME,
242
264
  START_TIME + 5.minutes,
243
- { :except => [:hours, :minutes, :seconds] },
244
- "less than 1 day"],
265
+ { except: %i[hours minutes seconds] },
266
+ 'less than 1 day'],
245
267
  [START_TIME,
246
268
  START_TIME + 1.days,
247
- { :highest_measures => 1, :only => [:years, :months] },
248
- "less than 1 month"]
249
- ]
250
- fragments.each do |start, finish, options, output|
269
+ { highest_measures: 1, only: %i[years months] },
270
+ 'less than 1 month']
271
+ ].each do |start, finish, options, output|
251
272
  it "should be #{output}" do
252
273
  expect(distance_of_time_in_words(start, finish, true, options)).to eq(output)
253
274
  end
254
275
  end
255
276
 
256
- describe "include_seconds" do
257
- it "is ignored if only seconds have passed" do
258
- expect(distance_of_time_in_words(START_TIME, START_TIME + 1.second, false)).to eq("1 second")
277
+ if defined?(ActionView)
278
+ describe 'ActionView' do
279
+ [
280
+ [START_TIME,
281
+ START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
282
+ { vague: true },
283
+ 'about 1 year'],
284
+ [START_TIME,
285
+ START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
286
+ { vague: 'Yes please' },
287
+ 'about 1 year'],
288
+ [START_TIME,
289
+ START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
290
+ { vague: false },
291
+ '1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds'],
292
+ [START_TIME,
293
+ START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
294
+ { vague: nil },
295
+ '1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds']
296
+ ].each do |start, finish, options, output|
297
+ it "should be #{output}" do
298
+ expect(distance_of_time_in_words(start, finish, true, options)).to eq(output)
299
+ end
300
+ end
259
301
  end
302
+ end
260
303
 
261
- it "removes seconds in all other cases" do
304
+ describe 'include_seconds' do
305
+ it 'is ignored if only seconds have passed' do
306
+ expect(distance_of_time_in_words(START_TIME, START_TIME + 1.second, false)).to eq('1 second')
307
+ end
308
+
309
+ it 'removes seconds in all other cases' do
262
310
  expect(distance_of_time_in_words(START_TIME,
263
- START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds,
264
- false)).to eq("1 year, 2 months, 3 days, 4 hours, and 5 minutes")
311
+ START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
312
+ false)).to eq('1 year, 2 months, 3 weeks, 4 days, 5 hours, and 6 minutes')
265
313
  end
266
314
  end # include_seconds
267
315
  end
268
316
 
269
- describe "percentage of time" do
270
- def time_in_percent(options = {})
271
- distance_of_time_in_percent("04-12-2009".to_time, "29-01-2010".to_time, "04-12-2010".to_time, options)
272
- end
317
+ if defined?(ActionView)
318
+ describe 'percentage of time' do
319
+ def time_in_percent(options = {})
320
+ distance_of_time_in_percent('04-12-2009'.to_time, '29-01-2010'.to_time, '04-12-2010'.to_time, options)
321
+ end
273
322
 
274
- it "calculates 15%" do
275
- expect(time_in_percent).to eq("15%")
276
- end
323
+ it 'calculates 15%' do
324
+ expect(time_in_percent).to eq('15%')
325
+ end
277
326
 
278
- it "calculates 15.3%" do
279
- expect(time_in_percent(:precision => 1)).to eq("15.3%")
327
+ it 'calculates 15.3%' do
328
+ expect(time_in_percent(precision: 1)).to eq('15.3%')
329
+ end
280
330
  end
281
331
  end
282
-
283
332
  end