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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d52199ee419e6e9effc50ae35409aa01605c4e2b05306ddf2ba4a7d5d9a627d
4
- data.tar.gz: c069bf8d7cc9078b9091284084907f777155b2a698b9fe9067ad4ee621dd4982
3
+ metadata.gz: e1c8a832bcdb740a88002dec2f5c843daeca75b2674b2e31c26abc17a144c6a2
4
+ data.tar.gz: 163a34f6e15e34026375176118399cc65ed73b2f723dab436bc9aedaf36dc0b7
5
5
  SHA512:
6
- metadata.gz: 9578117b3360f17e92d49ffe07b4071f805d9c8737033c5431f9ed6e6a9e75aec787d3ef22c9e156af2f1186083cb38c9b4039b9cb12b05cf4ea0dbfd7ce0d83
7
- data.tar.gz: c463d39fdf6b1e811a850b23ab363f4a1e4bf3cd76515621d90ee347489762e4cb0c436cdca038487954af6124c60ef9b84902ccc5a9a7ffa034aabee0826b16
6
+ metadata.gz: 6e1a5291d51d629e4fc27d3f915f84586089be0869a676107154ef5f865c46fac768c4a2e7d86ac5fdfc2aadc879b668923f130f2f75ad0c355cbb86a5b18cc4
7
+ data.tar.gz: f575e5e232a5adfefd8f81aa15f132dc352d020233bd1f66f6cddca473031d5cce0abf76bfd0842e0b55c3c60d4a44e2e7cf56a28b6e6fc89245e9fd17705bd7
@@ -15,23 +15,23 @@ jobs:
15
15
  fail-fast: false
16
16
  matrix:
17
17
  include:
18
- - ruby-version: 2.5.x
19
- - ruby-version: 2.6.x
20
- - ruby-version: 2.4.x
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.x
23
+ - ruby-version: 2.6
24
24
  gemfile: gemfiles/rails_5.0.gemfile
25
- - ruby-version: 2.6.x
25
+ - ruby-version: 2.6
26
26
  gemfile: gemfiles/rails_5.1.gemfile
27
- - ruby-version: 2.6.x
27
+ - ruby-version: 2.6
28
28
  gemfile: gemfiles/rails_5.2.gemfile
29
- - ruby-version: 2.6.x
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: actions/setup-ruby@v1
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
@@ -37,7 +37,7 @@ module DOTIW
37
37
  def files(directory, ext)
38
38
  Dir[File.join File.dirname(__FILE__), directory, ext]
39
39
  end
40
- end # DOTIW
40
+ end
41
41
 
42
42
  DOTIW.init_i18n!
43
43
 
@@ -3,14 +3,21 @@
3
3
  module ActionView
4
4
  module Helpers
5
5
  module DateHelper
6
- alias_method :_distance_of_time_in_words, :distance_of_time_in_words
7
- alias_method :_time_ago_in_words, :time_ago_in_words
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.delete(:vague)
13
- DOTIW::Methods.distance_of_time_in_words(from_time, to_time, include_seconds_or_options, options)
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 # DateHelper
24
- end # Helpers
25
- end # ActionView
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[:include_seconds] ||= true
16
- _display_time_in_words DOTIW::TimeHash.new(seconds, nil, nil, options_with_scope(options)).to_hash, options
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
- options.merge!({:scope => DOTIW::DEFAULT_I18N_SCOPE_COMPACT}) if options.delete(:compact)
40
- options
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 # DOTIW
108
+ end
@@ -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.delete(:accumulate_on)
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 < 1.minute
51
+ if distance < ONE_MINUTE
46
52
  build_seconds
47
- elsif distance < 1.hour
53
+ elsif distance < ONE_HOUR
48
54
  build_minutes
49
- elsif distance < 1.day
55
+ elsif distance < ONE_DAY
50
56
  build_hours
51
- elsif distance < 7.days
57
+ elsif distance < ONE_WEEK
52
58
  build_days
53
- elsif distance < 28.days
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(1.minute.to_i)
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(1.hour.to_i)
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(1.day.to_i) unless output[:days]
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(1.week.to_i) unless output[:weeks]
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(1.day.to_i)
146
+ total_days, @distance = distance.abs.divmod(ONE_DAY.to_i)
141
147
 
142
148
  [total_days, @distance]
143
149
  end
144
- end # TimeHash
145
- end # DOTIW
150
+ end
151
+ end
data/lib/dotiw/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DOTIW
4
- VERSION = '5.2.0'
4
+ VERSION = '5.3.0'
5
5
  end
@@ -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, "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"]
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, '1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 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 # :accumulate_on
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, { vague: false })
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 # include_seconds
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.2.0
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: 2020-10-03 00:00:00.000000000 Z
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.2
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