unit_measurements 4.12.0 → 5.0.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: 50b4c09e16a4111f9776ae68ed43e33eccb5b2d47e6146bd32711bdaa8a72cf7
4
- data.tar.gz: 1a5c0339f687684b6bb34f2bf53d9da7fd1ed8eba23bcc0c23fbc4634057dfb6
3
+ metadata.gz: 2a7a4305ab13c8d9d8d52eaf7c9e4646757dc8eee71af5ec8314f6a2b702f929
4
+ data.tar.gz: 9cb9fc75b29f7745278ca27ce32fce621a29427e6e08202590eec52ff90c4e66
5
5
  SHA512:
6
- metadata.gz: ee23a940d4596e69a28f5361d037b88df37bf0d31c4b4f86a5cd11a33f201eb2f0dcf54a1579d75e54f1d5989c27751a745d755073f0d6fe5be459846daa17d1
7
- data.tar.gz: aa2cd86031ecd07894fd8c0258367ae2e5bd24e4155a1137dc201a3a4bb450aa9823afc936a24db71f15b17d8bf03ba8e5a1d5516ed9ffc155059907e46e347d
6
+ metadata.gz: 46ddf50754159eb8dcaf4f753378fe19f912ac0d8316ecdd959b23620ed7ca2ef1a1122ce0a35d0a33bd0d643fbe7e6572a83348ca2faf3ab6815ce64c61e9d4
7
+ data.tar.gz: 9b84900e75d14377ebe58e8a21d75aaca6ae1329ce2be56768a7f24f4476782e27d8312fa65045c7398d6c67eb78ff2b01ea5b6da2263e53899eb21f015cb246
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## [5.0.0](https://github.com/shivam091/unit_measurements/compare/v4.12.0...v5.0.0) - 2023-10-18
2
+
3
+ ### What's new
4
+
5
+ - Added support to add binary SI prefixes for the unit.
6
+ - Added support to convert the measurement to a `primitive` unit of the unit group.
7
+ - Added methods `UnitGroup#units_for` and `UnitGroup#units_for!` to find units within
8
+ the specified unit system.
9
+
10
+ ----------
11
+
1
12
  ## [4.12.0](https://github.com/shivam091/unit_measurements/compare/v4.11.0...v4.12.0) - 2023-10-16
2
13
 
3
14
  ### What's new
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- unit_measurements (4.12.0)
4
+ unit_measurements (5.0.0)
5
5
  activesupport (~> 7.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -88,6 +88,13 @@ UnitMeasurements::Length.new(1, "km").convert_to!("m")
88
88
  #=> 1000.0 m
89
89
  ```
90
90
 
91
+ You can convert the measurement directly to the `primitive` unit of the unit group as:
92
+
93
+ ```ruby
94
+ UnitMeasurements::Length.new(1, "cm").convert_to("primitive")
95
+ #=> 0.01 m
96
+ ```
97
+
91
98
  You can also chain call of `#convert_to` and `#convert_to!` methods as:
92
99
 
93
100
  ```ruby
@@ -215,11 +222,22 @@ UnitMeasurements::Length.unit_names_with_aliases
215
222
  #=> ["\"", "'", "feet", "foot", "ft", "in", "inch", "inches", "m", "meter", "meters", "metre", "metres", "mi", "mile", "miles", "yard", "yards", "yd"]
216
223
  ```
217
224
 
225
+ **See list of units within the unit system:**
226
+
227
+ You can use `#units_for` or `#units_for!` methods to find units within the unit system.
228
+ `#units_for!` method returns an error if there are no units associated with specified
229
+ unit system.
230
+
231
+ ```ruby
232
+ UnitMeasurements::Length.units_for("metric")
233
+ #=> [#<UnitMeasurements::Unit: m (meter, meters, metre, metres)>, ...]
234
+ ```
235
+
218
236
  **Finding units within the unit group:**
219
237
 
220
- You can use `#unit_for` or `#unit_for!` (aliased as `#[]`) to find units within
221
- the unit group. `#unit_for!` method returns error if a unit is not present in the
222
- unit group.
238
+ You can use `#unit_for` or `#unit_for!` (aliased as `#[]`) methods to find units
239
+ within the unit group. `#unit_for!` method returns an error if a unit is not present
240
+ in the unit group.
223
241
 
224
242
  ```ruby
225
243
  UnitMeasurements::Length.unit_for("m")
@@ -309,10 +327,14 @@ You can check more about them along with their examples
309
327
 
310
328
  The **`UnitMeasurements::Unit`** class is used to represent the units for a measurement.
311
329
 
312
- ### Support for SI decimal prefixes
330
+ ### SI prefixed units
331
+
332
+ There is support for SI prefixed units through the use of `si_unit` method.
333
+ Units declared through it will have automatic support for all decimal SI prefixes.
334
+ This method takes `add_binary_prefixes` parameter which can be set to true, if the
335
+ unit supports binary SI prefixes along with decimal SI prefixes.
313
336
 
314
- There is support for SI decimal prefixes through the use of `si_unit` method.
315
- Units declared through it will have automatic support for all decimal prefixes:
337
+ #### Decimal SI prefixes
316
338
 
317
339
  | Multiplying Factor | SI Prefix | Scientific Notation |
318
340
  | ----------------------------------------- | ---------- | ------------------- |
@@ -341,6 +363,19 @@ Units declared through it will have automatic support for all decimal prefixes:
341
363
  | 0.000 000 000 000 000 000 000 000 001 | ronto (r) | 10^-27 |
342
364
  | 0.000 000 000 000 000 000 000 000 000 001 | quecto (q) | 10^-30 |
343
365
 
366
+ #### Binary SI prefixes
367
+
368
+ | Multiplying Factor | SI Prefix | Scientific Notation |
369
+ | --------------------------------- | --------- | ------------------- |
370
+ | 1 024 | kibi (Ki) | 2^10 |
371
+ | 1 048 576 | mebi (Mi) | 2^20 |
372
+ | 1 073 741 824 | gibi (Gi) | 2^30 |
373
+ | 1 099 511 627 776 | tebi (Ti) | 2^40 |
374
+ | 1 125 899 906 842 624 | pebi (Pi) | 2^50 |
375
+ | 1 152 921 504 606 846 976 | exbi (Ei) | 2^60 |
376
+ | 1 180 591 620 717 411 303 424 | zebi (Zi) | 2^70 |
377
+ | 1 208 925 819 614 629 174 706 176 | yobi (Yi) | 2^80 |
378
+
344
379
  ### Bundled units
345
380
 
346
381
  There are tons of units that are bundled in `unit_measurements`. You can check them out
@@ -396,9 +431,12 @@ UnitMeasurements::Time = UnitMeasurements.build do
396
431
 
397
432
  # Group units by the unit system (optional).
398
433
  system :metric do
399
- # Add a SI unit to the unit group.
434
+ # This will add unit `m` along with all decimal SI prefixes.
400
435
  si_unit "s", aliases: ["second", "seconds"]
401
436
 
437
+ # This will add unit `B` along with all binary & decimal SI prefixes.
438
+ si_unit "B", aliases: ["byte", "bytes"], add_binary_prefixes: true
439
+
402
440
  # Add units to the group, along with their conversion multipliers.
403
441
  unit "min", value: "60 s", aliases: ["hour", "hours"]
404
442
 
@@ -101,7 +101,12 @@ module UnitMeasurements
101
101
  # UnitMeasurements::Length.new(1, "m").convert_to("cm")
102
102
  # => 100.0 cm
103
103
  #
104
- # @param [String|Symbol] target_unit The target unit for conversion.
104
+ # UnitMeasurements::Length.new(1, "cm").convert_to("primitive")
105
+ # => 0.01 m
106
+ #
107
+ # @param [String|Symbol] target_unit
108
+ # The target unit for conversion. Specifing +primitive+ will convert the
109
+ # measurement to a primitive unit of the unit group.
105
110
  #
106
111
  # @return [Measurement]
107
112
  # A new +Measurement+ instance with the converted +quantity+ and
@@ -110,7 +115,11 @@ module UnitMeasurements
110
115
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
111
116
  # @since 1.0.0
112
117
  def convert_to(target_unit)
113
- target_unit = unit_from_unit_or_name!(target_unit)
118
+ target_unit = if target_unit.to_s.eql?("primitive")
119
+ self.class.unit_group.primitive
120
+ else
121
+ unit_from_unit_or_name!(target_unit)
122
+ end
114
123
 
115
124
  return self if target_unit == unit
116
125
 
@@ -188,7 +197,7 @@ module UnitMeasurements
188
197
  # Methods delegated from the unit group.
189
198
  def_delegators :unit_group, :primitive, :units, :unit_names, :unit_with_name_and_aliases,
190
199
  :unit_names_with_aliases, :unit_for, :unit_for!, :defined?,
191
- :unit_or_alias?, :[]
200
+ :unit_or_alias?, :[], :units_for, :units_for!
192
201
 
193
202
  # Parses an input string and returns a +Measurement+ instance depending on
194
203
  # the input string. This method first normalizes the +input+ internally,
@@ -57,7 +57,7 @@ module UnitMeasurements
57
57
  @name = name.to_s.freeze
58
58
  @value = value
59
59
  @aliases = Set.new(aliases.map(&:to_s).sort.map(&:freeze)).freeze
60
- @system = system
60
+ @system = system.to_s
61
61
  @unit_group = unit_group
62
62
  end
63
63
 
@@ -147,35 +147,50 @@ module UnitMeasurements
147
147
 
148
148
  private
149
149
 
150
+ # Binary prefixes for SI units.
151
+ #
152
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
153
+ # @since 5.0.0
154
+ SI_BINARY_PREFIXES = [
155
+ ["Ki", %w[kibi], 2.pow(10)],
156
+ ["Mi", %w[mebi], 2.pow(20)],
157
+ ["Gi", %w[gibi], 2.pow(30)],
158
+ ["Ti", %w[tebi], 2.pow(40)],
159
+ ["Pi", %w[pebi], 2.pow(50)],
160
+ ["Ei", %w[exbi], 2.pow(60)],
161
+ ["Zi", %w[zebi], 2.pow(70)],
162
+ ["Yi", %w[yobi], 2.pow(80)],
163
+ ].map(&:freeze).freeze
164
+
150
165
  # Decimal prefixes for SI units.
151
166
  #
152
167
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
153
168
  # @since 1.0.0
154
169
  SI_DECIMAL_PREFIXES = [
155
- ["q", %w(quecto), 1e-30],
156
- ["r", %w(ronto), 1e-27],
157
- ["y", %w(yocto), 1e-24],
158
- ["z", %w(zepto), 1e-21],
159
- ["a", %w(atto), 1e-18],
160
- ["f", %w(femto), 1e-15],
161
- ["p", %w(pico), 1e-12],
162
- ["n", %w(nano), 1e-9],
163
- ["μ", %w(micro), 1e-6],
164
- ["m", %w(milli), 1e-3],
165
- ["c", %w(centi), 1e-2],
166
- ["d", %w(deci), 1e-1],
167
- ["da", %w(deca deka), 1e+1],
168
- ["h", %w(hecto), 1e+2],
169
- ["k", %w(kilo), 1e+3],
170
- ["M", %w(mega), 1e+6],
171
- ["G", %w(giga), 1e+9],
172
- ["T", %w(tera), 1e+12],
173
- ["P", %w(peta), 1e+15],
174
- ["E", %w(exa), 1e+18],
175
- ["Z", %w(zetta), 1e+21],
176
- ["Y", %w(yotta), 1e+24],
177
- ["R", %w(ronna), 1e+27],
178
- ["Q", %w(quetta), 1e+30]
170
+ ["q", %w[quecto], 1e-30],
171
+ ["r", %w[ronto], 1e-27],
172
+ ["y", %w[yocto], 1e-24],
173
+ ["z", %w[zepto], 1e-21],
174
+ ["a", %w[atto], 1e-18],
175
+ ["f", %w[femto], 1e-15],
176
+ ["p", %w[pico], 1e-12],
177
+ ["n", %w[nano], 1e-9],
178
+ ["μ", %w[micro], 1e-6],
179
+ ["m", %w[milli], 1e-3],
180
+ ["c", %w[centi], 1e-2],
181
+ ["d", %w[deci], 1e-1],
182
+ ["da", %w[deca deka], 1e+1],
183
+ ["h", %w[hecto], 1e+2],
184
+ ["k", %w[kilo], 1e+3],
185
+ ["M", %w[mega], 1e+6],
186
+ ["G", %w[giga], 1e+9],
187
+ ["T", %w[tera], 1e+12],
188
+ ["P", %w[peta], 1e+15],
189
+ ["E", %w[exa], 1e+18],
190
+ ["Z", %w[zetta], 1e+21],
191
+ ["Y", %w[yotta], 1e+24],
192
+ ["R", %w[ronna], 1e+27],
193
+ ["Q", %w[quetta], 1e+30]
179
194
  ].map(&:freeze).freeze
180
195
 
181
196
  # Parses tokens and returns a +conversion value+ and the +unit+.
@@ -167,6 +167,69 @@ module UnitMeasurements
167
167
  !!unit_for(name)
168
168
  end
169
169
 
170
+ # Returns an array of units associated with a specified +unit_system+.
171
+ #
172
+ # This method takes a unit system name as an argument and filters the units
173
+ # in the unit group to return only those units that belong to the specified
174
+ # unit system. It then returns an array containing these filtered units.
175
+ #
176
+ # @example
177
+ # UnitMeasurements::Length.units_for("metric")
178
+ # => [#<UnitMeasurements::Unit: m (meter, meters, metre, metres)>]
179
+ #
180
+ # UnitMeasurements::Length.units_for("imperial")
181
+ # => [#<UnitMeasurements::Unit: in (", inch, inches)>, ...]
182
+ #
183
+ # UnitMeasurements::Length.units_for("troy")
184
+ # => []
185
+ #
186
+ # @param [String|Symbol] system_name
187
+ # The name of the unit system to retrieve units for.
188
+ #
189
+ # @return [Array<Unit>]
190
+ # An array of +Unit+ instances associated with the specified unit system.
191
+ #
192
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
193
+ # @since 5.0.0
194
+ def units_for(system_name)
195
+ units.select { |unit| unit.system.to_s == system_name.to_s }
196
+ end
197
+
198
+ # This method works same as +units_for+ method but it raises an error if
199
+ # there are no units associated with the +system_name+.
200
+ #
201
+ # @example
202
+ # UnitMeasurements::Length.units_for!("metric")
203
+ # => [#<UnitMeasurements::Unit: m (meter, meters, metre, metres)>]
204
+ #
205
+ # UnitMeasurements::Length.units_for!("imperial")
206
+ # => [#<UnitMeasurements::Unit: in (", inch, inches)>, ...]
207
+ #
208
+ # UnitMeasurements::Length.units_for!("troy")
209
+ # => Invalid unit system 'troy' within the unit group. (UnitMeasurements::BaseError)
210
+ #
211
+ # @param [String|Symbol] system_name
212
+ # The name of the unit system to retrieve units for.
213
+ #
214
+ # @return [Array<Unit>]
215
+ # An array of +Unit+ instances associated with the specified unit system.
216
+ #
217
+ # @raise [BaseError]
218
+ # If there are no units associated with the provided +system_name+.
219
+ #
220
+ # @see units_for
221
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
222
+ # @since 5.0.0
223
+ def units_for!(system_name)
224
+ system_units = units_for(system_name)
225
+
226
+ unless system_units.any?
227
+ raise BaseError, "Invalid unit system '#{system_name}' within the unit group."
228
+ end
229
+
230
+ system_units
231
+ end
232
+
170
233
  private
171
234
 
172
235
  # @private
@@ -56,6 +56,9 @@ module UnitMeasurements
56
56
  #
57
57
  # @param [String|Symbol] name The name of the unit.
58
58
  # @param [Numeric|String] value The conversion value of the unit.
59
+ # @param [TrueClass|FalseClass] add_binary_prefixes
60
+ # Whether the unit supports binary SI prefixes along with decimal SI
61
+ # prefixes.
59
62
  # @param [Array<String|Symbol>, optional] aliases An array of alternative names for the unit.
60
63
  #
61
64
  # @return [Array<Unit>] An array of +Unit+ instances.
@@ -63,8 +66,8 @@ module UnitMeasurements
63
66
  # @see #build_si_units
64
67
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
65
68
  # @since 1.0.0
66
- def si_unit(name, value: 1.0, aliases: [])
67
- @units += build_si_units(name, value: value, aliases: aliases)
69
+ def si_unit(name, value: 1.0, add_binary_prefixes: false, aliases: [])
70
+ @units += build_si_units(name, value: value, add_binary_prefixes: add_binary_prefixes, aliases: aliases)
68
71
  end
69
72
 
70
73
  # Constructs and returns a +UnitGroup+ object based on the units defined
@@ -133,6 +136,9 @@ module UnitMeasurements
133
136
  #
134
137
  # @param [String|Symbol] name The name of the unit.
135
138
  # @param [Numeric|String] value The conversion value of the unit.
139
+ # @param [TrueClass|FalseClass] add_binary_prefixes
140
+ # Whether the unit supports binary SI prefixes along with decimal SI
141
+ # prefixes.
136
142
  # @param [Array<String|Symbol>, optional] aliases
137
143
  # An array of alternative names for the unit.
138
144
  #
@@ -141,10 +147,12 @@ module UnitMeasurements
141
147
  # @see #build_unit
142
148
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
143
149
  # @since 1.0.0
144
- def build_si_units(name, value:, aliases:)
150
+ def build_si_units(name, value:, add_binary_prefixes:, aliases:)
145
151
  si_units = [build_unit(name, value: value, aliases: aliases)]
146
152
 
147
- Unit::SI_DECIMAL_PREFIXES.each do |short_prefix, long_prefix, multiplier|
153
+ si_prefixes = add_binary_prefixes ? (Unit::SI_DECIMAL_PREFIXES + Unit::SI_BINARY_PREFIXES) : Unit::SI_DECIMAL_PREFIXES
154
+
155
+ si_prefixes.each do |short_prefix, long_prefix, multiplier|
148
156
  si_aliases = long_prefix.product(aliases.to_a).flat_map do |prefix, unit|
149
157
  aliases.map { |alias_unit| prefix + alias_unit.to_s }
150
158
  end
@@ -5,8 +5,8 @@
5
5
  UnitMeasurements::InformationEntropy = UnitMeasurements.build do
6
6
  primitive "nat"
7
7
 
8
- si_unit "b", value: "1 Sh", aliases: ["bit", "bits"]
9
- si_unit "B", value: [2.pow(3), "b"], aliases: ["byte", "bytes"]
8
+ si_unit "b", value: "1 Sh", aliases: ["bit", "bits"], add_binary_prefixes: true
9
+ si_unit "B", value: [2.pow(3), "b"], aliases: ["byte", "bytes"], add_binary_prefixes: true
10
10
 
11
11
  unit "Sh", value: [Math.log(2), "nat"], aliases: ["shannon", "shannons"]
12
12
  unit "nat", aliases: ["nit", "nepit", "natural unit of information"]
@@ -4,5 +4,5 @@
4
4
 
5
5
  module UnitMeasurements
6
6
  # Current stable version.
7
- VERSION = "4.12.0"
7
+ VERSION = "5.0.0"
8
8
  end
data/units.md CHANGED
@@ -4,8 +4,10 @@ As there are lots of units bundled with `unit_measurements`, we recommend you to
4
4
  bundled units before converting your measurements.
5
5
 
6
6
  **Notes:**
7
- 1. Unit names suffixed with `*` support all [SI prefixes](README.md#support-for-si-decimal-prefixes).
8
- 2. Primitive unit of the unit group is in _emphasised typeface_.
7
+ 1. Unit names suffixed with `*` support all [Decimal SI prefixes](README.md#decimal-si-prefixes).
8
+ 2. Unit names suffixed with `**` support all [Decimal SI prefixes](README.md#decimal-si-prefixes)
9
+ and [Binary SI prefixes](README.md#binary-si-prefixes).
10
+ 3. Primitive unit of the unit group is in _emphasised typeface_.
9
11
 
10
12
  ## 1. Length/Distance
11
13
 
@@ -594,8 +596,8 @@ These units are defined in `UnitMeasurements::InformationEntropy`.
594
596
 
595
597
  | # | Name | Aliases |
596
598
  |:--|:--|:--|
597
- | 1 | b* | bit, bits |
598
- | 2 | B* | byte, bytes |
599
+ | 1 | b*\* | bit, bits |
600
+ | 2 | B*\* | byte, bytes |
599
601
  | 3 | Sh | shannon, shannons |
600
602
  | _4_ | _nat_ | _nit, nepit, natural unit of information_ |
601
603
  | 5 | nybl | nibble, nibbles, nybble, nyble |
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unit_measurements
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.12.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harshal LADHE
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-16 00:00:00.000000000 Z
11
+ date: 2023-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport