timerizer 0.3.1 → 0.3.2

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: e03bc2d5660e629ad3545c610bf09efa55fbe07cec5c364970eabb8001add9fd
4
- data.tar.gz: 050b2b058e5c63eda87f973e5adde7c84e34c9c230833c47f84eb7189ef0d774
3
+ metadata.gz: 02461e09b8beea13b38f2e36aab85ab643fe7975b2f96132aa7bdbe8930ed370
4
+ data.tar.gz: 9fe1a1573e379256bedf1628ea469ec65c0e68f3a8da842ed77d995b0b70f753
5
5
  SHA512:
6
- metadata.gz: bcc860c64450e0e1f099dca114205f727410a216846c25a61ce75b5052783e95a7b748df72227b9b1b108d44ca0eb11f4dbb81ac7ddcf715629f3a4d9e3135a1
7
- data.tar.gz: a9836b0cb9c429a8ed66fad757cea99f022934af83e7b5757f8bd84fdf805fe102624d6e14b41d6e9711cbb10dbb53fbd315798b86633de18edfb1e560d2b6ed
6
+ metadata.gz: 1135496242298cd85e09d05d945b156cd592f76f9645a4b4bd3693e8cda1f3b190e8a27130a64337077ae62ab4b47f3205e8fbdeb6178034e358bb7f682dcbc6
7
+ data.tar.gz: baa46d6fe2ad8cec7bd48199081624dd31f2499235c04f319c0bd27b58417dfbc649f1e41cf207b2156985f56ca6a76148926cbc09ea083e2023dd3963bc2354
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+ require 'forwardable'
3
+
4
+ module Timerizer
5
+ class Duration
6
+ # Wraps rounding a {Timerizer::Duration} to the nearest value by the number
7
+ # of "places", which are customary time units (seconds, minutes, hours,
8
+ # days, months, years, etc; decades and weeks are not included).
9
+ #
10
+ # @private
11
+ class RoundedTime
12
+ extend Forwardable
13
+
14
+ # @!method remainder_times
15
+ # @return (see TermTimes#remainder_times)
16
+ # @!method target_unit
17
+ # @return (see TermTimes#target_unit)
18
+ # @!method times
19
+ # @return (see TermTimes#times)
20
+ def_delegators :@tt, :remainder_times, :target_unit, :times
21
+
22
+ # Default "places" (units, e.g., hours/minutes) to use for rounding.
23
+ DEFAULT_PLACES = 2
24
+ # Default {Timerizer::Duration::UNITS} *not* to include in rounded value.
25
+ OMITTED_KEYS = [:decades, :weeks]
26
+
27
+ # Given an original {Timerizer::Duration} instance, return a new instance
28
+ # that "rounds" the duration to the closest value expressed in a certain
29
+ # number of units (default 2).
30
+ #
31
+ # @param [{Timerizer::Duration}] duration Object encapsulating a duration
32
+ # (in hours, minutes, etc) to "round" to a number of
33
+ # units specified by `places`.
34
+ # @param [Integer] places Number of units to include in rounded value.
35
+ # Default is 2.
36
+ # @param [Array<Symbol>] omitted_keys Units to omit from calculation or
37
+ # return value. Default is `[:decades, :weeks]`
38
+ # @return {Timerizer::Duration}
39
+ # @example
40
+ # t = (12.hours 16.minutes 47.seconds).ago
41
+ # d = Time.since(t)
42
+ # d2 = RoundedTime.call(d)
43
+ # d.to_s # => "12 hours, 16 minutes, 47 seconds"
44
+ # d2.to_s # => "12 hours, 17 minutes"
45
+ #
46
+ def self.call(duration, places = DEFAULT_PLACES,
47
+ omitted_keys = OMITTED_KEYS)
48
+ new(duration, places, omitted_keys).call
49
+ end
50
+
51
+ # High-level method to do calculations on component durations.
52
+ #
53
+ # @return {Timerizer::Duration}
54
+ #
55
+ def call
56
+ remainder = sum_of(remainder_times)
57
+ sum_of(times) + offset_from(remainder)
58
+ end
59
+
60
+ private
61
+
62
+ # Initial value for adding a collection of Duration instances.
63
+ # (see #sum_of)
64
+ ZERO_TIME = Timerizer::Duration.new(seconds: 0)
65
+ private_constant :ZERO_TIME
66
+
67
+ # Private initialiser to prevent direct instantiation by client code.
68
+ #
69
+ # @param [{Timerizer::Duration}] duration Object encapsulating a duration
70
+ # (in hours, minutes, etc) to "round" to a number of
71
+ # units specified by `places`.
72
+ # @param [Integer] places Number of units to include in rounded value.
73
+ # Default is 2.
74
+ # @param [Array<Symbol>] omitted_keys Units to omit from calculation or
75
+ # return value. Default is `[:decades, :weeks]`
76
+ #
77
+ def initialize(duration, places = DEFAULT_PLACES,
78
+ omitted_keys = OMITTED_KEYS)
79
+ @tt = TermTimes.new(duration, omitted_keys).call(places).freeze
80
+ end
81
+
82
+ # Determine whether returned {Timerizer::Duration} value should be rounded
83
+ # up or down based on a remainder value.
84
+ #
85
+ # If the remainder value is more than half of the {#target_unit}, then
86
+ # this will return a duration of 1 times the target unit, else a duration
87
+ # of {ZERO_TIME}.
88
+ #
89
+ # @return [{Timerizer::Duration}] Either zero or 1 times the `target_unit`
90
+ # @param [{Timerizer::Duration}] remainder Value of input duration less
91
+ # than one `target_unit`
92
+ def offset_from(remainder)
93
+ Timerizer::Duration.new((remainder * 2).to_units(target_unit))
94
+ end
95
+
96
+ # Add all time (Duration) values in an Array (or other Enumerable).
97
+ #
98
+ # @return [{Timerizer::Duration}] Sum total of input values.
99
+ # @param [Array<{Timerizer::Duration}>] Unit values to add together
100
+ #
101
+ def sum_of(time_values)
102
+ time_values.inject(ZERO_TIME, :+)
103
+ end
104
+
105
+ # Convert a single {Timerizer::Duration} instance into an enumeration of
106
+ # per-unit Duration instances (hours, minutes, etc).
107
+ #
108
+ # @private
109
+ class TermTimes
110
+ # Least-significant time unit (e.g., ``:days`) used for rounding.
111
+ # @return [Symbol] Least-significant time unit in the resulting value.
112
+ attr_reader :target_unit
113
+ # Time units to be included in "rounded" result, before rounding.
114
+ # @return [Array<{Timerizer::Duration}>] Base result time-unit values.
115
+ attr_reader :times
116
+ # Time units to be "rounded" to adjust resulting Duration value.
117
+ # @return [Array<{Timerizer::Duration}>] Remaining time-unit values.
118
+ attr_reader :remainder_times
119
+
120
+ # Build array of time-part values based on input {Timerizer::Duration}.
121
+ #
122
+ # @param [{Timerizer::Duration}] duration Time differential used as
123
+ # input.
124
+ # @param [Array<Symbol>] omitted_keys {Timerizer::Duration::UNITS}
125
+ # values to exclude from resulting value.
126
+ #
127
+ def initialize(duration, omitted_keys)
128
+ @part_values = filter_units(duration, omitted_keys)
129
+ end
130
+
131
+ # Compute per-unit {Timerizer::Duration} values, split based on unit
132
+ # count
133
+ #
134
+ # @param [Integer] places Number of time units to include in main Array.
135
+ def call(places)
136
+ # Note that `places` may exceed the number of actual units in the
137
+ # value. For example, with a duration of `(10.days)` and a `places`
138
+ # value of 2. Adjust as needed.
139
+ places = @part_values.count - 1 if @part_values.count < places
140
+ # If a zero-time `duration` is passed in, then @part_values will be
141
+ # empty, and the key arithmetic will return `nil`. Adjust as needed.
142
+ @target_unit = @part_values.keys[places - 1] || :seconds
143
+ term_times = unit_times
144
+ @times = term_times[0..places - 1]
145
+ @remainder_times = term_times[@times.count..-1]
146
+ self
147
+ end
148
+
149
+ private
150
+
151
+ def filter_units(duration, omitted_keys)
152
+ unit_keys = Timerizer::Duration::UNITS.keys - omitted_keys
153
+ duration.to_units(*unit_keys).reject { |_, v| v.zero? }
154
+ end
155
+
156
+ def unit_times
157
+ @part_values.map { |unit, val| Timerizer::Duration.new(unit => val) }
158
+ end
159
+ end # class RoundedTime::TermTimes
160
+ private_constant :TermTimes
161
+ end # class RoundedTime
162
+ end
163
+ end
@@ -1,3 +1,3 @@
1
1
  module Timerizer
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timerizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyle Lacy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-27 00:00:00.000000000 Z
11
+ date: 2018-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -76,6 +76,7 @@ files:
76
76
  - lib/timerizer.rb
77
77
  - lib/timerizer/core.rb
78
78
  - lib/timerizer/duration.rb
79
+ - lib/timerizer/duration/rounded_time.rb
79
80
  - lib/timerizer/version.rb
80
81
  - lib/timerizer/wall_clock.rb
81
82
  homepage: http://github.com/kylewlacy/timerizer