unit_measurements 4.12.0 → 5.0.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: 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