dotiw 5.2.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 +4 -4
- data/.github/workflows/ruby.yml +8 -8
- data/CHANGELOG.md +7 -0
- data/README.markdown +4 -1
- data/benchmarks/time_hash_bench.rb +19 -0
- data/lib/dotiw.rb +1 -1
- data/lib/dotiw/action_view/helpers/date_helper.rb +14 -7
- data/lib/dotiw/methods.rb +16 -7
- data/lib/dotiw/time_hash.rb +20 -14
- data/lib/dotiw/version.rb +1 -1
- data/spec/lib/dotiw_spec.rb +58 -13
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1c8a832bcdb740a88002dec2f5c843daeca75b2674b2e31c26abc17a144c6a2
|
4
|
+
data.tar.gz: 163a34f6e15e34026375176118399cc65ed73b2f723dab436bc9aedaf36dc0b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e1a5291d51d629e4fc27d3f915f84586089be0869a676107154ef5f865c46fac768c4a2e7d86ac5fdfc2aadc879b668923f130f2f75ad0c355cbb86a5b18cc4
|
7
|
+
data.tar.gz: f575e5e232a5adfefd8f81aa15f132dc352d020233bd1f66f6cddca473031d5cce0abf76bfd0842e0b55c3c60d4a44e2e7cf56a28b6e6fc89245e9fd17705bd7
|
data/.github/workflows/ruby.yml
CHANGED
@@ -15,23 +15,23 @@ jobs:
|
|
15
15
|
fail-fast: false
|
16
16
|
matrix:
|
17
17
|
include:
|
18
|
-
- ruby-version: 2.5
|
19
|
-
- ruby-version: 2.6
|
20
|
-
- ruby-version: 2.4
|
18
|
+
- ruby-version: 2.5
|
19
|
+
- ruby-version: 2.6
|
20
|
+
- ruby-version: 2.4
|
21
21
|
bundler-version: 1.17.3
|
22
22
|
gemfile: gemfiles/rails_4.gemfile
|
23
|
-
- ruby-version: 2.6
|
23
|
+
- ruby-version: 2.6
|
24
24
|
gemfile: gemfiles/rails_5.0.gemfile
|
25
|
-
- ruby-version: 2.6
|
25
|
+
- ruby-version: 2.6
|
26
26
|
gemfile: gemfiles/rails_5.1.gemfile
|
27
|
-
- ruby-version: 2.6
|
27
|
+
- ruby-version: 2.6
|
28
28
|
gemfile: gemfiles/rails_5.2.gemfile
|
29
|
-
- ruby-version: 2.6
|
29
|
+
- ruby-version: 2.6
|
30
30
|
gemfile: gemfiles/rails_6.0.gemfile
|
31
31
|
steps:
|
32
32
|
- uses: actions/checkout@v2
|
33
33
|
- name: Set up Ruby
|
34
|
-
uses:
|
34
|
+
uses: ruby/setup-ruby@v1
|
35
35
|
with:
|
36
36
|
ruby-version: ${{ matrix.ruby-version }}
|
37
37
|
- name: Build and test
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## 5.3.0 (2021/03/18)
|
2
|
+
|
3
|
+
* [#115](https://github.com/radar/distance_of_time_in_words/pull/115): Use constants for time durations (2x faster, 3.5x less memory) - [@krzysiek1507](https://github.com/krzysiek1507).
|
4
|
+
* [#117](https://github.com/radar/distance_of_time_in_words/pull/117): Support `#distance_of_time_in_words_to_now` with `vague: true` - [@joshuapinter](https://github.com/joshuapinter).
|
5
|
+
* [#118](https://github.com/radar/distance_of_time_in_words/pull/118): Raise `ArgumentError` when `nil` is passed for time, to match original `distance_of_time_in_words` - [@joshuapinter](https://github.com/joshuapinter).
|
6
|
+
* [#119](https://github.com/radar/distance_of_time_in_words/pull/119): Do not mutate input options - [@joshuapinter](https://github.com/joshuapinter).
|
7
|
+
|
1
8
|
## 5.2.0 (2020/10/03)
|
2
9
|
|
3
10
|
* [#94](https://github.com/radar/distance_of_time_in_words/pull/94): Add :compact formatting option - [@booty](https://github.com/booty).
|
data/README.markdown
CHANGED
@@ -69,12 +69,15 @@ Yes this could just be merged into the options hash but I'm leaving it here to e
|
|
69
69
|
|
70
70
|
The last argument is an optional options hash that can be used to manipulate behavior and (which uses `to_sentence`).
|
71
71
|
|
72
|
-
Don't like having to pass in `Time.now` all the time? Then use `time_ago_in_words` which also will *rock your
|
72
|
+
Don't like having to pass in `Time.now` all the time? Then use `time_ago_in_words` or `distance_of_time_in_words_to_now` which also will *rock your
|
73
73
|
world*:
|
74
74
|
|
75
75
|
```ruby
|
76
76
|
>> time_ago_in_words(Time.now + 3.days + 1.second)
|
77
77
|
=> "3 days, and 1 second"
|
78
|
+
|
79
|
+
>> distance_of_time_in_words_to_now(Time.now + 3.days + 1.second)
|
80
|
+
=> "3 days, and 1 second"
|
78
81
|
```
|
79
82
|
|
80
83
|
Oh, and did I mention it supports I18n? Oh yeah. Rock on!
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'benchmark/ips'
|
4
|
+
require 'benchmark/memory'
|
5
|
+
require 'active_support/core_ext/numeric'
|
6
|
+
require 'active_support/core_ext/integer'
|
7
|
+
|
8
|
+
require_relative '../lib/dotiw/time_hash'
|
9
|
+
|
10
|
+
from = Time.now
|
11
|
+
to = Time.now + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds
|
12
|
+
|
13
|
+
%i[ips memory].each do |type|
|
14
|
+
Benchmark.public_send(type) do |x|
|
15
|
+
x.report('master') { DOTIW::TimeHash.new(nil, from, to) }
|
16
|
+
|
17
|
+
x.compare!
|
18
|
+
end
|
19
|
+
end
|
data/lib/dotiw.rb
CHANGED
@@ -3,14 +3,21 @@
|
|
3
3
|
module ActionView
|
4
4
|
module Helpers
|
5
5
|
module DateHelper
|
6
|
-
|
7
|
-
|
6
|
+
alias _distance_of_time_in_words distance_of_time_in_words
|
7
|
+
alias _time_ago_in_words time_ago_in_words
|
8
8
|
|
9
9
|
include DOTIW::Methods
|
10
10
|
|
11
11
|
def distance_of_time_in_words(from_time, to_time = 0, include_seconds_or_options = {}, options = {})
|
12
|
-
return _distance_of_time_in_words(from_time, to_time, options) if options
|
13
|
-
|
12
|
+
return _distance_of_time_in_words(from_time, to_time, options) if options[:vague]
|
13
|
+
|
14
|
+
DOTIW::Methods.distance_of_time_in_words(from_time, to_time, include_seconds_or_options, options.except(:vague))
|
15
|
+
end
|
16
|
+
|
17
|
+
def distance_of_time_in_words_to_now(to_time = 0, include_seconds_or_options = {}, options = {})
|
18
|
+
return _distance_of_time_in_words(Time.now, to_time, options) if options[:vague]
|
19
|
+
|
20
|
+
DOTIW::Methods.distance_of_time_in_words(Time.now, to_time, include_seconds_or_options, options.except(:vague))
|
14
21
|
end
|
15
22
|
|
16
23
|
def distance_of_time_in_percent(from_time, current_time, to_time, options = {})
|
@@ -20,6 +27,6 @@ module ActionView
|
|
20
27
|
result = ((current_time - from_time) / distance) * 100
|
21
28
|
number_with_precision(result, options).to_s + '%'
|
22
29
|
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/dotiw/methods.rb
CHANGED
@@ -12,14 +12,20 @@ module DOTIW
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def distance_of_time(seconds, options = {})
|
15
|
-
options
|
16
|
-
|
15
|
+
options = options_with_scope(options).reverse_merge(
|
16
|
+
include_seconds: true
|
17
|
+
)
|
18
|
+
options.delete(:compact)
|
19
|
+
_display_time_in_words DOTIW::TimeHash.new(seconds, nil, nil, options).to_hash, options
|
17
20
|
end
|
18
21
|
|
19
22
|
def distance_of_time_in_words(from_time, to_time = 0, include_seconds_or_options = {}, options = {})
|
23
|
+
raise ArgumentError, "nil can't be converted to a Time value" if from_time.nil? || to_time.nil?
|
24
|
+
|
20
25
|
if include_seconds_or_options.is_a?(Hash)
|
21
26
|
options = include_seconds_or_options
|
22
27
|
else
|
28
|
+
options = options.dup
|
23
29
|
options[:include_seconds] ||= !!include_seconds_or_options
|
24
30
|
end
|
25
31
|
return distance_of_time(from_time, options) if to_time == 0
|
@@ -36,12 +42,15 @@ module DOTIW
|
|
36
42
|
private
|
37
43
|
|
38
44
|
def options_with_scope(options)
|
39
|
-
|
40
|
-
|
45
|
+
if options.key?(:compact)
|
46
|
+
options.merge(scope: DOTIW::DEFAULT_I18N_SCOPE_COMPACT)
|
47
|
+
else
|
48
|
+
options
|
49
|
+
end
|
41
50
|
end
|
42
51
|
|
43
52
|
def _display_time_in_words(hash, options = {})
|
44
|
-
options.reverse_merge
|
53
|
+
options = options.reverse_merge(
|
45
54
|
include_seconds: false
|
46
55
|
).symbolize_keys!
|
47
56
|
|
@@ -93,7 +102,7 @@ module DOTIW
|
|
93
102
|
default: :'support.array.last_word_connector',
|
94
103
|
locale: options[:locale]
|
95
104
|
|
96
|
-
output.to_sentence(options)
|
105
|
+
output.to_sentence(options.except(:accumulate_on))
|
97
106
|
end
|
98
107
|
end
|
99
|
-
end
|
108
|
+
end
|
data/lib/dotiw/time_hash.rb
CHANGED
@@ -8,7 +8,7 @@ module DOTIW
|
|
8
8
|
|
9
9
|
def initialize(distance, from_time, to_time = nil, options = {})
|
10
10
|
@output = {}
|
11
|
-
@options = options
|
11
|
+
@options = options.dup
|
12
12
|
@distance = distance
|
13
13
|
@from_time = from_time || Time.current
|
14
14
|
@to_time = to_time || (@to_time_not_given = true && @from_time + distance.seconds)
|
@@ -34,23 +34,29 @@ module DOTIW
|
|
34
34
|
|
35
35
|
attr_reader :options, :output
|
36
36
|
|
37
|
+
ONE_MINUTE = 1.minute.freeze
|
38
|
+
ONE_HOUR = 1.hour.freeze
|
39
|
+
ONE_DAY = 1.day.freeze
|
40
|
+
ONE_WEEK = 7.days.freeze
|
41
|
+
FOUR_WEEKS = 28.days.freeze
|
42
|
+
|
37
43
|
def build_time_hash
|
38
|
-
if accumulate_on = options
|
44
|
+
if accumulate_on = options[:accumulate_on]
|
39
45
|
accumulate_on = accumulate_on.to_sym
|
40
46
|
return build_time_hash if accumulate_on == :years
|
41
47
|
|
42
48
|
TIME_FRACTIONS.index(accumulate_on).downto(0) { |i| send("build_#{TIME_FRACTIONS[i]}") }
|
43
49
|
else
|
44
50
|
while distance > 0
|
45
|
-
if distance <
|
51
|
+
if distance < ONE_MINUTE
|
46
52
|
build_seconds
|
47
|
-
elsif distance <
|
53
|
+
elsif distance < ONE_HOUR
|
48
54
|
build_minutes
|
49
|
-
elsif distance <
|
55
|
+
elsif distance < ONE_DAY
|
50
56
|
build_hours
|
51
|
-
elsif distance <
|
57
|
+
elsif distance < ONE_WEEK
|
52
58
|
build_days
|
53
|
-
elsif distance <
|
59
|
+
elsif distance < FOUR_WEEKS
|
54
60
|
build_weeks
|
55
61
|
else # greater than a week
|
56
62
|
build_years_months_weeks_days
|
@@ -67,19 +73,19 @@ module DOTIW
|
|
67
73
|
end
|
68
74
|
|
69
75
|
def build_minutes
|
70
|
-
output[:minutes], @distance = distance.divmod(
|
76
|
+
output[:minutes], @distance = distance.divmod(ONE_MINUTE.to_i)
|
71
77
|
end
|
72
78
|
|
73
79
|
def build_hours
|
74
|
-
output[:hours], @distance = distance.divmod(
|
80
|
+
output[:hours], @distance = distance.divmod(ONE_HOUR.to_i)
|
75
81
|
end
|
76
82
|
|
77
83
|
def build_days
|
78
|
-
output[:days], @distance = distance.divmod(
|
84
|
+
output[:days], @distance = distance.divmod(ONE_DAY.to_i) unless output[:days]
|
79
85
|
end
|
80
86
|
|
81
87
|
def build_weeks
|
82
|
-
output[:weeks], @distance = distance.divmod(
|
88
|
+
output[:weeks], @distance = distance.divmod(ONE_WEEK.to_i) unless output[:weeks]
|
83
89
|
end
|
84
90
|
|
85
91
|
def build_months
|
@@ -137,9 +143,9 @@ module DOTIW
|
|
137
143
|
output[:weeks] = weeks
|
138
144
|
output[:days] = days
|
139
145
|
|
140
|
-
total_days, @distance = distance.abs.divmod(
|
146
|
+
total_days, @distance = distance.abs.divmod(ONE_DAY.to_i)
|
141
147
|
|
142
148
|
[total_days, @distance]
|
143
149
|
end
|
144
|
-
end
|
145
|
-
end
|
150
|
+
end
|
151
|
+
end
|
data/lib/dotiw/version.rb
CHANGED
data/spec/lib/dotiw_spec.rb
CHANGED
@@ -23,15 +23,15 @@ describe 'A better distance_of_time_in_words' do
|
|
23
23
|
|
24
24
|
describe '#distance_of_time' do
|
25
25
|
[
|
26
|
-
[0.5.minutes,
|
27
|
-
[4.5.minutes,
|
28
|
-
[5.minutes.to_i,
|
29
|
-
[10.minutes.to_i,
|
30
|
-
[1.hour.to_i,
|
31
|
-
[1.hour + 30.seconds,
|
32
|
-
[4.weeks.to_i,
|
33
|
-
[4.weeks + 2.days,
|
34
|
-
[24.weeks.to_i,
|
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
35
|
].each do |number, result, compact_result|
|
36
36
|
it "#{number} == #{result}" do
|
37
37
|
expect(distance_of_time(number)).to eq(result)
|
@@ -101,6 +101,11 @@ describe 'A better distance_of_time_in_words' do
|
|
101
101
|
expect(DOTIW.languages.map(&:to_s).sort).to eq languages.sort
|
102
102
|
end
|
103
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
|
+
|
104
109
|
DOTIW.languages.each do |lang|
|
105
110
|
context lang do
|
106
111
|
YAML.safe_load(
|
@@ -138,7 +143,8 @@ describe 'A better distance_of_time_in_words' do
|
|
138
143
|
[START_TIME, START_TIME + 3.hour, '3 hours'],
|
139
144
|
[START_TIME, START_TIME + 13.months, '1 year and 1 month'],
|
140
145
|
# Any numeric sequence is merely coincidental.
|
141
|
-
[START_TIME, START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
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'],
|
142
148
|
['2009-3-16'.to_time, '2008-4-14'.to_time, '11 months and 2 days'],
|
143
149
|
['2009-3-16'.to_time + 1.minute, '2008-4-14'.to_time, '11 months, 2 days, and 1 minute'],
|
144
150
|
['2009-4-14'.to_time, '2008-3-16'.to_time, '1 year, 4 weeks, and 1 day'],
|
@@ -215,7 +221,7 @@ describe 'A better distance_of_time_in_words' do
|
|
215
221
|
expect(distance_of_time_in_words(start, finish, true, accumulate_on: accumulator)).to eq(output)
|
216
222
|
end
|
217
223
|
end
|
218
|
-
end
|
224
|
+
end
|
219
225
|
|
220
226
|
describe 'without finish time' do
|
221
227
|
# A missing finish argument should default to zero, essentially returning
|
@@ -341,7 +347,8 @@ describe 'A better distance_of_time_in_words' do
|
|
341
347
|
it '#distance_of_time_in_words' do
|
342
348
|
end_time = START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds
|
343
349
|
expected = '1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds'
|
344
|
-
actual = ActionController::Base.helpers.distance_of_time_in_words(START_TIME, end_time, true,
|
350
|
+
actual = ActionController::Base.helpers.distance_of_time_in_words(START_TIME, end_time, true,
|
351
|
+
{ vague: false })
|
345
352
|
expect(actual).to eq(expected)
|
346
353
|
end
|
347
354
|
|
@@ -350,6 +357,44 @@ describe 'A better distance_of_time_in_words' do
|
|
350
357
|
actual = ActionController::Base.helpers.time_ago_in_words(Time.now - 3.days - 14.minutes)
|
351
358
|
expect(actual).to eq(expected)
|
352
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
|
353
398
|
end
|
354
399
|
end
|
355
400
|
end
|
@@ -368,7 +413,7 @@ describe 'A better distance_of_time_in_words' do
|
|
368
413
|
)
|
369
414
|
).to eq('1 year, 2 months, 3 weeks, 4 days, 5 hours, and 6 minutes')
|
370
415
|
end
|
371
|
-
end
|
416
|
+
end
|
372
417
|
end
|
373
418
|
|
374
419
|
if defined?(ActionView)
|
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.3.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: 2021-03-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -146,6 +146,7 @@ files:
|
|
146
146
|
- MIT-LICENSE
|
147
147
|
- README.markdown
|
148
148
|
- Rakefile
|
149
|
+
- benchmarks/time_hash_bench.rb
|
149
150
|
- dotiw.gemspec
|
150
151
|
- gemfiles/.bundle/config
|
151
152
|
- gemfiles/rails_4.gemfile
|
@@ -217,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
217
218
|
- !ruby/object:Gem::Version
|
218
219
|
version: '0'
|
219
220
|
requirements: []
|
220
|
-
rubygems_version: 3.1.
|
221
|
+
rubygems_version: 3.1.3
|
221
222
|
signing_key:
|
222
223
|
specification_version: 4
|
223
224
|
summary: Better distance_of_time_in_words for Rails
|