dotiw 5.2.0 → 5.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|