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