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 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