dotiw 4.0.0 → 5.3.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.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +45 -0
- data/.rspec +2 -0
- data/Appraisals +19 -0
- data/CHANGELOG.md +38 -6
- data/Gemfile +2 -0
- data/MIT-LICENSE +1 -1
- data/README.markdown +151 -63
- data/Rakefile +3 -1
- data/benchmarks/time_hash_bench.rb +19 -0
- data/dotiw.gemspec +17 -19
- data/gemfiles/rails_4.gemfile +5 -3
- data/gemfiles/rails_5.0.gemfile +5 -3
- data/gemfiles/rails_5.1.gemfile +5 -3
- data/gemfiles/rails_5.2.gemfile +9 -0
- data/gemfiles/rails_6.0.gemfile +9 -0
- data/lib/dotiw.rb +33 -14
- data/lib/dotiw/action_view/helpers/date_helper.rb +32 -0
- data/lib/dotiw/locale/ar.yml +104 -0
- data/lib/dotiw/locale/da.yml +35 -0
- data/lib/dotiw/locale/de.yml +36 -1
- data/lib/dotiw/locale/en.yml +35 -0
- data/lib/dotiw/locale/es.yml +36 -1
- data/lib/dotiw/locale/fr.yml +35 -0
- data/lib/dotiw/locale/id.yml +35 -0
- data/lib/dotiw/locale/it.yml +35 -0
- data/lib/dotiw/locale/ja.yml +35 -0
- data/lib/dotiw/locale/ko.yml +48 -0
- data/lib/dotiw/locale/nb.yml +36 -1
- data/lib/dotiw/locale/nl.yml +35 -0
- data/lib/dotiw/locale/pl.yml +42 -0
- data/lib/dotiw/locale/pt-BR.yml +35 -0
- data/lib/dotiw/locale/ru.yml +37 -0
- data/lib/dotiw/locale/sv.yml +48 -0
- data/lib/dotiw/locale/vi.yml +48 -0
- data/lib/dotiw/locale/zh-CN.yml +48 -0
- data/lib/dotiw/locale/zh-TW.yml +60 -0
- data/lib/dotiw/methods.rb +108 -0
- data/lib/dotiw/time_hash.rb +52 -40
- data/lib/dotiw/version.rb +2 -2
- data/spec/lib/dotiw_spec.rb +303 -159
- data/spec/lib/i18n/ar.yml +2 -0
- data/spec/lib/i18n/da.yml +2 -0
- data/spec/lib/i18n/de.yml +2 -0
- data/spec/lib/i18n/en.yml +2 -0
- data/spec/lib/i18n/es.yml +3 -0
- data/spec/lib/i18n/fr.yml +2 -0
- data/spec/lib/i18n/id.yml +2 -0
- data/spec/lib/i18n/it.yml +3 -0
- data/spec/lib/i18n/ja.yml +2 -0
- data/spec/lib/i18n/ko.yml +2 -0
- data/spec/lib/i18n/nb.yml +2 -0
- data/spec/lib/i18n/nl.yml +2 -0
- data/spec/lib/i18n/pl.yml +2 -0
- data/spec/lib/i18n/pt-BR.yml +2 -0
- data/spec/lib/i18n/ru.yml +5 -0
- data/spec/lib/i18n/sv.yml +2 -0
- data/spec/lib/i18n/vi.yml +22 -0
- data/spec/lib/i18n/zh-CN.yml +2 -0
- data/spec/lib/i18n/zh-TW.yml +2 -0
- data/spec/spec_helper.rb +2 -9
- metadata +79 -31
- data/.travis.yml +0 -27
- data/lib/dotiw/action_view_ext/helpers/date_helper.rb +0 -103
data/lib/dotiw/version.rb
CHANGED
data/spec/lib/dotiw_spec.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
9
10
|
|
10
|
-
|
11
|
+
require 'action_controller'
|
12
|
+
else
|
13
|
+
include DOTIW::Methods
|
14
|
+
end
|
15
|
+
|
16
|
+
START_TIME = '01-08-2009'.to_time
|
11
17
|
|
12
18
|
before do
|
13
19
|
I18n.locale = :en
|
@@ -15,57 +21,57 @@ describe "A better distance_of_time_in_words" do
|
|
15
21
|
allow(Time.zone).to receive(:now).and_return(START_TIME)
|
16
22
|
end
|
17
23
|
|
18
|
-
describe
|
19
|
-
|
20
|
-
[0.5.minutes,
|
21
|
-
[4.5.minutes,
|
22
|
-
[5.minutes.to_i,
|
23
|
-
[10.minutes.to_i,
|
24
|
-
[1.hour.to_i,
|
25
|
-
[1.hour + 30.seconds,
|
26
|
-
[4.weeks.to_i,
|
27
|
-
[4.weeks + 2.days,
|
28
|
-
[24.weeks.to_i,
|
29
|
-
]
|
30
|
-
fragments.each do |number, result|
|
24
|
+
describe '#distance_of_time' do
|
25
|
+
[
|
26
|
+
[0.5.minutes, '30 seconds', '30s'],
|
27
|
+
[4.5.minutes, '4 minutes and 30 seconds', '4m30s'],
|
28
|
+
[5.minutes.to_i, '5 minutes', '5m'],
|
29
|
+
[10.minutes.to_i, '10 minutes', '10m'],
|
30
|
+
[1.hour.to_i, '1 hour', '1h'],
|
31
|
+
[1.hour + 30.seconds, '1 hour and 30 seconds', '1h30s'],
|
32
|
+
[4.weeks.to_i, '4 weeks', '4w'],
|
33
|
+
[4.weeks + 2.days, '4 weeks and 2 days', '4w2d'],
|
34
|
+
[24.weeks.to_i, '5 months, 2 weeks, and 1 day', '5mo2w1d']
|
35
|
+
].each do |number, result, compact_result|
|
31
36
|
it "#{number} == #{result}" do
|
32
37
|
expect(distance_of_time(number)).to eq(result)
|
38
|
+
expect(distance_of_time(number, compact: true)).to eq(compact_result)
|
33
39
|
end
|
34
40
|
end
|
35
41
|
|
36
|
-
describe
|
37
|
-
it
|
38
|
-
expect(distance_of_time(1.2.minute, except: 'seconds')).to eq(
|
39
|
-
expect(distance_of_time(2.5.hours + 30.seconds, except: 'seconds')).to eq(
|
42
|
+
describe 'with options' do
|
43
|
+
it 'except:seconds should skip seconds' do
|
44
|
+
expect(distance_of_time(1.2.minute, except: 'seconds')).to eq('1 minute')
|
45
|
+
expect(distance_of_time(2.5.hours + 30.seconds, except: 'seconds')).to eq('2 hours and 30 minutes')
|
40
46
|
end
|
41
47
|
|
42
|
-
it
|
48
|
+
it 'except:seconds has higher precedence than include_seconds:true' do
|
43
49
|
expect(distance_of_time(1.2.minute, include_seconds: true, except: 'seconds')).to eq('1 minute')
|
44
50
|
end
|
45
51
|
end
|
46
|
-
|
47
52
|
end
|
48
53
|
|
49
|
-
describe
|
50
|
-
describe
|
51
|
-
|
52
|
-
[:years, :months, :weeks, :days, :minutes, :seconds].each do |name|
|
54
|
+
describe '#distance_of_time_in_words_hash' do
|
55
|
+
describe 'giving correct numbers of' do
|
56
|
+
%i[years months weeks days minutes seconds].each do |name|
|
53
57
|
describe name do
|
54
|
-
it
|
58
|
+
it 'exactly' do
|
55
59
|
hash = distance_of_time_in_words_hash(START_TIME, START_TIME + 1.send(name))
|
56
60
|
expect(hash[name]).to eq(1)
|
57
61
|
end
|
58
62
|
|
59
|
-
it
|
63
|
+
it 'two' do
|
60
64
|
hash = distance_of_time_in_words_hash(START_TIME, START_TIME + 2.send(name))
|
61
65
|
expect(hash[name]).to eq(2)
|
62
66
|
end
|
63
67
|
end
|
64
68
|
end
|
65
69
|
|
66
|
-
it
|
67
|
-
hash = distance_of_time_in_words_hash(
|
68
|
-
|
70
|
+
it 'should be happy with lots of measurements' do
|
71
|
+
hash = distance_of_time_in_words_hash(
|
72
|
+
START_TIME,
|
73
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds
|
74
|
+
)
|
69
75
|
expect(hash[:years]).to eq(1)
|
70
76
|
expect(hash[:months]).to eq(2)
|
71
77
|
expect(hash[:weeks]).to eq(3)
|
@@ -77,214 +83,352 @@ describe "A better distance_of_time_in_words" do
|
|
77
83
|
end
|
78
84
|
end
|
79
85
|
|
80
|
-
describe
|
81
|
-
it
|
82
|
-
expect(
|
83
|
-
expect(distance_of_time_in_words(START_TIME, START_TIME + 5.days, :locale => :es)).to eq("5 días")
|
86
|
+
describe '#time_ago_in_words' do
|
87
|
+
it 'aliases to distance_of_time_in_words' do
|
88
|
+
expect(time_ago_in_words(Time.now - 3.days - 14.minutes)).to eq('3 days and 14 minutes')
|
84
89
|
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#distance_of_time_in_words' do
|
93
|
+
context 'locale' do
|
94
|
+
it 'includes known languages' do
|
95
|
+
expect(DOTIW.languages).to include :en
|
96
|
+
expect(DOTIW.languages).to include :ru
|
97
|
+
end
|
85
98
|
|
86
|
-
|
87
|
-
|
88
|
-
|
99
|
+
it 'includes all the languages in specs' do
|
100
|
+
languages = Dir[File.join(File.dirname(__FILE__), 'i18n', '*.yml')].map { |f| File.basename(f, '.yml') }
|
101
|
+
expect(DOTIW.languages.map(&:to_s).sort).to eq languages.sort
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'raises ArgumentError when nil is passed for time' do
|
105
|
+
expect { distance_of_time_in_words(nil) }.to raise_error(ArgumentError)
|
106
|
+
expect { distance_of_time_in_words(nil, nil) }.to raise_error(ArgumentError)
|
107
|
+
end
|
108
|
+
|
109
|
+
DOTIW.languages.each do |lang|
|
110
|
+
context lang do
|
111
|
+
YAML.safe_load(
|
112
|
+
File.read(
|
113
|
+
File.join(
|
114
|
+
File.dirname(__FILE__), 'i18n', "#{lang}.yml"
|
115
|
+
)
|
116
|
+
)
|
117
|
+
).each_pair do |category, fixtures|
|
118
|
+
context category do
|
119
|
+
fixtures.each_pair do |k, v|
|
120
|
+
it v do
|
121
|
+
expect(
|
122
|
+
distance_of_time_in_words(
|
123
|
+
START_TIME,
|
124
|
+
START_TIME + eval(k),
|
125
|
+
true,
|
126
|
+
locale: lang
|
127
|
+
)
|
128
|
+
).to eq(v)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
89
135
|
end
|
90
136
|
|
91
|
-
|
92
|
-
[START_TIME, START_TIME + 5.days + 3.minutes,
|
93
|
-
[START_TIME, START_TIME + 1.minute,
|
94
|
-
[START_TIME, START_TIME + 3.years,
|
95
|
-
[START_TIME, START_TIME + 10.years,
|
96
|
-
[START_TIME, START_TIME + 8.months,
|
97
|
-
[START_TIME, START_TIME + 3.hour,
|
98
|
-
[START_TIME, START_TIME + 13.months,
|
137
|
+
[
|
138
|
+
[START_TIME, START_TIME + 5.days + 3.minutes, '5 days and 3 minutes'],
|
139
|
+
[START_TIME, START_TIME + 1.minute, '1 minute'],
|
140
|
+
[START_TIME, START_TIME + 3.years, '3 years'],
|
141
|
+
[START_TIME, START_TIME + 10.years, '10 years'],
|
142
|
+
[START_TIME, START_TIME + 8.months, '8 months'],
|
143
|
+
[START_TIME, START_TIME + 3.hour, '3 hours'],
|
144
|
+
[START_TIME, START_TIME + 13.months, '1 year and 1 month'],
|
99
145
|
# Any numeric sequence is merely coincidental.
|
100
|
-
[START_TIME, START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
101
|
-
|
102
|
-
[
|
103
|
-
[
|
104
|
-
[
|
105
|
-
[
|
106
|
-
|
107
|
-
|
146
|
+
[START_TIME, START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
147
|
+
'1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds'],
|
148
|
+
['2009-3-16'.to_time, '2008-4-14'.to_time, '11 months and 2 days'],
|
149
|
+
['2009-3-16'.to_time + 1.minute, '2008-4-14'.to_time, '11 months, 2 days, and 1 minute'],
|
150
|
+
['2009-4-14'.to_time, '2008-3-16'.to_time, '1 year, 4 weeks, and 1 day'],
|
151
|
+
['2009-2-01'.to_time, '2009-3-01'.to_time, '1 month'],
|
152
|
+
['2008-2-01'.to_time, '2008-3-01'.to_time, '1 month'],
|
153
|
+
[Date.parse('31.03.2015').to_time, Time.parse('01.03.2016'), '10 months, 4 weeks, and 2 days'],
|
154
|
+
[Date.new(2014, 1, 31), Date.new(2014, 3, 1), '4 weeks and 1 day'],
|
155
|
+
['2008-2-01'.to_time, '2008-3-01'.to_time, '1 month'],
|
156
|
+
['2014-1-31'.to_time, '2014-3-01'.to_time, '4 weeks and 1 day'],
|
157
|
+
['2014-1-31'.to_time, '2014-3-02'.to_time, '4 weeks and 2 days'],
|
158
|
+
['2016-1-31'.to_time, '2016-3-01'.to_time, '4 weeks and 2 days'],
|
159
|
+
['2016-1-31'.to_time, '2016-3-02'.to_time, '1 month']
|
160
|
+
].each do |start, finish, output|
|
108
161
|
it "should be #{output}" do
|
109
162
|
expect(distance_of_time_in_words(start, finish, true)).to eq(output)
|
163
|
+
expect(distance_of_time_in_words(finish, start, true)).to eq(output)
|
110
164
|
end
|
111
165
|
end
|
112
166
|
|
113
|
-
|
114
|
-
|
167
|
+
[
|
168
|
+
[Time.zone.now, Time.zone.now + 1.day - 1.minute, '23 hours and 59 minutes'],
|
169
|
+
[Time.zone.now, Time.zone.now + 15.days - 1.minute, '14 days, 23 hours, and 59 minutes'],
|
170
|
+
[Time.zone.now, Time.zone.now + 29.days - 1.minute, '28 days, 23 hours, and 59 minutes'],
|
171
|
+
[Time.zone.now, Time.zone.now + 30.days - 1.minute, '29 days, 23 hours, and 59 minutes'],
|
172
|
+
[Time.zone.now, Time.zone.now + 31.days - 1.minute, '30 days, 23 hours, and 59 minutes'],
|
173
|
+
[Time.zone.now, Time.zone.now + 32.days - 1.minute, '31 days, 23 hours, and 59 minutes'],
|
174
|
+
[Time.zone.now, Time.zone.now + 33.days - 1.minute, '32 days, 23 hours, and 59 minutes']
|
175
|
+
].each do |start, finish, output|
|
176
|
+
it "should be #{output}" do
|
177
|
+
expect(distance_of_time_in_words(start, finish, accumulate_on: 'days')).to eq(output)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
[
|
182
|
+
[Time.at(1), Time.at(100), '1 minute'],
|
183
|
+
[DateTime.now, DateTime.now + 1.minute, '1 minute'],
|
184
|
+
[Date.new(2000, 1, 2), Date.new(2000, 1, 3), '1 day'],
|
185
|
+
[Time.at(DateTime.now), DateTime.now + 1.minute, '1 minute']
|
186
|
+
].each do |start, finish, output|
|
187
|
+
it "should be #{output}" do
|
188
|
+
expect(distance_of_time_in_words(start, finish)).to eq(output)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe 'accumulate_on:' do
|
193
|
+
[
|
115
194
|
[START_TIME,
|
116
195
|
START_TIME + 10.minute,
|
117
196
|
:seconds,
|
118
|
-
|
197
|
+
'600 seconds'],
|
119
198
|
[START_TIME,
|
120
199
|
START_TIME + 10.hour + 10.minute + 1.second,
|
121
200
|
:minutes,
|
122
|
-
|
201
|
+
'610 minutes and 1 second'],
|
123
202
|
[START_TIME,
|
124
|
-
START_TIME + 2.day +
|
203
|
+
START_TIME + 2.day + 10_000.hour + 10.second,
|
125
204
|
:hours,
|
126
|
-
|
205
|
+
'10048 hours and 10 seconds'],
|
127
206
|
[START_TIME,
|
128
|
-
START_TIME + 2.day +
|
207
|
+
START_TIME + 2.day + 10_000.hour + 10.second,
|
129
208
|
:days,
|
130
|
-
|
209
|
+
'418 days, 16 hours, and 10 seconds'],
|
131
210
|
[START_TIME,
|
132
|
-
START_TIME + 2.day +
|
211
|
+
START_TIME + 2.day + 10_000.hour + 10.second,
|
133
212
|
:weeks,
|
134
|
-
|
213
|
+
'59 weeks, 5 days, 16 hours, and 10 seconds'],
|
135
214
|
[START_TIME,
|
136
|
-
START_TIME + 2.day +
|
215
|
+
START_TIME + 2.day + 10_000.hour + 10.second,
|
137
216
|
:months,
|
138
|
-
|
139
|
-
[
|
140
|
-
|
141
|
-
]
|
142
|
-
fragments.each do |start, finish, accumulator, output|
|
217
|
+
'13 months, 3 weeks, 1 day, 16 hours, and 10 seconds'],
|
218
|
+
['2015-1-15'.to_time, '2016-3-15'.to_time, :months, '14 months']
|
219
|
+
].each do |start, finish, accumulator, output|
|
143
220
|
it "should be #{output}" do
|
144
|
-
expect(distance_of_time_in_words(start, finish, true, :
|
221
|
+
expect(distance_of_time_in_words(start, finish, true, accumulate_on: accumulator)).to eq(output)
|
145
222
|
end
|
146
223
|
end
|
147
|
-
end
|
224
|
+
end
|
148
225
|
|
149
|
-
describe
|
226
|
+
describe 'without finish time' do
|
150
227
|
# A missing finish argument should default to zero, essentially returning
|
151
228
|
# the equivalent of distance_of_time in order to be backwards-compatible
|
152
229
|
# with the original rails distance_of_time_in_words helper.
|
153
|
-
|
154
|
-
[5.minutes.to_i,
|
155
|
-
[10.minutes.to_i,
|
156
|
-
[1.hour.to_i,
|
157
|
-
[6.days.to_i,
|
158
|
-
[4.weeks.to_i,
|
159
|
-
[24.weeks.to_i,
|
160
|
-
]
|
161
|
-
fragments.each do |start, output|
|
230
|
+
[
|
231
|
+
[5.minutes.to_i, '5 minutes'],
|
232
|
+
[10.minutes.to_i, '10 minutes'],
|
233
|
+
[1.hour.to_i, '1 hour'],
|
234
|
+
[6.days.to_i, '6 days'],
|
235
|
+
[4.weeks.to_i, '4 weeks'],
|
236
|
+
[24.weeks.to_i, '5 months, 2 weeks, and 1 day']
|
237
|
+
].each do |start, output|
|
162
238
|
it "should be #{output}" do
|
163
239
|
expect(distance_of_time_in_words(start)).to eq(output)
|
164
240
|
end
|
165
241
|
end
|
166
242
|
end
|
167
|
-
|
168
243
|
end
|
169
244
|
|
170
|
-
describe
|
171
|
-
|
245
|
+
describe 'with output options' do
|
246
|
+
[
|
172
247
|
# Any numeric sequence is merely coincidental.
|
173
248
|
[START_TIME,
|
174
249
|
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
175
|
-
{ :
|
176
|
-
|
250
|
+
{ words_connector: ' - ' },
|
251
|
+
'1 year - 2 months - 3 weeks - 4 days - 5 hours - 6 minutes, and 7 seconds'],
|
177
252
|
[START_TIME,
|
178
253
|
START_TIME + 5.minutes + 6.seconds,
|
179
|
-
{ :
|
180
|
-
|
254
|
+
{ two_words_connector: ' - ' },
|
255
|
+
'5 minutes - 6 seconds'],
|
181
256
|
[START_TIME,
|
182
|
-
START_TIME + 4.hours +
|
183
|
-
{ :
|
184
|
-
|
257
|
+
START_TIME + 4.hours + 5.minutes + 6.seconds,
|
258
|
+
{ last_word_connector: ' - ' },
|
259
|
+
'4 hours, 5 minutes - 6 seconds'],
|
185
260
|
[START_TIME,
|
186
261
|
START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds,
|
187
|
-
{ :
|
188
|
-
|
262
|
+
{ except: 'minutes' },
|
263
|
+
'1 year, 2 months, 3 days, 4 hours, and 6 seconds'],
|
189
264
|
[START_TIME,
|
190
265
|
START_TIME + 1.hour + 1.minute,
|
191
|
-
{ :
|
266
|
+
{ except: 'minutes' }, '1 hour'],
|
192
267
|
[START_TIME,
|
193
268
|
START_TIME + 1.hour + 1.day + 1.minute,
|
194
|
-
{ :
|
195
|
-
|
269
|
+
{ except: %w[minutes hours] },
|
270
|
+
'1 day'],
|
196
271
|
[START_TIME,
|
197
272
|
START_TIME + 1.hour + 1.day + 1.minute,
|
198
|
-
{ :
|
199
|
-
|
273
|
+
{ only: %w[minutes hours] },
|
274
|
+
'1 hour and 1 minute'],
|
200
275
|
[START_TIME,
|
201
276
|
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
202
|
-
{ :
|
203
|
-
|
277
|
+
{ except: 'minutes' },
|
278
|
+
'1 year, 2 months, 3 weeks, 4 days, 5 hours, and 7 seconds'],
|
204
279
|
[START_TIME,
|
205
|
-
START_TIME + 1.
|
206
|
-
{ :
|
207
|
-
|
208
|
-
[START_TIME,
|
209
|
-
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
210
|
-
{ :vague => false },
|
211
|
-
"1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds"],
|
212
|
-
[START_TIME,
|
213
|
-
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
214
|
-
{ :vague => nil },
|
215
|
-
"1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds"],
|
216
|
-
[START_TIME,
|
217
|
-
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
218
|
-
{ :except => "minutes" },
|
219
|
-
"1 year, 2 months, 3 weeks, 4 days, 5 hours, and 7 seconds"],
|
220
|
-
[START_TIME,
|
221
|
-
START_TIME + 1.hour + 2.minutes + 3.seconds,
|
222
|
-
{ :highest_measure_only => true },
|
223
|
-
"1 hour"],
|
280
|
+
START_TIME + 1.hour + 2.minutes + 3.seconds,
|
281
|
+
{ highest_measure_only: true },
|
282
|
+
'1 hour'],
|
224
283
|
[START_TIME,
|
225
284
|
START_TIME + 1.hours + 2.minutes + 3.seconds,
|
226
|
-
{ :
|
227
|
-
|
285
|
+
{ highest_measures: 1 },
|
286
|
+
'1 hour'],
|
228
287
|
[START_TIME,
|
229
288
|
START_TIME + 2.year + 3.months + 4.days + 5.hours + 6.minutes + 7.seconds,
|
230
|
-
{ :
|
231
|
-
|
289
|
+
{ highest_measures: 3 },
|
290
|
+
'2 years, 3 months, and 4 days'],
|
232
291
|
[START_TIME,
|
233
292
|
START_TIME + 2.year + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
234
|
-
{ :
|
235
|
-
|
293
|
+
{ highest_measures: 2 },
|
294
|
+
'2 years and 3 weeks'],
|
236
295
|
[START_TIME,
|
237
296
|
START_TIME + 4.days + 6.minutes + 7.seconds,
|
238
|
-
{ :
|
239
|
-
|
297
|
+
{ highest_measures: 3 },
|
298
|
+
'4 days, 6 minutes, and 7 seconds'],
|
240
299
|
[START_TIME,
|
241
300
|
START_TIME + 1.year + 2.weeks,
|
242
|
-
{ :
|
243
|
-
|
301
|
+
{ highest_measures: 3 },
|
302
|
+
'1 year and 2 weeks'],
|
244
303
|
[START_TIME,
|
245
304
|
START_TIME + 1.days,
|
246
|
-
{ :
|
247
|
-
|
305
|
+
{ only: %i[years months] },
|
306
|
+
'less than 1 month'],
|
248
307
|
[START_TIME,
|
249
308
|
START_TIME + 5.minutes,
|
250
|
-
{ :
|
251
|
-
|
309
|
+
{ except: %i[hours minutes seconds] },
|
310
|
+
'less than 1 day'],
|
252
311
|
[START_TIME,
|
253
312
|
START_TIME + 1.days,
|
254
|
-
{ :
|
255
|
-
|
256
|
-
]
|
257
|
-
fragments.each do |start, finish, options, output|
|
313
|
+
{ highest_measures: 1, only: %i[years months] },
|
314
|
+
'less than 1 month']
|
315
|
+
].each do |start, finish, options, output|
|
258
316
|
it "should be #{output}" do
|
259
317
|
expect(distance_of_time_in_words(start, finish, true, options)).to eq(output)
|
260
318
|
end
|
261
319
|
end
|
262
320
|
|
263
|
-
|
264
|
-
|
265
|
-
|
321
|
+
if defined?(ActionView)
|
322
|
+
describe 'ActionView' do
|
323
|
+
[
|
324
|
+
[START_TIME,
|
325
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
326
|
+
{ vague: true },
|
327
|
+
'about 1 year'],
|
328
|
+
[START_TIME,
|
329
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
330
|
+
{ vague: 'Yes please' },
|
331
|
+
'about 1 year'],
|
332
|
+
[START_TIME,
|
333
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
334
|
+
{ vague: false },
|
335
|
+
'1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds'],
|
336
|
+
[START_TIME,
|
337
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
338
|
+
{ vague: nil },
|
339
|
+
'1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds']
|
340
|
+
].each do |start, finish, options, output|
|
341
|
+
it "should be #{output}" do
|
342
|
+
expect(distance_of_time_in_words(start, finish, true, options)).to eq(output)
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
context 'via ActionController::Base.helpers' do
|
347
|
+
it '#distance_of_time_in_words' do
|
348
|
+
end_time = START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds
|
349
|
+
expected = '1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds'
|
350
|
+
actual = ActionController::Base.helpers.distance_of_time_in_words(START_TIME, end_time, true,
|
351
|
+
{ vague: false })
|
352
|
+
expect(actual).to eq(expected)
|
353
|
+
end
|
354
|
+
|
355
|
+
it '#time_ago_in_words' do
|
356
|
+
expected = '3 days and 14 minutes'
|
357
|
+
actual = ActionController::Base.helpers.time_ago_in_words(Time.now - 3.days - 14.minutes)
|
358
|
+
expect(actual).to eq(expected)
|
359
|
+
end
|
360
|
+
|
361
|
+
describe '#distance_of_time_in_words_to_now' do
|
362
|
+
context 'with nil' do
|
363
|
+
it 'raises ArgumentError when nil is passed for time' do
|
364
|
+
expect do
|
365
|
+
ActionController::Base.helpers.distance_of_time_in_words_to_now(nil)
|
366
|
+
end.to raise_error(ArgumentError)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
context 'without options' do
|
371
|
+
it 'shows detailed duration' do
|
372
|
+
expected = '3 days and 14 minutes'
|
373
|
+
actual = ActionController::Base.helpers.distance_of_time_in_words_to_now(Time.now - 3.days - 14.minutes)
|
374
|
+
expect(actual).to eq(expected)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
context 'with vague option true' do
|
379
|
+
it 'shows vague duration' do
|
380
|
+
expected = '3 days'
|
381
|
+
actual = ActionController::Base.helpers.distance_of_time_in_words_to_now(
|
382
|
+
Time.now - 3.days - 14.minutes, false, vague: true
|
383
|
+
)
|
384
|
+
expect(actual).to eq(expected)
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
context 'with vague option false' do
|
389
|
+
it 'shows detailed duration' do
|
390
|
+
expected = '3 days and 14 minutes'
|
391
|
+
actual = ActionController::Base.helpers.distance_of_time_in_words_to_now(
|
392
|
+
Time.now - 3.days - 14.minutes, false, vague: false
|
393
|
+
)
|
394
|
+
expect(actual).to eq(expected)
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
266
399
|
end
|
400
|
+
end
|
267
401
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
false)).to eq("1 year, 2 months, 3 weeks, 4 days, 5 hours, and 6 minutes")
|
402
|
+
describe 'include_seconds' do
|
403
|
+
it 'is ignored if only seconds have passed' do
|
404
|
+
expect(distance_of_time_in_words(START_TIME, START_TIME + 1.second, false)).to eq('1 second')
|
272
405
|
end
|
273
|
-
end # include_seconds
|
274
|
-
end
|
275
406
|
|
276
|
-
|
277
|
-
|
278
|
-
|
407
|
+
it 'removes seconds in all other cases' do
|
408
|
+
expect(
|
409
|
+
distance_of_time_in_words(
|
410
|
+
START_TIME,
|
411
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
412
|
+
false
|
413
|
+
)
|
414
|
+
).to eq('1 year, 2 months, 3 weeks, 4 days, 5 hours, and 6 minutes')
|
415
|
+
end
|
279
416
|
end
|
417
|
+
end
|
280
418
|
|
281
|
-
|
282
|
-
|
283
|
-
|
419
|
+
if defined?(ActionView)
|
420
|
+
describe 'percentage of time' do
|
421
|
+
def time_in_percent(options = {})
|
422
|
+
distance_of_time_in_percent('04-12-2009'.to_time, '29-01-2010'.to_time, '04-12-2010'.to_time, options)
|
423
|
+
end
|
424
|
+
|
425
|
+
it 'calculates 15%' do
|
426
|
+
expect(time_in_percent).to eq('15%')
|
427
|
+
end
|
284
428
|
|
285
|
-
|
286
|
-
|
429
|
+
it 'calculates 15.3%' do
|
430
|
+
expect(time_in_percent(precision: 1)).to eq('15.3%')
|
431
|
+
end
|
287
432
|
end
|
288
433
|
end
|
289
|
-
|
290
434
|
end
|