unit_measurements 4.12.0 → 5.1.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: a8e055ec9a81c6c27050136128e36d6bceba2b3292e6494a2bbd3305ccbcb20b
4
+ data.tar.gz: 381e87126aaa72bd762f537fe6be8638adbf07105ed992009a8298f6d6159de4
5
5
  SHA512:
6
- metadata.gz: ee23a940d4596e69a28f5361d037b88df37bf0d31c4b4f86a5cd11a33f201eb2f0dcf54a1579d75e54f1d5989c27751a745d755073f0d6fe5be459846daa17d1
7
- data.tar.gz: aa2cd86031ecd07894fd8c0258367ae2e5bd24e4155a1137dc201a3a4bb450aa9823afc936a24db71f15b17d8bf03ba8e5a1d5516ed9ffc155059907e46e347d
6
+ metadata.gz: b8b3831f2e780623cd1d7d8e86d7f4687c58ed380dabccfa2eff81ab1c9cb13c8295970c1980acbf920ee00bffcba6fd3d310563fc3d27ecbc6946e14fadddea
7
+ data.tar.gz: d45c0207c736ca65b6041483d609a6390784fd60334c49220d36580f5fb3e3882c1f5a49d5951e6bc3f46386769cd18168bb8fcb6e897fb9b742fa3445acd8b7
data/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ## [5.1.0](https://github.com/shivam091/unit_measurements/compare/v5.0.0...v5.1.0) - 2023-10-19
2
+
3
+ ### What's new
4
+
5
+ - Added new methods (`**`, `-@`, `nonzero?`, `zero?`, `positive?`, `negative?`,
6
+ `finite?`, and `infinite?`) to perform arithmetic operations.
7
+ - Added new alias `scale` for `**` arithmetic method.
8
+
9
+ ### What's updated
10
+
11
+ - Updated readme and documentation.
12
+ - Updated documentation hosting link to `https://rubydoc.info/gems/unit_measurements`.
13
+
14
+ ----------
15
+
16
+ ## [5.0.0](https://github.com/shivam091/unit_measurements/compare/v4.12.0...v5.0.0) - 2023-10-18
17
+
18
+ ### What's new
19
+
20
+ - Added support to add binary SI prefixes for the unit.
21
+ - Added support to convert the measurement to a `primitive` unit of the unit group.
22
+ - Added methods `UnitGroup#units_for` and `UnitGroup#units_for!` to find units within
23
+ the specified unit system.
24
+
25
+ ----------
26
+
1
27
  ## [4.12.0](https://github.com/shivam091/unit_measurements/compare/v4.11.0...v4.12.0) - 2023-10-16
2
28
 
3
29
  ### 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.1.0)
5
5
  activesupport (~> 7.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -22,19 +22,19 @@ to numerous errors.
22
22
 
23
23
  The `unit_measurements` gem is designed to simplify the handling of units for scientific calculations.
24
24
 
25
- ## Advantages
25
+ ## Features
26
26
 
27
- 1. It provides easy conversion between units.
28
- 2. It is lightweight and easily extensible to include other units and conversions.
29
- 3. It has built in support for various [unit groups](https://github.com/shivam091/unit_measurements/blob/main/units.md).
30
- 4. It has well organized and very descriptive documentation published [here](https://shivam091.github.io/unit_measurements).
31
- 5. It can convert `complex`, `fractional`, `mixed fractional`, `scientific` numbers, and `ratios`.
27
+ - Easy unit conversion.
28
+ - Lightweight and extensible for adding custom units and conversions.
29
+ - Supports various [unit groups](https://github.com/shivam091/unit_measurements/blob/main/units.md).
30
+ - Well-documented: [Documentation](https://rubydoc.info/gems/unit_measurements).
31
+ - Parses complex, fractional, mixed fractional, scientific numbers, and ratios.
32
32
 
33
33
  ## Disclaimer
34
34
 
35
- _The unit conversions presented in `unit_measurements` are provided for reference and general informational purposes.
36
- While we aim to offer accurate conversions, we cannot guarantee their precision in all scenarios.
37
- Users are advised to cross-verify conversions as needed for their specific use cases._
35
+ _The unit conversions provided here are for reference and general informational
36
+ purposes. While we aim for accuracy, we cannot guarantee precision in all scenarios.
37
+ Users are advised to cross-verify conversions for their specific use cases._
38
38
 
39
39
  ## Minimum Requirements
40
40
 
@@ -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
@@ -120,7 +127,7 @@ UnitMeasurements::Length.parse("2e+2 km to m")
120
127
  #=> 200000.0 m
121
128
  ```
122
129
  You can check supported special characters for exponents
123
- [here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Normalizer.html).
130
+ [here](https://rubydoc.info/gems/unit_measurements/UnitMeasurements/Normalizer.html).
124
131
 
125
132
  **Parse complex numbers, source unit, and (or) target unit:**
126
133
 
@@ -136,24 +143,16 @@ UnitMeasurements::Length.parse("2+3i km to m")
136
143
  ```ruby
137
144
  UnitMeasurements::Length.parse("2 ½ km").convert_to("m")
138
145
  #=> 2500.0 m
139
- UnitMeasurements::Length.parse("2/3 km").convert_to("m")
140
- #=> 666.666666666667 m
141
146
  UnitMeasurements::Length.parse("2/3 km to m")
142
147
  #=> 666.666666666667 m
143
- UnitMeasurements::Length.parse("2 1/2 km").convert_to("m")
144
- #=> 2500.0 m
145
- UnitMeasurements::Length.parse("2 ½ km to m")
146
- #=> 2500.0 m
147
148
  ```
148
149
 
149
150
  You can check supported special characters for fractional notations
150
- [here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Normalizer.html).
151
+ [here](https://rubydoc.info/gems/unit_measurements/UnitMeasurements/Normalizer.html).
151
152
 
152
153
  **Parse ratios, source unit, and (or) target unit:**
153
154
 
154
155
  ```ruby
155
- UnitMeasurements::Length.new("1:2", "km").convert_to("m")
156
- #=> 500.0 m
157
156
  UnitMeasurements::Length.parse("1:2 km").convert_to("m")
158
157
  #=> 500.0 m
159
158
  UnitMeasurements::Length.parse("1:2 km to m")
@@ -166,16 +165,12 @@ If you want to format measurement to certain format, you can use `#format` metho
166
165
  If format is not specified, it defaults to `"%.2<value>f %<unit>s"`.
167
166
 
168
167
  ```ruby
169
- UnitMeasurements::Length.new(100, "m").to("in").format
170
- #=> "3937.01 in"
171
168
  UnitMeasurements::Length.new(100, "m").to("in").format("%.4<quantity>f %<unit>s")
172
169
  #=> "3937.0079 in"
173
- UnitMeasurements::Length.new(100, "m").to("in").format("%.4<quantity>f")
174
- #=> "3937.0079"
175
170
  ```
176
171
 
177
172
  You can check more about formatting along with their examples
178
- [here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Formatter.html).
173
+ [here](https://rubydoc.info/gems/unit_measurements/UnitMeasurements/Formatter.html).
179
174
 
180
175
  **Extract the unit and the quantity from measurement:**
181
176
 
@@ -215,19 +210,28 @@ UnitMeasurements::Length.unit_names_with_aliases
215
210
  #=> ["\"", "'", "feet", "foot", "ft", "in", "inch", "inches", "m", "meter", "meters", "metre", "metres", "mi", "mile", "miles", "yard", "yards", "yd"]
216
211
  ```
217
212
 
213
+ **See list of units within the unit system:**
214
+
215
+ You can use `#units_for` or `#units_for!` methods to find units within the unit system.
216
+ `#units_for!` method returns an error if there are no units associated with specified
217
+ unit system.
218
+
219
+ ```ruby
220
+ UnitMeasurements::Length.units_for("metric")
221
+ #=> [#<UnitMeasurements::Unit: m (meter, meters, metre, metres)>, ...]
222
+ ```
223
+
218
224
  **Finding units within the unit group:**
219
225
 
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.
226
+ You can use `#unit_for` or `#unit_for!` (aliased as `#[]`) methods to find units
227
+ within the unit group. `#unit_for!` method returns an error if a unit is not present
228
+ in the unit group.
223
229
 
224
230
  ```ruby
225
231
  UnitMeasurements::Length.unit_for("m")
226
232
  #=> #<UnitMeasurements::Unit: m (meter, meters, metre, metres)>
227
233
  UnitMeasurements::Length.unit_for("z")
228
234
  #=> nil
229
- UnitMeasurements::Length.unit_for!("m")
230
- #=> #<UnitMeasurements::Unit: m (meter, meters, metre, metres)>
231
235
  UnitMeasurements::Length.unit_for!("z")
232
236
  #=> Invalid unit: 'z'. (UnitMeasurements::UnitError)
233
237
  ```
@@ -261,7 +265,7 @@ UnitMeasurements::Length.parse("1 km") != UnitMeasurements::Length.parse("1 m")
261
265
  ```
262
266
 
263
267
  You can check supported comparisons along with their examples
264
- [here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Comparison.html).
268
+ [here](https://rubydoc.info/gems/unit_measurements/UnitMeasurements/Comparison.html).
265
269
 
266
270
  ### Arithmetic
267
271
 
@@ -278,7 +282,7 @@ UnitMeasurements::Length.new(2, "km") * 2+2i
278
282
  ```
279
283
 
280
284
  You can check supported arithmetic operations along with their examples
281
- [here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Arithmetic.html).
285
+ [here](https://rubydoc.info/gems/unit_measurements/UnitMeasurements/Arithmetic.html).
282
286
 
283
287
  ### Math
284
288
 
@@ -290,7 +294,7 @@ UnitMeasurements::Length.new(17.625, "m").round
290
294
  ```
291
295
 
292
296
  You can check supported mathematical functions along with their examples
293
- [here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Math.html).
297
+ [here](https://rubydoc.info/gems/unit_measurements/UnitMeasurements/Math.html).
294
298
 
295
299
  ### Conversions
296
300
 
@@ -303,16 +307,20 @@ UnitMeasurements::Length.new(2.25567, "km").to_i
303
307
  ```
304
308
 
305
309
  You can check more about them along with their examples
306
- [here](https://shivam091.github.io/unit_measurements/UnitMeasurements/Conversion.html).
310
+ [here](https://rubydoc.info/gems/unit_measurements/UnitMeasurements/Conversion.html).
307
311
 
308
312
  ## Units
309
313
 
310
314
  The **`UnitMeasurements::Unit`** class is used to represent the units for a measurement.
311
315
 
312
- ### Support for SI decimal prefixes
316
+ ### SI prefixed units
313
317
 
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:
318
+ Support for SI prefixed units is provided through the `si_unit` method. Units
319
+ declared this way automatically support all decimal SI prefixes. This method takes
320
+ an optional `add_binary_prefixes` parameter, which can be set to `true` if the
321
+ unit supports binary SI prefixes in addition to decimal SI prefixes.
322
+
323
+ #### Decimal SI prefixes
316
324
 
317
325
  | Multiplying Factor | SI Prefix | Scientific Notation |
318
326
  | ----------------------------------------- | ---------- | ------------------- |
@@ -341,6 +349,19 @@ Units declared through it will have automatic support for all decimal prefixes:
341
349
  | 0.000 000 000 000 000 000 000 000 001 | ronto (r) | 10^-27 |
342
350
  | 0.000 000 000 000 000 000 000 000 000 001 | quecto (q) | 10^-30 |
343
351
 
352
+ #### Binary SI prefixes
353
+
354
+ | Multiplying Factor | SI Prefix | Scientific Notation |
355
+ | --------------------------------- | --------- | ------------------- |
356
+ | 1 024 | kibi (Ki) | 2^10 |
357
+ | 1 048 576 | mebi (Mi) | 2^20 |
358
+ | 1 073 741 824 | gibi (Gi) | 2^30 |
359
+ | 1 099 511 627 776 | tebi (Ti) | 2^40 |
360
+ | 1 125 899 906 842 624 | pebi (Pi) | 2^50 |
361
+ | 1 152 921 504 606 846 976 | exbi (Ei) | 2^60 |
362
+ | 1 180 591 620 717 411 303 424 | zebi (Zi) | 2^70 |
363
+ | 1 208 925 819 614 629 174 706 176 | yobi (Yi) | 2^80 |
364
+
344
365
  ### Bundled units
345
366
 
346
367
  There are tons of units that are bundled in `unit_measurements`. You can check them out
@@ -348,8 +369,7 @@ There are tons of units that are bundled in `unit_measurements`. You can check t
348
369
 
349
370
  ### Specifing units
350
371
 
351
- By default, `unit_measurements` ships with all the unit groups and this happens automatically
352
- when requiring the gem in the following manner.
372
+ By default, `unit_measurements` includes all unit groups automatically when you require the gem using:
353
373
 
354
374
  ```ruby
355
375
  require "unit_measurements"
@@ -357,37 +377,22 @@ require "unit_measurements"
357
377
 
358
378
  **You can skip these unit groups and only [build your own unit groups](#building-new-unit-groups) by doing:**
359
379
 
360
- ```ruby
361
- require "unit_measurements/base"
362
- ```
363
-
364
- or simply
365
-
366
380
  ```ruby
367
381
  gem "unit_measurements", require: "unit_measurements/base"
368
382
  ```
369
383
 
370
384
  **You can also use unit groups in your application as per your need as:**
371
385
 
372
- ```ruby
373
- require "unit_measurements/base"
374
-
375
- require "unit_measurements/unit_groups/length"
376
- ```
377
-
378
- or
379
-
380
386
  ```ruby
381
387
  gem "unit_measurements", require: ["unit_measurements/base", "unit_measurements/unit_groups/length"]
382
388
  ```
383
389
 
384
390
  ### Building new unit groups
385
391
 
386
- This library provides simpler way to build your own unit groups. To build new unit group,
387
- use `UnitMeasurements.build` method in order to define units within it:
388
-
389
- For convenience, you also have ability to group units by the unit system using `system` method
390
- and set primitive unit for each unit group using `primitive` method.
392
+ This library provides a simpler way to define your own unit groups. Use the
393
+ `UnitMeasurements.build` method to define units within it. You can also group
394
+ units by the unit system using the `system` method and set the primitive unit for
395
+ each unit group using the `primitive` method.
391
396
 
392
397
  ```ruby
393
398
  UnitMeasurements::Time = UnitMeasurements.build do
@@ -396,14 +401,17 @@ UnitMeasurements::Time = UnitMeasurements.build do
396
401
 
397
402
  # Group units by the unit system (optional).
398
403
  system :metric do
399
- # Add a SI unit to the unit group.
404
+ # This will add unit `m` along with all decimal SI prefixes.
400
405
  si_unit "s", aliases: ["second", "seconds"]
401
406
 
407
+ # This will add unit `B` along with all binary & decimal SI prefixes.
408
+ si_unit "B", aliases: ["byte", "bytes"], add_binary_prefixes: true
409
+
402
410
  # Add units to the group, along with their conversion multipliers.
403
411
  unit "min", value: "60 s", aliases: ["hour", "hours"]
404
412
 
405
413
  # You can also specify unit value as an array.
406
- unit :h, value: [60, "min"], aliases: ["day", "days"]
414
+ unit "h", value: [60, "min"], aliases: ["day", "days"]
407
415
  end
408
416
  end
409
417
  ```
@@ -16,6 +16,11 @@ module UnitMeasurements
16
16
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
17
17
  # @since 1.4.0
18
18
  module Arithmetic
19
+ extend Forwardable
20
+
21
+ # Methods delegated from the Numeric.
22
+ def_delegators :@quantity, :zero?, :positive?, :negative?, :finite?, :infinite?
23
+
19
24
  # Adds the quantity of the other measurement or a numeric value to the
20
25
  # quantity of the current measurement.
21
26
  #
@@ -78,6 +83,7 @@ module UnitMeasurements
78
83
  def *(other)
79
84
  arithmetic_operation(other, :*)
80
85
  end
86
+ alias_method :scale, :*
81
87
 
82
88
  # Divides the quantity of the current measurement by the quantity of the other
83
89
  # measurement or a numeric value.
@@ -100,6 +106,70 @@ module UnitMeasurements
100
106
  arithmetic_operation(other, :/)
101
107
  end
102
108
 
109
+ # Raises the quantity of the current measurement to the power of the quantity of
110
+ # the other measurement or numeric value.
111
+ #
112
+ # When +other+ is an instance of +Measurement+, the quantity to raise
113
+ # is calculated by converting the +other+ measurement to the unit of the +current+
114
+ # measurement, and then the quantity of the +current+ measurement is raised to
115
+ # the converted quantity.
116
+ #
117
+ # @param [Numeric|Measurement] other
118
+ # The value to be raised. It can be a numeric value or another measurement.
119
+ #
120
+ # @example
121
+ # UnitMeasurements::Length.new(2, "km") ** UnitMeasurements::Length.new(3, "m")
122
+ # => 1.00208160507963279 km
123
+ #
124
+ # UnitMeasurements::Length.new(2, "km") ** 3
125
+ # => 8 km
126
+ #
127
+ # UnitMeasurements::Length.new(8, "km") ** 1/3r
128
+ # => 2 km
129
+ #
130
+ # @return [Measurement] A new +Measurement+ instance with the raised quantity.
131
+ #
132
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
133
+ # @since 5.1.0
134
+ def **(other)
135
+ arithmetic_operation(other, :**)
136
+ end
137
+
138
+ # Negates the quantity of the measurement.
139
+ #
140
+ # @example
141
+ # -UnitMeasurements::Length.new(2, "km")
142
+ # => -2 km
143
+ #
144
+ # -UnitMeasurements::Length.new(-2, "km")
145
+ # => 2 km
146
+ #
147
+ # @return [Measurement] A new +Measurement+ instance with the negated quantity.
148
+ #
149
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
150
+ # @since 5.1.0
151
+ def -@
152
+ self.class.new(-self.quantity, self.unit)
153
+ end
154
+
155
+ # Checks whether the quantity of the measurement is nonzero.
156
+ #
157
+ # @example
158
+ # UnitMeasurements::Length.new(2, "km").nonzero?
159
+ # => true
160
+ #
161
+ # UnitMeasurements::Length.new(0, "km").nonzero?
162
+ # => false
163
+ #
164
+ # @return [TrueClass|FalseClass]
165
+ # +true+ if the quantity is nonzero otherwise it returns +false+.
166
+ #
167
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
168
+ # @since 5.1.0
169
+ def nonzero?
170
+ quantity.nonzero? ? true : false
171
+ end
172
+
103
173
  private
104
174
 
105
175
  # @private
@@ -16,6 +16,8 @@ module UnitMeasurements
16
16
  class ParseError < BaseError
17
17
  # The input string that caused the error while parsing.
18
18
  #
19
+ # @return [String] The input string that caused the error while parsing.
20
+ #
19
21
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
20
22
  # @since 1.0.0
21
23
  attr_reader :string
@@ -16,6 +16,8 @@ module UnitMeasurements
16
16
  class UnitAlreadyDefinedError < BaseError
17
17
  # The name of the unit that is already defined.
18
18
  #
19
+ # @return [String] The name of the unit that is already defined.
20
+ #
19
21
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
20
22
  # @since 1.0.0
21
23
  attr_reader :unit
@@ -15,6 +15,8 @@ module UnitMeasurements
15
15
  class UnitError < BaseError
16
16
  # The name of the invalid unit.
17
17
  #
18
+ # @return [String] The name of the invalid unit.
19
+ #
18
20
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
19
21
  # @since 1.0.0
20
22
  attr_reader :unit
@@ -33,12 +33,25 @@ module UnitMeasurements
33
33
  include Math
34
34
 
35
35
  # Regular expression to match conversion strings.
36
+ #
37
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
38
+ # @since 1.0.0
36
39
  CONVERSION_STRING_REGEXP = /(.+?)\s?(?:\s+(?:in|to|as)\s+(.+)|\z)/i.freeze
37
40
 
38
41
  # Quantity of the measurement.
42
+ #
43
+ # @return [Numeric] Quantity of the measurement.
44
+ #
45
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
46
+ # @since 1.0.0
39
47
  attr_reader :quantity
40
48
 
41
49
  # The unit associated with the measurement.
50
+ #
51
+ # @return [Unit] The +unit+ instance associated with the measurement.
52
+ #
53
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
54
+ # @since 1.0.0
42
55
  attr_reader :unit
43
56
 
44
57
  # Initializes a new instance of +Measurement+ with a specified +quantity+
@@ -55,6 +68,12 @@ module UnitMeasurements
55
68
  # UnitMeasurements::Length.new("2e+2", "km")
56
69
  # => 200.0 km
57
70
  #
71
+ # UnitMeasurements::Length.new("2e²", "km")
72
+ # => 200.0 km
73
+ #
74
+ # UnitMeasurements::Length.new("2e⁻²", "km")
75
+ # => 0.02 km
76
+ #
58
77
  # @example Initializing the measurement with complex number and unit:
59
78
  # UnitMeasurements::Length.new(Complex(2, 3), "km")
60
79
  # => 2+3i km
@@ -75,6 +94,9 @@ module UnitMeasurements
75
94
  # UnitMeasurements::Length.new("½", "km")
76
95
  # => 0.5 km
77
96
  #
97
+ # UnitMeasurements::Length.new("2 ½", "km")
98
+ # => 2.5 km
99
+ #
78
100
  # @example Initializing the measurement with ratio and unit:
79
101
  # UnitMeasurements::Length.new("1:2", "km")
80
102
  # => 0.5 km
@@ -95,13 +117,19 @@ module UnitMeasurements
95
117
  @unit = unit_from_unit_or_name!(unit)
96
118
  end
97
119
 
98
- # Converts the measurement to a +target_unit+.
120
+ # Converts the measurement to a +target_unit+ and returns new instance of the
121
+ # measurement.
99
122
  #
100
123
  # @example
101
124
  # UnitMeasurements::Length.new(1, "m").convert_to("cm")
102
125
  # => 100.0 cm
103
126
  #
104
- # @param [String|Symbol] target_unit The target unit for conversion.
127
+ # UnitMeasurements::Length.new(1, "cm").convert_to("primitive")
128
+ # => 0.01 m
129
+ #
130
+ # @param [String|Symbol] target_unit
131
+ # The target unit for conversion. Specifing +primitive+ will convert the
132
+ # measurement to a primitive unit of the unit group.
105
133
  #
106
134
  # @return [Measurement]
107
135
  # A new +Measurement+ instance with the converted +quantity+ and
@@ -110,7 +138,11 @@ module UnitMeasurements
110
138
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
111
139
  # @since 1.0.0
112
140
  def convert_to(target_unit)
113
- target_unit = unit_from_unit_or_name!(target_unit)
141
+ target_unit = if target_unit.to_s.eql?("primitive")
142
+ self.class.unit_group.primitive
143
+ else
144
+ unit_from_unit_or_name!(target_unit)
145
+ end
114
146
 
115
147
  return self if target_unit == unit
116
148
 
@@ -133,6 +165,7 @@ module UnitMeasurements
133
165
  # @return [Measurement]
134
166
  # The current +Measurement+ instance with updated +quantity+ and +unit+.
135
167
  #
168
+ # @see #convert_to
136
169
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
137
170
  # @since 1.0.0
138
171
  def convert_to!(target_unit)
@@ -188,7 +221,7 @@ module UnitMeasurements
188
221
  # Methods delegated from the unit group.
189
222
  def_delegators :unit_group, :primitive, :units, :unit_names, :unit_with_name_and_aliases,
190
223
  :unit_names_with_aliases, :unit_for, :unit_for!, :defined?,
191
- :unit_or_alias?, :[]
224
+ :unit_or_alias?, :[], :units_for, :units_for!
192
225
 
193
226
  # Parses an input string and returns a +Measurement+ instance depending on
194
227
  # the input string. This method first normalizes the +input+ internally,
@@ -266,7 +299,8 @@ module UnitMeasurements
266
299
  # @see Parser
267
300
  # @see Normalizer
268
301
  # @see CONVERSION_STRING_REGEXP
269
- # @see _parse
302
+ # @see ._parse
303
+ # @see #convert_to
270
304
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
271
305
  # @since 1.0.0
272
306
  def parse(input)
@@ -300,6 +334,7 @@ module UnitMeasurements
300
334
  #
301
335
  # @return [Measurement] The +Measurement+ instance.
302
336
  #
337
+ # @see Parser.parse
303
338
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
304
339
  # @since 1.0.0
305
340
  def _parse(string)
@@ -13,6 +13,8 @@ module UnitMeasurements
13
13
  class Unit
14
14
  # The name of the unit.
15
15
  #
16
+ # @return [String] Name of the unit.
17
+ #
16
18
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
17
19
  # @since 1.0.0
18
20
  attr_reader :name
@@ -20,24 +22,33 @@ module UnitMeasurements
20
22
  # The conversion value of the unit. It can be a numeric value or a string in
21
23
  # the form of a number followed by a unit name (e.g., “10 m”).
22
24
  #
25
+ # @return [String|Numeric|Array<Numeric, String>]
26
+ # Conversion value of the unit.
27
+ #
23
28
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
24
29
  # @since 1.0.0
25
30
  attr_reader :value
26
31
 
27
32
  # A set of alternative names for the unit.
28
33
  #
34
+ # @return [Set<String>] A set of alternative names.
35
+ #
29
36
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
30
37
  # @since 1.0.0
31
38
  attr_reader :aliases
32
39
 
33
40
  # The system to which the unit belongs (e.g., “metric”, “imperial”).
34
41
  #
42
+ # @return [String] Unit system in which the unit belongs.
43
+ #
35
44
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
36
45
  # @since 4.0.0
37
46
  attr_reader :system
38
47
 
39
48
  # The unit group to which the unit belongs.
40
49
  #
50
+ # @return [UnitGroup] Unit group in which the unit belongs.
51
+ #
41
52
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
42
53
  # @since 1.0.0
43
54
  attr_reader :unit_group
@@ -50,14 +61,13 @@ module UnitMeasurements
50
61
  # @param [String|Symbol|NilClass] system The system to which the unit belongs.
51
62
  # @param [UnitGroup|NilClass] unit_group The unit group to which the unit belongs.
52
63
  #
53
- # @see UnitGroup
54
64
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
55
65
  # @since 1.0.0
56
66
  def initialize(name, value:, aliases:, system:, unit_group: nil)
57
67
  @name = name.to_s.freeze
58
68
  @value = value
59
69
  @aliases = Set.new(aliases.map(&:to_s).sort.map(&:freeze)).freeze
60
- @system = system
70
+ @system = system.to_s.freeze
61
71
  @unit_group = unit_group
62
72
  end
63
73
 
@@ -71,7 +81,6 @@ module UnitMeasurements
71
81
  #
72
82
  # @return [Unit] A new unit with specified parameters.
73
83
  #
74
- # @see UnitGroup
75
84
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
76
85
  # @since 1.0.0
77
86
  def with(name: nil, value: nil, aliases: nil, system: nil, unit_group: nil)
@@ -147,35 +156,50 @@ module UnitMeasurements
147
156
 
148
157
  private
149
158
 
159
+ # Binary prefixes for SI units.
160
+ #
161
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
162
+ # @since 5.0.0
163
+ SI_BINARY_PREFIXES = [
164
+ ["Ki", %w[kibi], 2.pow(10)],
165
+ ["Mi", %w[mebi], 2.pow(20)],
166
+ ["Gi", %w[gibi], 2.pow(30)],
167
+ ["Ti", %w[tebi], 2.pow(40)],
168
+ ["Pi", %w[pebi], 2.pow(50)],
169
+ ["Ei", %w[exbi], 2.pow(60)],
170
+ ["Zi", %w[zebi], 2.pow(70)],
171
+ ["Yi", %w[yobi], 2.pow(80)],
172
+ ].map(&:freeze).freeze
173
+
150
174
  # Decimal prefixes for SI units.
151
175
  #
152
176
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
153
177
  # @since 1.0.0
154
178
  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]
179
+ ["q", %w[quecto], 1e-30],
180
+ ["r", %w[ronto], 1e-27],
181
+ ["y", %w[yocto], 1e-24],
182
+ ["z", %w[zepto], 1e-21],
183
+ ["a", %w[atto], 1e-18],
184
+ ["f", %w[femto], 1e-15],
185
+ ["p", %w[pico], 1e-12],
186
+ ["n", %w[nano], 1e-9],
187
+ ["μ", %w[micro], 1e-6],
188
+ ["m", %w[milli], 1e-3],
189
+ ["c", %w[centi], 1e-2],
190
+ ["d", %w[deci], 1e-1],
191
+ ["da", %w[deca deka], 1e+1],
192
+ ["h", %w[hecto], 1e+2],
193
+ ["k", %w[kilo], 1e+3],
194
+ ["M", %w[mega], 1e+6],
195
+ ["G", %w[giga], 1e+9],
196
+ ["T", %w[tera], 1e+12],
197
+ ["P", %w[peta], 1e+15],
198
+ ["E", %w[exa], 1e+18],
199
+ ["Z", %w[zetta], 1e+21],
200
+ ["Y", %w[yotta], 1e+24],
201
+ ["R", %w[ronna], 1e+27],
202
+ ["Q", %w[quetta], 1e+30]
179
203
  ].map(&:freeze).freeze
180
204
 
181
205
  # Parses tokens and returns a +conversion value+ and the +unit+.
@@ -30,6 +30,8 @@ module UnitMeasurements
30
30
  # UnitMeasurements::Length.units
31
31
  # => [#<UnitMeasurements::Unit: m (meter, meters, metre, metres)>, ...]
32
32
  #
33
+ # @return [Array<Unit>] An array of +Unit+ instances.
34
+ #
33
35
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
34
36
  # @since 1.0.0
35
37
  attr_reader :units
@@ -167,6 +169,70 @@ module UnitMeasurements
167
169
  !!unit_for(name)
168
170
  end
169
171
 
172
+ # Returns an array of units associated with a specified +unit_system+.
173
+ #
174
+ # This method takes a unit system name as an argument and filters the units
175
+ # in the unit group to return only those units that belong to the specified
176
+ # unit system. It then returns an array containing these filtered units. If
177
+ # there are no units associated with unit system, it returns empty array.
178
+ #
179
+ # @example
180
+ # UnitMeasurements::Length.units_for("metric")
181
+ # => [#<UnitMeasurements::Unit: m (meter, meters, metre, metres)>]
182
+ #
183
+ # UnitMeasurements::Length.units_for("imperial")
184
+ # => [#<UnitMeasurements::Unit: in (", inch, inches)>, ...]
185
+ #
186
+ # UnitMeasurements::Length.units_for("troy")
187
+ # => []
188
+ #
189
+ # @param [String|Symbol] system_name
190
+ # The name of the unit system to retrieve units for.
191
+ #
192
+ # @return [Array<Unit>]
193
+ # An array of +Unit+ instances associated with the specified unit system.
194
+ #
195
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
196
+ # @since 5.0.0
197
+ def units_for(system_name)
198
+ units.select { |unit| unit.system.to_s == system_name.to_s }
199
+ end
200
+
201
+ # This method works same as +units_for+ method but it raises an error if
202
+ # there are no units associated with the +system_name+.
203
+ #
204
+ # @example
205
+ # UnitMeasurements::Length.units_for!("metric")
206
+ # => [#<UnitMeasurements::Unit: m (meter, meters, metre, metres)>]
207
+ #
208
+ # UnitMeasurements::Length.units_for!("imperial")
209
+ # => [#<UnitMeasurements::Unit: in (", inch, inches)>, ...]
210
+ #
211
+ # UnitMeasurements::Length.units_for!("troy")
212
+ # => Invalid unit system 'troy' within the unit group. (UnitMeasurements::BaseError)
213
+ #
214
+ # @param [String|Symbol] system_name
215
+ # The name of the unit system to retrieve units for.
216
+ #
217
+ # @return [Array<Unit>]
218
+ # An array of +Unit+ instances associated with the specified unit system.
219
+ #
220
+ # @raise [BaseError]
221
+ # If there are no units associated with the provided +system_name+.
222
+ #
223
+ # @see #units_for
224
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
225
+ # @since 5.0.0
226
+ def units_for!(system_name)
227
+ system_units = units_for(system_name)
228
+
229
+ unless system_units.any?
230
+ raise BaseError, "Invalid unit system '#{system_name}' within the unit group."
231
+ end
232
+
233
+ system_units
234
+ end
235
+
170
236
  private
171
237
 
172
238
  # @private
@@ -18,6 +18,8 @@ module UnitMeasurements
18
18
  class UnitGroupBuilder
19
19
  # An array to store the units defined using the builder.
20
20
  #
21
+ # @return [Array<Unit>] An array of +Unit+ instances.
22
+ #
21
23
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
22
24
  # @since 1.0.0
23
25
  attr_reader :units
@@ -56,6 +58,9 @@ module UnitMeasurements
56
58
  #
57
59
  # @param [String|Symbol] name The name of the unit.
58
60
  # @param [Numeric|String] value The conversion value of the unit.
61
+ # @param [TrueClass|FalseClass] add_binary_prefixes
62
+ # Whether the unit supports binary SI prefixes along with decimal SI
63
+ # prefixes.
59
64
  # @param [Array<String|Symbol>, optional] aliases An array of alternative names for the unit.
60
65
  #
61
66
  # @return [Array<Unit>] An array of +Unit+ instances.
@@ -63,11 +68,11 @@ module UnitMeasurements
63
68
  # @see #build_si_units
64
69
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
65
70
  # @since 1.0.0
66
- def si_unit(name, value: 1.0, aliases: [])
67
- @units += build_si_units(name, value: value, aliases: aliases)
71
+ def si_unit(name, value: 1.0, add_binary_prefixes: false, aliases: [])
72
+ @units += build_si_units(name, value: value, add_binary_prefixes: add_binary_prefixes, aliases: aliases)
68
73
  end
69
74
 
70
- # Constructs and returns a +UnitGroup+ object based on the units defined
75
+ # Constructs and returns a +UnitGroup+ instance based on the units defined
71
76
  # using the builder.
72
77
  #
73
78
  # @return [UnitGroup]
@@ -133,6 +138,9 @@ module UnitMeasurements
133
138
  #
134
139
  # @param [String|Symbol] name The name of the unit.
135
140
  # @param [Numeric|String] value The conversion value of the unit.
141
+ # @param [TrueClass|FalseClass] add_binary_prefixes
142
+ # Whether the unit supports binary SI prefixes along with decimal SI
143
+ # prefixes.
136
144
  # @param [Array<String|Symbol>, optional] aliases
137
145
  # An array of alternative names for the unit.
138
146
  #
@@ -141,10 +149,12 @@ module UnitMeasurements
141
149
  # @see #build_unit
142
150
  # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
143
151
  # @since 1.0.0
144
- def build_si_units(name, value:, aliases:)
152
+ def build_si_units(name, value:, add_binary_prefixes:, aliases:)
145
153
  si_units = [build_unit(name, value: value, aliases: aliases)]
146
154
 
147
- Unit::SI_DECIMAL_PREFIXES.each do |short_prefix, long_prefix, multiplier|
155
+ si_prefixes = add_binary_prefixes ? (Unit::SI_DECIMAL_PREFIXES + Unit::SI_BINARY_PREFIXES) : Unit::SI_DECIMAL_PREFIXES
156
+
157
+ si_prefixes.each do |short_prefix, long_prefix, multiplier|
148
158
  si_aliases = long_prefix.product(aliases.to_a).flat_map do |prefix, unit|
149
159
  aliases.map { |alias_unit| prefix + alias_unit.to_s }
150
160
  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.1.0"
8
8
  end
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
23
23
 
24
24
  spec.metadata["homepage_uri"] = spec.homepage
25
- spec.metadata["documentation_uri"] = "https://shivam091.github.io/unit_measurements"
25
+ spec.metadata["documentation_uri"] = "https://rubydoc.info/gems/unit_measurements"
26
26
  spec.metadata["source_code_uri"] = "https://github.com/shivam091/unit_measurements"
27
27
  spec.metadata["changelog_uri"] = "https://github.com/shivam091/unit_measurements/blob/main/CHANGELOG.md"
28
28
  spec.metadata["bug_tracker_uri"] = "https://github.com/shivam091/unit_measurements/issues"
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.1.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-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -178,7 +178,7 @@ licenses:
178
178
  metadata:
179
179
  allowed_push_host: https://rubygems.org
180
180
  homepage_uri: https://github.com/shivam091/unit_measurements
181
- documentation_uri: https://shivam091.github.io/unit_measurements
181
+ documentation_uri: https://rubydoc.info/gems/unit_measurements
182
182
  source_code_uri: https://github.com/shivam091/unit_measurements
183
183
  changelog_uri: https://github.com/shivam091/unit_measurements/blob/main/CHANGELOG.md
184
184
  bug_tracker_uri: https://github.com/shivam091/unit_measurements/issues