dotiw 5.3.3 → 5.6.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 +4 -4
- data/.github/workflows/ruby.yml +41 -16
- data/.gitignore +1 -0
- data/Appraisals +25 -4
- data/CHANGELOG.md +26 -0
- data/CODEOWNERS +2 -0
- data/README.markdown +73 -5
- data/RELEASING.md +71 -0
- data/benchmarks/distance_of_time_in_words_bench.rb +38 -0
- data/dotiw.gemspec +4 -1
- data/gemfiles/{rails_4.gemfile → rails_7.0.gemfile} +2 -1
- data/gemfiles/rails_7.1.gemfile +11 -0
- data/gemfiles/rails_7.2.gemfile +11 -0
- data/gemfiles/rails_8.0.gemfile +11 -0
- data/gemfiles/rails_8.1.gemfile +11 -0
- data/gemfiles/rails_8.1_i18n.gemfile +11 -0
- data/lib/dotiw/core.rb +45 -0
- data/lib/dotiw/locale/dz.yml +60 -0
- data/lib/dotiw/locale/ru.yml +9 -9
- data/lib/dotiw/methods.rb +127 -21
- data/lib/dotiw/time_hash.rb +60 -12
- data/lib/dotiw/version.rb +1 -1
- data/lib/dotiw.rb +1 -40
- data/spec/lib/dotiw_module_spec.rb +52 -0
- data/spec/lib/dotiw_spec.rb +225 -14
- data/spec/lib/i18n/dz.yml +21 -0
- data/spec/lib/i18n/ru.yml +18 -0
- data/spec/spec_helper.rb +19 -0
- metadata +65 -9
data/spec/lib/dotiw_spec.rb
CHANGED
|
@@ -13,10 +13,16 @@ describe 'A better distance_of_time_in_words' do
|
|
|
13
13
|
include DOTIW::Methods
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
START_TIME = '01-08-2009'.to_time
|
|
16
|
+
START_TIME = '01-08-2009'.to_time(:utc)
|
|
17
17
|
|
|
18
18
|
before do
|
|
19
19
|
I18n.locale = :en
|
|
20
|
+
# This config is deprecated as of Rails 8.1 (it becomes the permanent,
|
|
21
|
+
# non-configurable behavior) and is removed entirely in Rails 8.2.
|
|
22
|
+
if Gem::Version.new(ActiveSupport::VERSION::STRING) < Gem::Version.new('8.1')
|
|
23
|
+
ActiveSupport.to_time_preserves_timezone = :zone
|
|
24
|
+
end
|
|
25
|
+
|
|
20
26
|
allow(Time).to receive(:now).and_return(START_TIME)
|
|
21
27
|
allow(Time.zone).to receive(:now).and_return(START_TIME)
|
|
22
28
|
end
|
|
@@ -113,12 +119,18 @@ describe 'A better distance_of_time_in_words' do
|
|
|
113
119
|
context category do
|
|
114
120
|
fixtures.each_pair do |k, v|
|
|
115
121
|
it v do
|
|
122
|
+
options = {
|
|
123
|
+
locale: lang
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
options[:compact] = true if category.split.include?('compact')
|
|
127
|
+
|
|
116
128
|
expect(
|
|
117
129
|
distance_of_time_in_words(
|
|
118
130
|
START_TIME,
|
|
119
131
|
START_TIME + eval(k),
|
|
120
132
|
true,
|
|
121
|
-
|
|
133
|
+
options
|
|
122
134
|
)
|
|
123
135
|
).to eq(v)
|
|
124
136
|
end
|
|
@@ -165,7 +177,7 @@ describe 'A better distance_of_time_in_words' do
|
|
|
165
177
|
[Time.zone.now, Time.zone.now + 15.days - 1.minute, '14 days, 23 hours, and 59 minutes'],
|
|
166
178
|
[Time.zone.now, Time.zone.now + 29.days - 1.minute, '28 days, 23 hours, and 59 minutes'],
|
|
167
179
|
[Time.zone.now, Time.zone.now + 30.days - 1.minute, '29 days, 23 hours, and 59 minutes'],
|
|
168
|
-
[Time.zone.now, Time.zone.now + 31.
|
|
180
|
+
[Time.zone.now, Time.zone.now + 31.day - 1.minute, '30 days, 23 hours, and 59 minutes'],
|
|
169
181
|
[Time.zone.now, Time.zone.now + 32.days - 1.minute, '31 days, 23 hours, and 59 minutes'],
|
|
170
182
|
[Time.zone.now, Time.zone.now + 33.days - 1.minute, '32 days, 23 hours, and 59 minutes']
|
|
171
183
|
].each do |start, finish, output|
|
|
@@ -185,6 +197,63 @@ describe 'A better distance_of_time_in_words' do
|
|
|
185
197
|
end
|
|
186
198
|
end
|
|
187
199
|
|
|
200
|
+
context 'in timezones with an inverted DST scheme (#63)' do
|
|
201
|
+
# Real, non-mocked reproduction from #63: running the suite under
|
|
202
|
+
# certain timezones (e.g. Europe/Dublin, where IST is "standard" time
|
|
203
|
+
# and GMT is technically the DST offset) previously failed because
|
|
204
|
+
# Time#dst? disagreed between a Time built via Time.at(datetime) and
|
|
205
|
+
# one built via datetime.to_time for the exact same instant, even
|
|
206
|
+
# though their utc_offset was identical. This caused a spurious +/-1
|
|
207
|
+
# hour "DST correction" to be applied.
|
|
208
|
+
around do |example|
|
|
209
|
+
original_tz = ENV.fetch('TZ', nil)
|
|
210
|
+
ENV['TZ'] = tz
|
|
211
|
+
example.run
|
|
212
|
+
ENV['TZ'] = original_tz
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
%w[
|
|
216
|
+
Europe/Dublin
|
|
217
|
+
Africa/Casablanca
|
|
218
|
+
Asia/Tehran
|
|
219
|
+
Europe/Moscow
|
|
220
|
+
Asia/Gaza
|
|
221
|
+
].each do |timezone|
|
|
222
|
+
context "TZ=#{timezone}" do
|
|
223
|
+
let(:tz) { timezone }
|
|
224
|
+
|
|
225
|
+
it 'is 1 minute' do
|
|
226
|
+
start = Time.at(DateTime.now)
|
|
227
|
+
finish = DateTime.now + 1.minute
|
|
228
|
+
|
|
229
|
+
expect(distance_of_time_in_words(start, finish)).to eq('1 minute')
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
context 'across a historical UTC offset change (#153)' do
|
|
236
|
+
# Real, non-mocked reproduction from #153: Pacific/Norfolk permanently
|
|
237
|
+
# changed its UTC offset from +11:30 to +11:00 on 2015-10-04 (a
|
|
238
|
+
# tzdata rule change, not a recurring DST transition - both endpoints
|
|
239
|
+
# report dst? == false). The calendar distance (years/months/weeks/
|
|
240
|
+
# days) was correct, but the leftover hours/minutes leaked the 30
|
|
241
|
+
# minute offset difference as a spurious "23 hours and 30 minutes".
|
|
242
|
+
around do |example|
|
|
243
|
+
original_tz = ENV.fetch('TZ', nil)
|
|
244
|
+
ENV['TZ'] = 'Pacific/Norfolk'
|
|
245
|
+
example.run
|
|
246
|
+
ENV['TZ'] = original_tz
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
it 'is 1 year and 2 months, not 1 year, 2 months, 23 hours, and 30 minutes' do
|
|
250
|
+
start = '2015-1-15'.to_time
|
|
251
|
+
finish = '2016-3-15'.to_time
|
|
252
|
+
|
|
253
|
+
expect(distance_of_time_in_words(start, finish, true)).to eq('1 year and 2 months')
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
188
257
|
describe 'accumulate_on:' do
|
|
189
258
|
[
|
|
190
259
|
[START_TIME,
|
|
@@ -211,7 +280,8 @@ describe 'A better distance_of_time_in_words' do
|
|
|
211
280
|
START_TIME + 2.day + 10_000.hour + 10.second,
|
|
212
281
|
:months,
|
|
213
282
|
'13 months, 3 weeks, 1 day, 16 hours, and 10 seconds'],
|
|
214
|
-
['2015-1-15'.to_time, '2016-3-15'.to_time, :months, '14 months']
|
|
283
|
+
['2015-1-15'.to_time, '2016-3-15'.to_time, :months, '14 months'],
|
|
284
|
+
['2015-1-15'.to_time, '2016-3-15'.to_time, :years, '1 year and 2 months']
|
|
215
285
|
].each do |start, finish, accumulator, output|
|
|
216
286
|
it "should be #{output}" do
|
|
217
287
|
expect(distance_of_time_in_words(start, finish, true, accumulate_on: accumulator)).to eq(output)
|
|
@@ -219,6 +289,55 @@ describe 'A better distance_of_time_in_words' do
|
|
|
219
289
|
end
|
|
220
290
|
end
|
|
221
291
|
|
|
292
|
+
describe 'max_unit:' do
|
|
293
|
+
[
|
|
294
|
+
[START_TIME,
|
|
295
|
+
START_TIME + 10.minute,
|
|
296
|
+
:seconds,
|
|
297
|
+
{ seconds: 600 },
|
|
298
|
+
'600 seconds'],
|
|
299
|
+
[START_TIME,
|
|
300
|
+
START_TIME + 10.hour + 10.minute + 1.second,
|
|
301
|
+
:minutes,
|
|
302
|
+
{ minutes: 610 },
|
|
303
|
+
'610 minutes'],
|
|
304
|
+
[START_TIME,
|
|
305
|
+
START_TIME + 2.day + 10_000.hour + 10.second,
|
|
306
|
+
:hours,
|
|
307
|
+
{ hours: 10_048 },
|
|
308
|
+
'10048 hours'],
|
|
309
|
+
[START_TIME,
|
|
310
|
+
START_TIME + 2.day + 10_000.hour + 10.second,
|
|
311
|
+
:days,
|
|
312
|
+
{ days: 418 },
|
|
313
|
+
'418 days'],
|
|
314
|
+
[START_TIME,
|
|
315
|
+
START_TIME + 2.day + 10_000.hour + 10.second,
|
|
316
|
+
:weeks,
|
|
317
|
+
{ weeks: 59 },
|
|
318
|
+
'59 weeks'],
|
|
319
|
+
['2015-1-15'.to_time, '2016-3-15'.to_time, :months, { months: 14 }, '14 months'],
|
|
320
|
+
['2015-1-15'.to_time, '2016-3-15'.to_time, :years, { years: 1 }, '1 year']
|
|
321
|
+
].each do |start, finish, unit, hash, output|
|
|
322
|
+
it "should be #{output}" do
|
|
323
|
+
expect(distance_of_time_in_words_hash(start, finish, max_unit: unit)).to eq(hash)
|
|
324
|
+
expect(distance_of_time_in_words(start, finish, true, max_unit: unit)).to eq(output)
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
it 'floors and discards any remainder smaller than the unit' do
|
|
329
|
+
expect(
|
|
330
|
+
distance_of_time_in_words_hash(START_TIME, START_TIME + 1.year - 1.day, max_unit: :years)
|
|
331
|
+
).to eq(years: 0)
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
it 'raises for an unrecognized unit' do
|
|
335
|
+
expect do
|
|
336
|
+
distance_of_time_in_words_hash(START_TIME, START_TIME + 1.day, max_unit: :fortnights)
|
|
337
|
+
end.to raise_error(ArgumentError, /unrecognized max_unit/)
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
222
341
|
describe 'without finish time' do
|
|
223
342
|
# A missing finish argument should default to zero, essentially returning
|
|
224
343
|
# the equivalent of distance_of_time in order to be backwards-compatible
|
|
@@ -288,22 +407,28 @@ describe 'A better distance_of_time_in_words' do
|
|
|
288
407
|
[START_TIME,
|
|
289
408
|
START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds,
|
|
290
409
|
{ except: 'minutes' },
|
|
291
|
-
|
|
410
|
+
# 5 excluded minutes are folded into seconds (5 * 60 + 6 = 306) instead of being discarded.
|
|
411
|
+
'1 year, 2 months, 3 days, 4 hours, and 306 seconds'],
|
|
292
412
|
[START_TIME,
|
|
293
413
|
START_TIME + 1.hour + 1.minute,
|
|
294
|
-
{ except: 'minutes' },
|
|
414
|
+
{ except: 'minutes' },
|
|
415
|
+
# The excluded minute is folded into seconds (1 * 60 = 60) instead of being discarded.
|
|
416
|
+
'1 hour and 60 seconds'],
|
|
295
417
|
[START_TIME,
|
|
296
418
|
START_TIME + 1.hour + 1.day + 1.minute,
|
|
297
419
|
{ except: %w[minutes hours] },
|
|
298
|
-
|
|
420
|
+
# The excluded hour and minute cascade down into seconds (1 * 24 * 60 * 60 + 1 * 60 = 3660).
|
|
421
|
+
'1 day and 3660 seconds'],
|
|
299
422
|
[START_TIME,
|
|
300
423
|
START_TIME + 1.hour + 1.day + 1.minute,
|
|
301
424
|
{ only: %w[minutes hours] },
|
|
302
|
-
|
|
425
|
+
# The excluded day is folded into hours (1 * 24 + 1 = 25) instead of being discarded.
|
|
426
|
+
'25 hours and 1 minute'],
|
|
303
427
|
[START_TIME,
|
|
304
428
|
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
305
429
|
{ except: 'minutes' },
|
|
306
|
-
|
|
430
|
+
# 6 excluded minutes are folded into seconds (6 * 60 + 7 = 367) instead of being discarded.
|
|
431
|
+
'1 year, 2 months, 3 weeks, 4 days, 5 hours, and 367 seconds'],
|
|
307
432
|
[START_TIME,
|
|
308
433
|
START_TIME + 1.hour + 2.minutes + 3.seconds,
|
|
309
434
|
{ highest_measure_only: true },
|
|
@@ -329,7 +454,7 @@ describe 'A better distance_of_time_in_words' do
|
|
|
329
454
|
{ highest_measures: 3 },
|
|
330
455
|
'1 year and 2 weeks'],
|
|
331
456
|
[START_TIME,
|
|
332
|
-
START_TIME + 1.
|
|
457
|
+
START_TIME + 1.day,
|
|
333
458
|
{ only: %i[years months] },
|
|
334
459
|
'less than 1 month'],
|
|
335
460
|
[START_TIME,
|
|
@@ -337,15 +462,83 @@ describe 'A better distance_of_time_in_words' do
|
|
|
337
462
|
{ except: %i[hours minutes seconds] },
|
|
338
463
|
'less than 1 day'],
|
|
339
464
|
[START_TIME,
|
|
340
|
-
START_TIME + 1.
|
|
465
|
+
START_TIME + 1.day,
|
|
341
466
|
{ highest_measures: 1, only: %i[years months] },
|
|
342
|
-
'less than 1 month']
|
|
467
|
+
'less than 1 month'],
|
|
468
|
+
[START_TIME,
|
|
469
|
+
START_TIME + 1.day + 1.hour,
|
|
470
|
+
{ highest_measures: {} },
|
|
471
|
+
'1 day'],
|
|
472
|
+
[START_TIME,
|
|
473
|
+
START_TIME + 1.day + 1.hour,
|
|
474
|
+
{ highest_measures: { remainder: :floor} },
|
|
475
|
+
'1 day'],
|
|
476
|
+
[START_TIME,
|
|
477
|
+
START_TIME + 1.year + 1.minute,
|
|
478
|
+
{ highest_measures: { remainder: :ceiling } },
|
|
479
|
+
'2 years'],
|
|
480
|
+
[START_TIME,
|
|
481
|
+
START_TIME + 1.day + 2.hours + 30.minutes,
|
|
482
|
+
{ highest_measures: { max: 2, remainder: :round } },
|
|
483
|
+
'1 day and 3 hours'],
|
|
484
|
+
[START_TIME,
|
|
485
|
+
START_TIME + 1.day + 23.hours + 59.minutes + 59.seconds,
|
|
486
|
+
{ highest_measures: { max: 3, remainder: :round } },
|
|
487
|
+
'2 days'],
|
|
488
|
+
[START_TIME,
|
|
489
|
+
START_TIME + 1.day,
|
|
490
|
+
{ highest_measures: { remainder: :ceiling }, only: :months },
|
|
491
|
+
'less than 1 month'],
|
|
492
|
+
[START_TIME,
|
|
493
|
+
# Simplistic rounding: one would expect this to round up to a second week.
|
|
494
|
+
START_TIME + 1.week + 3.days + 23.hours,
|
|
495
|
+
{ highest_measures: { remainder: :round } },
|
|
496
|
+
'1 week'],
|
|
497
|
+
[START_TIME,
|
|
498
|
+
# Simplistic rounding: in some months, 15 days is less than half, but we always round it up.
|
|
499
|
+
START_TIME + 1.month + 14.days,
|
|
500
|
+
{ highest_measures: { remainder: :round } },
|
|
501
|
+
'2 months'],
|
|
343
502
|
].each do |start, finish, options, output|
|
|
344
503
|
it "should be #{output}" do
|
|
345
504
|
expect(distance_of_time_in_words(start, finish, true, options)).to eq(output)
|
|
346
505
|
end
|
|
347
506
|
end
|
|
348
507
|
|
|
508
|
+
it "raises ArgumentError when an unrecognized value is passed for highest_measure.remainder" do
|
|
509
|
+
expect do
|
|
510
|
+
distance_of_time_in_words(START_TIME, START_TIME + 1.day, true, { highest_measures: { remainder: :oops }})
|
|
511
|
+
end.to raise_error(ArgumentError)
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
describe 'folding excluded fractions into included ones (regression for #77 and #120)' do
|
|
515
|
+
it 'folds excluded weeks into days rather than discarding them' do
|
|
516
|
+
from = '2019-01-02'.to_time
|
|
517
|
+
to = '2020-12-28'.to_time
|
|
518
|
+
expect(distance_of_time_in_words(from, to, false, only: %i[years months days]))
|
|
519
|
+
.to eq('1 year, 11 months, and 26 days')
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
it 'folds excluded weeks into days when using except' do
|
|
523
|
+
from = '2019-01-02'.to_time
|
|
524
|
+
to = '2020-12-28'.to_time
|
|
525
|
+
expect(distance_of_time_in_words(from, to, false, except: :weeks))
|
|
526
|
+
.to eq('1 year, 11 months, and 26 days')
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
it 'folds an excluded month into days' do
|
|
530
|
+
expect(distance_of_time_in_words(START_TIME, START_TIME + 1.month + 9.days, false, only: %i[months days]))
|
|
531
|
+
.to eq('1 month and 9 days')
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
it 'converts a negative day count into a week when the day-of-month matches but the hour rolls back' do
|
|
535
|
+
from = Time.new(2024, 5, 1, 10, 0, 0)
|
|
536
|
+
to = Time.new(2024, 6, 1, 9, 0, 0)
|
|
537
|
+
expect(distance_of_time_in_words(from, to, false, only: %i[months weeks days]))
|
|
538
|
+
.to eq('4 weeks and 2 days')
|
|
539
|
+
end
|
|
540
|
+
end
|
|
541
|
+
|
|
349
542
|
if defined?(ActionView)
|
|
350
543
|
describe 'ActionView without include seconds argument' do
|
|
351
544
|
[
|
|
@@ -391,13 +584,31 @@ describe 'A better distance_of_time_in_words' do
|
|
|
391
584
|
[START_TIME,
|
|
392
585
|
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
393
586
|
{ vague: nil },
|
|
394
|
-
'1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds']
|
|
587
|
+
'1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds'],
|
|
588
|
+
[START_TIME,
|
|
589
|
+
START_TIME + 1.year + 2.months,
|
|
590
|
+
{ vague: true, locale: :en },
|
|
591
|
+
'about 1 year']
|
|
395
592
|
].each do |start, finish, options, output|
|
|
396
593
|
it "should be #{output}" do
|
|
397
594
|
expect(distance_of_time_in_words(start, finish, true, options)).to eq(output)
|
|
398
595
|
end
|
|
399
596
|
end
|
|
400
|
-
|
|
597
|
+
|
|
598
|
+
# requires the rails-i18n gem for non-English datetime.distance_in_words translations, see #44
|
|
599
|
+
if defined?(RailsI18n)
|
|
600
|
+
it 'should be rundt 1 år for vague: true, locale: :nb' do
|
|
601
|
+
finish = START_TIME + 1.year + 2.months
|
|
602
|
+
expect(distance_of_time_in_words(START_TIME, finish, true, vague: true, locale: :nb)).to eq('rundt 1 år')
|
|
603
|
+
end
|
|
604
|
+
else
|
|
605
|
+
it 'returns a translation missing message for vague: true, locale: :nb without the rails-i18n gem' do
|
|
606
|
+
finish = START_TIME + 1.year + 2.months
|
|
607
|
+
expect(distance_of_time_in_words(START_TIME, finish, true, vague: true, locale: :nb))
|
|
608
|
+
.to eq('Translation missing: nb.datetime.distance_in_words.about_x_years')
|
|
609
|
+
end
|
|
610
|
+
end
|
|
611
|
+
|
|
401
612
|
context 'via ActionController::Base.helpers' do
|
|
402
613
|
it '#distance_of_time_in_words' do
|
|
403
614
|
end_time = START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
seconds:
|
|
2
|
+
1.second: སྐར་ཆ་ ༡
|
|
3
|
+
3.seconds: སྐར་ཆ་ 3
|
|
4
|
+
minutes:
|
|
5
|
+
1.minute: སྐར་མ་ ༡
|
|
6
|
+
20.minutes: སྐར་མ་ 20
|
|
7
|
+
hours:
|
|
8
|
+
1.hour: ཆུ་ཚོད་ ༡
|
|
9
|
+
5.hours: ཆུ་ཚོད་ 5
|
|
10
|
+
days:
|
|
11
|
+
1.day: ཉིནམ་ ༡
|
|
12
|
+
6.days: ཉིནམ་ 6
|
|
13
|
+
weeks:
|
|
14
|
+
1.week: བདུན༌ཕྲག་ ༡
|
|
15
|
+
2.weeks: བདུན༌ཕྲག་ 2
|
|
16
|
+
months:
|
|
17
|
+
1.month: ཟླཝ་ ༡
|
|
18
|
+
9.months: ཟླཝ་ 9
|
|
19
|
+
years:
|
|
20
|
+
1.year: ལོ་ ༡
|
|
21
|
+
3.years: ལོ་ 3
|
data/spec/lib/i18n/ru.yml
CHANGED
|
@@ -3,3 +3,21 @@ seconds:
|
|
|
3
3
|
1.second: 1 секунда
|
|
4
4
|
minutes:
|
|
5
5
|
1.minute: 1 минута
|
|
6
|
+
compact seconds:
|
|
7
|
+
1.second: 1с
|
|
8
|
+
11.seconds: 11с
|
|
9
|
+
21.seconds: 21с
|
|
10
|
+
compact minutes:
|
|
11
|
+
1.minute: 1м
|
|
12
|
+
11.minutes: 11м
|
|
13
|
+
21.minutes: 21м
|
|
14
|
+
compact hours:
|
|
15
|
+
1.hour: 1ч
|
|
16
|
+
11.hours: 11ч
|
|
17
|
+
21.hours: 21ч
|
|
18
|
+
compact days:
|
|
19
|
+
1.day: 1д
|
|
20
|
+
compact years:
|
|
21
|
+
1.year: 1г
|
|
22
|
+
11.years: 11г
|
|
23
|
+
21.years: 21г
|
data/spec/spec_helper.rb
CHANGED
|
@@ -3,8 +3,27 @@
|
|
|
3
3
|
ROOT_PATH = File.join(File.dirname(__FILE__), '..')
|
|
4
4
|
$LOAD_PATH.unshift ROOT_PATH unless $LOAD_PATH.include? ROOT_PATH
|
|
5
5
|
|
|
6
|
+
require 'simplecov'
|
|
7
|
+
SimpleCov.start do
|
|
8
|
+
add_filter '/spec/'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Ruby 3.4 dropped concurrent-ruby's implicit require of logger, which older
|
|
12
|
+
# Rails versions rely on being already loaded, see https://github.com/rails/rails/issues/54271.
|
|
13
|
+
require 'logger'
|
|
14
|
+
require 'bundler'
|
|
15
|
+
Bundler.require
|
|
16
|
+
|
|
6
17
|
require 'dotiw'
|
|
7
18
|
|
|
19
|
+
# Loads Rails' own datetime.distance_in_words translations for non-English
|
|
20
|
+
# locales, needed by the vague: true option, which falls back to Rails'
|
|
21
|
+
# native distance_of_time_in_words instead of dotiw's own translations, see #44.
|
|
22
|
+
# Only present when the rails-i18n gem is in the Gemfile (see gemfiles/rails_8.1_i18n.gemfile).
|
|
23
|
+
if defined?(RailsI18n)
|
|
24
|
+
I18n.load_path += Dir[File.join(Gem.loaded_specs['rails-i18n'].gem_dir, 'rails', 'locale', '*.yml')]
|
|
25
|
+
end
|
|
26
|
+
|
|
8
27
|
Time.zone = 'UTC'
|
|
9
28
|
|
|
10
29
|
I18n.locale = :en
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dotiw
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Bigg
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2026-08-28 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activesupport
|
|
@@ -110,19 +110,61 @@ dependencies:
|
|
|
110
110
|
- !ruby/object:Gem::Version
|
|
111
111
|
version: '3.0'
|
|
112
112
|
- !ruby/object:Gem::Dependency
|
|
113
|
-
name:
|
|
113
|
+
name: mutex_m
|
|
114
114
|
requirement: !ruby/object:Gem::Requirement
|
|
115
115
|
requirements:
|
|
116
|
-
- - "
|
|
116
|
+
- - ">="
|
|
117
117
|
- !ruby/object:Gem::Version
|
|
118
|
-
version:
|
|
118
|
+
version: '0'
|
|
119
119
|
type: :development
|
|
120
120
|
prerelease: false
|
|
121
121
|
version_requirements: !ruby/object:Gem::Requirement
|
|
122
122
|
requirements:
|
|
123
|
-
- - "
|
|
123
|
+
- - ">="
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: '0'
|
|
126
|
+
- !ruby/object:Gem::Dependency
|
|
127
|
+
name: base64
|
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
|
129
|
+
requirements:
|
|
130
|
+
- - ">="
|
|
124
131
|
- !ruby/object:Gem::Version
|
|
125
|
-
version:
|
|
132
|
+
version: '0'
|
|
133
|
+
type: :development
|
|
134
|
+
prerelease: false
|
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
136
|
+
requirements:
|
|
137
|
+
- - ">="
|
|
138
|
+
- !ruby/object:Gem::Version
|
|
139
|
+
version: '0'
|
|
140
|
+
- !ruby/object:Gem::Dependency
|
|
141
|
+
name: bigdecimal
|
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
|
143
|
+
requirements:
|
|
144
|
+
- - ">="
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: '0'
|
|
147
|
+
type: :development
|
|
148
|
+
prerelease: false
|
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
150
|
+
requirements:
|
|
151
|
+
- - ">="
|
|
152
|
+
- !ruby/object:Gem::Version
|
|
153
|
+
version: '0'
|
|
154
|
+
- !ruby/object:Gem::Dependency
|
|
155
|
+
name: simplecov
|
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
|
157
|
+
requirements:
|
|
158
|
+
- - ">="
|
|
159
|
+
- !ruby/object:Gem::Version
|
|
160
|
+
version: '0'
|
|
161
|
+
type: :development
|
|
162
|
+
prerelease: false
|
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
164
|
+
requirements:
|
|
165
|
+
- - ">="
|
|
166
|
+
- !ruby/object:Gem::Version
|
|
167
|
+
version: '0'
|
|
126
168
|
description: |-
|
|
127
169
|
dotiw is a gem for Rails that overrides the
|
|
128
170
|
default distance_of_time_in_words and provides
|
|
@@ -141,24 +183,34 @@ files:
|
|
|
141
183
|
- ".rspec"
|
|
142
184
|
- Appraisals
|
|
143
185
|
- CHANGELOG.md
|
|
186
|
+
- CODEOWNERS
|
|
144
187
|
- CONTRIBUTING.md
|
|
145
188
|
- Gemfile
|
|
146
189
|
- MIT-LICENSE
|
|
147
190
|
- README.markdown
|
|
191
|
+
- RELEASING.md
|
|
148
192
|
- Rakefile
|
|
193
|
+
- benchmarks/distance_of_time_in_words_bench.rb
|
|
149
194
|
- benchmarks/time_hash_bench.rb
|
|
150
195
|
- dotiw.gemspec
|
|
151
196
|
- gemfiles/.bundle/config
|
|
152
|
-
- gemfiles/rails_4.gemfile
|
|
153
197
|
- gemfiles/rails_5.0.gemfile
|
|
154
198
|
- gemfiles/rails_5.1.gemfile
|
|
155
199
|
- gemfiles/rails_5.2.gemfile
|
|
156
200
|
- gemfiles/rails_6.0.gemfile
|
|
201
|
+
- gemfiles/rails_7.0.gemfile
|
|
202
|
+
- gemfiles/rails_7.1.gemfile
|
|
203
|
+
- gemfiles/rails_7.2.gemfile
|
|
204
|
+
- gemfiles/rails_8.0.gemfile
|
|
205
|
+
- gemfiles/rails_8.1.gemfile
|
|
206
|
+
- gemfiles/rails_8.1_i18n.gemfile
|
|
157
207
|
- lib/dotiw.rb
|
|
158
208
|
- lib/dotiw/action_view/helpers/date_helper.rb
|
|
209
|
+
- lib/dotiw/core.rb
|
|
159
210
|
- lib/dotiw/locale/ar.yml
|
|
160
211
|
- lib/dotiw/locale/da.yml
|
|
161
212
|
- lib/dotiw/locale/de.yml
|
|
213
|
+
- lib/dotiw/locale/dz.yml
|
|
162
214
|
- lib/dotiw/locale/en.yml
|
|
163
215
|
- lib/dotiw/locale/es.yml
|
|
164
216
|
- lib/dotiw/locale/fr.yml
|
|
@@ -178,10 +230,12 @@ files:
|
|
|
178
230
|
- lib/dotiw/methods.rb
|
|
179
231
|
- lib/dotiw/time_hash.rb
|
|
180
232
|
- lib/dotiw/version.rb
|
|
233
|
+
- spec/lib/dotiw_module_spec.rb
|
|
181
234
|
- spec/lib/dotiw_spec.rb
|
|
182
235
|
- spec/lib/i18n/ar.yml
|
|
183
236
|
- spec/lib/i18n/da.yml
|
|
184
237
|
- spec/lib/i18n/de.yml
|
|
238
|
+
- spec/lib/i18n/dz.yml
|
|
185
239
|
- spec/lib/i18n/en.yml
|
|
186
240
|
- spec/lib/i18n/es.yml
|
|
187
241
|
- spec/lib/i18n/fr.yml
|
|
@@ -218,15 +272,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
218
272
|
- !ruby/object:Gem::Version
|
|
219
273
|
version: '0'
|
|
220
274
|
requirements: []
|
|
221
|
-
rubygems_version: 3.
|
|
275
|
+
rubygems_version: 3.5.16
|
|
222
276
|
signing_key:
|
|
223
277
|
specification_version: 4
|
|
224
278
|
summary: Better distance_of_time_in_words for Rails
|
|
225
279
|
test_files:
|
|
280
|
+
- spec/lib/dotiw_module_spec.rb
|
|
226
281
|
- spec/lib/dotiw_spec.rb
|
|
227
282
|
- spec/lib/i18n/ar.yml
|
|
228
283
|
- spec/lib/i18n/da.yml
|
|
229
284
|
- spec/lib/i18n/de.yml
|
|
285
|
+
- spec/lib/i18n/dz.yml
|
|
230
286
|
- spec/lib/i18n/en.yml
|
|
231
287
|
- spec/lib/i18n/es.yml
|
|
232
288
|
- spec/lib/i18n/fr.yml
|