unit_measurements_us_complete 5.17.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 +7 -0
- data/.github/workflows/main.yml +31 -0
- data/.github/workflows/pages.yml +31 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +645 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +56 -0
- data/LICENSE.md +21 -0
- data/README.md +511 -0
- data/Rakefile +10 -0
- data/lib/unit_measurements/arithmetic.rb +225 -0
- data/lib/unit_measurements/base.rb +177 -0
- data/lib/unit_measurements/cache.rb +173 -0
- data/lib/unit_measurements/comparison.rb +64 -0
- data/lib/unit_measurements/configuration.rb +64 -0
- data/lib/unit_measurements/conversion.rb +92 -0
- data/lib/unit_measurements/errors/blank_quantity_error.rb +21 -0
- data/lib/unit_measurements/errors/blank_unit_error.rb +21 -0
- data/lib/unit_measurements/errors/missing_primitive_unit_error.rb +24 -0
- data/lib/unit_measurements/errors/parse_error.rb +37 -0
- data/lib/unit_measurements/errors/primitive_unit_already_set_error.rb +22 -0
- data/lib/unit_measurements/errors/unit_already_defined_error.rb +37 -0
- data/lib/unit_measurements/errors/unit_error.rb +36 -0
- data/lib/unit_measurements/extras/conversion_methods.rb +87 -0
- data/lib/unit_measurements/extras/numeric_methods.rb +85 -0
- data/lib/unit_measurements/formatter.rb +58 -0
- data/lib/unit_measurements/math.rb +120 -0
- data/lib/unit_measurements/measurement.rb +539 -0
- data/lib/unit_measurements/normalizer.rb +155 -0
- data/lib/unit_measurements/parser.rb +220 -0
- data/lib/unit_measurements/unit.rb +243 -0
- data/lib/unit_measurements/unit_group.rb +297 -0
- data/lib/unit_measurements/unit_group_builder.rb +224 -0
- data/lib/unit_measurements/unit_groups/acceleration.rb +36 -0
- data/lib/unit_measurements/unit_groups/all.rb +56 -0
- data/lib/unit_measurements/unit_groups/amount_of_substance.rb +13 -0
- data/lib/unit_measurements/unit_groups/angular_acceleration.rb +14 -0
- data/lib/unit_measurements/unit_groups/angular_velocity.rb +25 -0
- data/lib/unit_measurements/unit_groups/area.rb +49 -0
- data/lib/unit_measurements/unit_groups/catalytic_activity.rb +13 -0
- data/lib/unit_measurements/unit_groups/density.rb +33 -0
- data/lib/unit_measurements/unit_groups/dynamic_viscosity.rb +22 -0
- data/lib/unit_measurements/unit_groups/electric_charge.rb +20 -0
- data/lib/unit_measurements/unit_groups/electric_conductance.rb +15 -0
- data/lib/unit_measurements/unit_groups/electric_current.rb +19 -0
- data/lib/unit_measurements/unit_groups/electric_dipole_moment.rb +13 -0
- data/lib/unit_measurements/unit_groups/electric_potential.rb +17 -0
- data/lib/unit_measurements/unit_groups/electric_quadrupole_moment.rb +14 -0
- data/lib/unit_measurements/unit_groups/electrical_capacitance.rb +15 -0
- data/lib/unit_measurements/unit_groups/electrical_elastance.rb +13 -0
- data/lib/unit_measurements/unit_groups/electrical_inductance.rb +15 -0
- data/lib/unit_measurements/unit_groups/electrical_resistance.rb +16 -0
- data/lib/unit_measurements/unit_groups/energy.rb +58 -0
- data/lib/unit_measurements/unit_groups/force.rb +47 -0
- data/lib/unit_measurements/unit_groups/frequency.rb +16 -0
- data/lib/unit_measurements/unit_groups/illuminance.rb +18 -0
- data/lib/unit_measurements/unit_groups/information_entropy.rb +15 -0
- data/lib/unit_measurements/unit_groups/kinetic_viscosity.rb +18 -0
- data/lib/unit_measurements/unit_groups/length.rb +67 -0
- data/lib/unit_measurements/unit_groups/luminance.rb +21 -0
- data/lib/unit_measurements/unit_groups/luminous_flux.rb +11 -0
- data/lib/unit_measurements/unit_groups/luminous_intensity.rb +13 -0
- data/lib/unit_measurements/unit_groups/magnetic_field.rb +13 -0
- data/lib/unit_measurements/unit_groups/magnetic_flux.rb +15 -0
- data/lib/unit_measurements/unit_groups/magnetic_induction.rb +13 -0
- data/lib/unit_measurements/unit_groups/magnetomotive_force.rb +13 -0
- data/lib/unit_measurements/unit_groups/mass_flow_rate.rb +49 -0
- data/lib/unit_measurements/unit_groups/plane_angle.rb +30 -0
- data/lib/unit_measurements/unit_groups/power.rb +54 -0
- data/lib/unit_measurements/unit_groups/pressure.rb +60 -0
- data/lib/unit_measurements/unit_groups/quantity.rb +14 -0
- data/lib/unit_measurements/unit_groups/radiation_absorbed_dose.rb +14 -0
- data/lib/unit_measurements/unit_groups/radiation_equivalent_dose.rb +13 -0
- data/lib/unit_measurements/unit_groups/radiation_exposure.rb +15 -0
- data/lib/unit_measurements/unit_groups/radioactivity.rb +14 -0
- data/lib/unit_measurements/unit_groups/solid_angle.rb +18 -0
- data/lib/unit_measurements/unit_groups/sound_level.rb +13 -0
- data/lib/unit_measurements/unit_groups/temperature.rb +19 -0
- data/lib/unit_measurements/unit_groups/time.rb +29 -0
- data/lib/unit_measurements/unit_groups/torque.rb +40 -0
- data/lib/unit_measurements/unit_groups/velocity.rb +37 -0
- data/lib/unit_measurements/unit_groups/volume.rb +67 -0
- data/lib/unit_measurements/unit_groups/volumetric_flow_rate.rb +35 -0
- data/lib/unit_measurements/unit_groups/weight.rb +55 -0
- data/lib/unit_measurements/version.rb +8 -0
- data/lib/unit_measurements.rb +7 -0
- data/unit_measurements.gemspec +43 -0
- data/units.md +843 -0
- metadata +216 -0
@@ -0,0 +1,220 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# -*- frozen_stringing_literal: true -*-
|
3
|
+
# -*- warn_indent: true -*-
|
4
|
+
|
5
|
+
module UnitMeasurements
|
6
|
+
# The +UnitMeasurements::Parser+ class provides methods for parsing strings to
|
7
|
+
# extract quantity and associated unit. It can handle various formats, including
|
8
|
+
# complex numbers, scientific numbers, and rational numbers for the +quantity+.
|
9
|
+
#
|
10
|
+
# @see Measurement
|
11
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
12
|
+
# @since 1.0.0
|
13
|
+
class Parser
|
14
|
+
# Matches any character sequence that does not consist of digits, whitespace,
|
15
|
+
# or forward slashes.
|
16
|
+
#
|
17
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
18
|
+
# @since 1.0.0
|
19
|
+
UNIT_REGEX = /
|
20
|
+
( # Start of the capturing group
|
21
|
+
[^\d\s\/] # Match any character that is not a digit, whitespace, or a forward slash
|
22
|
+
.* # Match zero or more of any character (except for a newline)
|
23
|
+
) # End of the capturing group
|
24
|
+
/x.freeze
|
25
|
+
|
26
|
+
# Matches scientific numbers (e.g., +1.23e-4+).
|
27
|
+
#
|
28
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
29
|
+
# @since 1.0.0
|
30
|
+
SCIENTIFIC_NUMBER = /
|
31
|
+
( # Start of a capturing group (denoted by parentheses)
|
32
|
+
[+-]? # Match an optional plus or minus sign (+ or -)
|
33
|
+
\d* # Match zero or more digits
|
34
|
+
\.? # Match an optional dot (.)
|
35
|
+
\d+ # Match one or more digits
|
36
|
+
(?: # Start of a non-capturing group
|
37
|
+
[Ee] # Match either 'E' or 'e'
|
38
|
+
[+-]? # Match an optional plus or minus sign (+ or -)
|
39
|
+
)? # End of the non-capturing group; ? makes it optional
|
40
|
+
\d* # Match zero or more digits
|
41
|
+
) # End of the capturing group
|
42
|
+
/x.freeze
|
43
|
+
|
44
|
+
# Matches rational numbers (e.g., +1/2+).
|
45
|
+
#
|
46
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
47
|
+
# @since 1.0.0
|
48
|
+
RATIONAL_NUMBER = /
|
49
|
+
( # Start of the first capturing group
|
50
|
+
[+-]? # Match an optional plus or minus sign (+ or -)
|
51
|
+
\d+ # Match one or more digits
|
52
|
+
\s+ # Match one or more whitespace characters
|
53
|
+
)? # End of the first capturing group
|
54
|
+
( # Start of the second capturing group (the fraction part)
|
55
|
+
(\d+) # Start of the third capturing group (one or more digits, the numerator)
|
56
|
+
\/ # Match a forward slash - the division symbol
|
57
|
+
(\d+) # Start of the fourth capturing group (one or more digits, the denominator)
|
58
|
+
) # End of the second capturing group (the fraction part)
|
59
|
+
/x.freeze
|
60
|
+
|
61
|
+
# Matches complex numbers (e.g., +1-2i+).
|
62
|
+
#
|
63
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
64
|
+
# @since 1.0.0
|
65
|
+
COMPLEX_NUMBER = /
|
66
|
+
#{SCIENTIFIC_NUMBER} # Pattern for scientific number
|
67
|
+
#{SCIENTIFIC_NUMBER} # Pattern for scientific number
|
68
|
+
i # Match the letter 'i' (the imaginary unit)
|
69
|
+
/x.freeze
|
70
|
+
|
71
|
+
# Matches strings containing scientific numbers and unit.
|
72
|
+
#
|
73
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
74
|
+
# @since 1.0.0
|
75
|
+
SCIENTIFIC_REGEX = /
|
76
|
+
\A # Anchor at the start of the string
|
77
|
+
#{SCIENTIFIC_NUMBER} # Match a scientific number (as defined earlier)
|
78
|
+
\s* # Match zero or more whitespace characters
|
79
|
+
#{UNIT_REGEX}? # Match a unit, the '?' makes it optional
|
80
|
+
\z # Anchor at the end of the string
|
81
|
+
/x.freeze
|
82
|
+
|
83
|
+
# Matches strings containing rational numbers and unit.
|
84
|
+
#
|
85
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
86
|
+
# @since 1.0.0
|
87
|
+
RATIONAL_REGEX = /
|
88
|
+
\A # Anchor at the start of the string
|
89
|
+
#{RATIONAL_NUMBER} # Match a rational number (as defined earlier)
|
90
|
+
\s* # Match zero or more whitespace characters
|
91
|
+
#{UNIT_REGEX}? # Match a unit, the '?' makes it optional
|
92
|
+
\z
|
93
|
+
/x.freeze
|
94
|
+
|
95
|
+
# Matches strings containing complex numbers and unit.
|
96
|
+
#
|
97
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
98
|
+
# @since 1.0.0
|
99
|
+
COMPLEX_REGEX = /
|
100
|
+
\A # Anchor at the start of the string
|
101
|
+
#{COMPLEX_NUMBER} # Match a complex number (as defined earlier)
|
102
|
+
\s* # Match zero or more whitespace characters
|
103
|
+
#{UNIT_REGEX}? # Match a unit, the '?' makes it optional
|
104
|
+
\z
|
105
|
+
/x.freeze
|
106
|
+
|
107
|
+
class << self
|
108
|
+
# Parses a string to extract a +quantity+ and its associated +unit+. This
|
109
|
+
# method first extracts a +quantity+ and converts it to +Float+ before
|
110
|
+
# returning it.
|
111
|
+
#
|
112
|
+
# To get the correct parsed results, you must first normalize the +string+
|
113
|
+
# with +Normalizer+ if using the parser standalone.
|
114
|
+
#
|
115
|
+
# @example Parsing string representing a complex number:
|
116
|
+
# UnitMeasurements::Parser.parse("1+2i m")
|
117
|
+
# => [(1.0+2.0i), "m"]
|
118
|
+
#
|
119
|
+
# @example Parsing string representing a rational number:
|
120
|
+
# UnitMeasurements::Parser.parse("1/2 m")
|
121
|
+
# => [0.5, "m"]
|
122
|
+
#
|
123
|
+
# @example Parsing string representing a mixed rational number:
|
124
|
+
# UnitMeasurements::Parser.parse("2 1/2 km")
|
125
|
+
# => [2.5, "km"]
|
126
|
+
#
|
127
|
+
# @example Parsing string representing a scientific number:
|
128
|
+
# UnitMeasurements::Parser.parse("1e+2 km")
|
129
|
+
# => [100.0, "km"]
|
130
|
+
#
|
131
|
+
# @param [String] string
|
132
|
+
# The input string containing a +quantity+ and an optional +unit+.
|
133
|
+
#
|
134
|
+
# @return [Array<Numeric, String|NilClass>]
|
135
|
+
# The parsed +quantity+ and the +unit+ associated with it (or +nil+ if
|
136
|
+
# no unit is specified in the +string+).
|
137
|
+
#
|
138
|
+
# @raise [ParseError] If the string is invalid and cannot be parsed.
|
139
|
+
#
|
140
|
+
# @see Measurement
|
141
|
+
# @see Normalizer
|
142
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
143
|
+
# @since 1.0.0
|
144
|
+
def parse(string)
|
145
|
+
case string
|
146
|
+
when COMPLEX_REGEX then parse_complex(string)
|
147
|
+
when SCIENTIFIC_REGEX then parse_scientific(string)
|
148
|
+
when RATIONAL_REGEX then parse_rational(string)
|
149
|
+
else raise ParseError, string
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
# @private
|
156
|
+
# Parses a string representing a complex number with an optional unit.
|
157
|
+
#
|
158
|
+
# @param [String] string
|
159
|
+
# The input string containing a complex number and an optional unit.
|
160
|
+
#
|
161
|
+
# @return [Array<Numeric, String|NilClass>]
|
162
|
+
# The parsed complex number and the associated unit (or +nil+ if no unit
|
163
|
+
# is specified in the string).
|
164
|
+
#
|
165
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
166
|
+
# @since 1.0.0
|
167
|
+
def parse_complex(string)
|
168
|
+
real, imaginary, unit = string.match(COMPLEX_REGEX)&.captures
|
169
|
+
quantity = Complex(real.to_f, imaginary.to_f)
|
170
|
+
|
171
|
+
[quantity, unit]
|
172
|
+
end
|
173
|
+
|
174
|
+
# @private
|
175
|
+
# Parses a string representing a scientific number with an optional unit.
|
176
|
+
#
|
177
|
+
# @param [String] string
|
178
|
+
# The input string containing a scientific number and an optional unit.
|
179
|
+
#
|
180
|
+
# @return [Array<Numeric, String|NilClass>]
|
181
|
+
# The parsed scientific number and the associated unit (or +nil+ if no unit
|
182
|
+
# is specified in the string).
|
183
|
+
#
|
184
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
185
|
+
# @since 1.0.0
|
186
|
+
def parse_scientific(string)
|
187
|
+
whole, unit = string.match(SCIENTIFIC_REGEX)&.captures
|
188
|
+
quantity = whole.to_f
|
189
|
+
|
190
|
+
[quantity, unit]
|
191
|
+
end
|
192
|
+
|
193
|
+
# @private
|
194
|
+
# Parses a string representing a rational number with an optional unit.
|
195
|
+
#
|
196
|
+
# @param [String] string
|
197
|
+
# The input string containing a rational number and an optional unit.
|
198
|
+
#
|
199
|
+
# @return [Array<Numeric, String|NilClass>]
|
200
|
+
# The parsed rational number and the associated unit (or +nil+ if no unit
|
201
|
+
# is specified in the string).
|
202
|
+
#
|
203
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
204
|
+
# @since 1.0.0
|
205
|
+
def parse_rational(string)
|
206
|
+
whole, _, numerator, denominator, unit = string.match(RATIONAL_REGEX)&.captures
|
207
|
+
|
208
|
+
if numerator && denominator
|
209
|
+
numerator = numerator.to_f + (denominator.to_f * whole.to_f)
|
210
|
+
denominator = denominator.to_f
|
211
|
+
quantity = Rational(numerator, denominator).to_f
|
212
|
+
else
|
213
|
+
quantity = whole.to_f
|
214
|
+
end
|
215
|
+
|
216
|
+
[quantity, unit]
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# -*- frozen_string_literal: true -*-
|
3
|
+
# -*- warn_indent: true -*-
|
4
|
+
|
5
|
+
require "set"
|
6
|
+
|
7
|
+
module UnitMeasurements
|
8
|
+
# The +UnitMeasurements::Unit+ class represents a unit of measurement and
|
9
|
+
# provides methods to interact with its properties and conversion factors.
|
10
|
+
#
|
11
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
12
|
+
# @since 1.0.0
|
13
|
+
class Unit
|
14
|
+
# The name of the unit.
|
15
|
+
#
|
16
|
+
# @return [String] Name of the unit.
|
17
|
+
#
|
18
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
19
|
+
# @since 1.0.0
|
20
|
+
attr_reader :name
|
21
|
+
|
22
|
+
# The conversion value of the unit. It can be a numeric value or a string in
|
23
|
+
# the form of a number followed by a unit name (e.g., “10 m”).
|
24
|
+
#
|
25
|
+
# @return [String|Numeric|Array<Numeric, String>]
|
26
|
+
# Conversion value of the unit.
|
27
|
+
#
|
28
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
29
|
+
# @since 1.0.0
|
30
|
+
attr_reader :value
|
31
|
+
|
32
|
+
# A set of alternative names for the unit.
|
33
|
+
#
|
34
|
+
# @return [Set<String>] A set of alternative names.
|
35
|
+
#
|
36
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
37
|
+
# @since 1.0.0
|
38
|
+
attr_reader :aliases
|
39
|
+
|
40
|
+
# The system to which the unit belongs (e.g., “metric”, “imperial”).
|
41
|
+
#
|
42
|
+
# @return [String] Unit system in which the unit belongs.
|
43
|
+
#
|
44
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
45
|
+
# @since 4.0.0
|
46
|
+
attr_reader :system
|
47
|
+
|
48
|
+
# The unit group to which the unit belongs.
|
49
|
+
#
|
50
|
+
# @return [UnitGroup] Unit group in which the unit belongs.
|
51
|
+
#
|
52
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
53
|
+
# @since 1.0.0
|
54
|
+
attr_reader :unit_group
|
55
|
+
|
56
|
+
# Initializes a new +Unit+ instance.
|
57
|
+
#
|
58
|
+
# @param [String|Symbol] name The name of the unit.
|
59
|
+
# @param [String|Numeric] value The conversion value of the unit.
|
60
|
+
# @param [Array<String|Symbol>] aliases Alternative names for the unit.
|
61
|
+
# @param [String|Symbol|NilClass] system The system to which the unit belongs.
|
62
|
+
# @param [UnitGroup|NilClass] unit_group The unit group to which the unit belongs.
|
63
|
+
#
|
64
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
65
|
+
# @since 1.0.0
|
66
|
+
def initialize(name, value:, aliases:, system:, unit_group: nil)
|
67
|
+
@name = name.to_s.freeze
|
68
|
+
@value = value
|
69
|
+
@aliases = Set.new(aliases.map(&:to_s).sort.map(&:freeze)).freeze
|
70
|
+
@system = system.to_s.freeze
|
71
|
+
@unit_group = unit_group
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns a new +Unit+ instance with specified attributes.
|
75
|
+
#
|
76
|
+
# @param [String|Symbol] name The new name of the unit.
|
77
|
+
# @param [String|Numeric] value The new conversion value of the unit.
|
78
|
+
# @param [Set<String>] aliases New alternative names for the unit.
|
79
|
+
# @param [String|Symbol|NilClass] system The new system to which the unit belongs.
|
80
|
+
# @param [UnitGroup|NilClass] unit_group The new unit group to which the unit belongs.
|
81
|
+
#
|
82
|
+
# @return [Unit] A new unit with specified parameters.
|
83
|
+
#
|
84
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
85
|
+
# @since 1.0.0
|
86
|
+
def with(name: nil, value: nil, aliases: nil, system: nil, unit_group: nil)
|
87
|
+
self.class.new(
|
88
|
+
(name || self.name),
|
89
|
+
value: (value || self.value),
|
90
|
+
aliases: (aliases || self.aliases),
|
91
|
+
system: (system || self.system),
|
92
|
+
unit_group: (unit_group || self.unit_group)
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns an array containing the name of the unit and its aliases, sorted
|
97
|
+
# alphabetically.
|
98
|
+
#
|
99
|
+
# @example
|
100
|
+
# UnitMeasurements::Length.new(1, "m").unit.names
|
101
|
+
# => ["m", "meter", "meters", "metre", "metres"]
|
102
|
+
#
|
103
|
+
# @return [Array<String>] An array of unit names.
|
104
|
+
#
|
105
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
106
|
+
# @since 1.0.0
|
107
|
+
def names
|
108
|
+
(aliases + [name]).sort.freeze
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns the name of the unit as a string.
|
112
|
+
#
|
113
|
+
# @example
|
114
|
+
# UnitMeasurements::Length.new(1, "m").unit.to_s
|
115
|
+
# => "m"
|
116
|
+
#
|
117
|
+
# @return [String] The name of the unit.
|
118
|
+
#
|
119
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
120
|
+
# @since 1.0.0
|
121
|
+
def to_s
|
122
|
+
name
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns an object representation of the unit, including its aliases if present.
|
126
|
+
#
|
127
|
+
# @return [Object] An object representation of the +unit+.
|
128
|
+
#
|
129
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
130
|
+
# @since 1.0.0
|
131
|
+
def inspect
|
132
|
+
aliases = "(#{@aliases.join(", ")})" if @aliases.any?
|
133
|
+
"#<#{self.class.name}: #{name} #{aliases}>"
|
134
|
+
end
|
135
|
+
|
136
|
+
# Calculates the conversion factor for the unit. This method is recursively
|
137
|
+
# invoked to calculate the conversion factor of the unit, if unit conversion
|
138
|
+
# +value+ is specified with respect to the other unit.
|
139
|
+
#
|
140
|
+
# This method uses +parse_value+ method to extract the conversion value and
|
141
|
+
# the unit.
|
142
|
+
#
|
143
|
+
# @return [Numeric] The conversion factor as a numeric value.
|
144
|
+
#
|
145
|
+
# @see #parse_value
|
146
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
147
|
+
# @since 1.0.0
|
148
|
+
def conversion_factor
|
149
|
+
return value if value.is_a?(Numeric)
|
150
|
+
|
151
|
+
measurement_value, measurement_unit = parse_value(value)
|
152
|
+
conversion_factor = unit_group.unit_for!(measurement_unit).conversion_factor
|
153
|
+
|
154
|
+
conversion_factor * measurement_value
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
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
|
+
|
174
|
+
# Decimal prefixes for SI units.
|
175
|
+
#
|
176
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
177
|
+
# @since 1.0.0
|
178
|
+
SI_DECIMAL_PREFIXES = [
|
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]
|
203
|
+
].map(&:freeze).freeze
|
204
|
+
|
205
|
+
# Parses tokens and returns a +conversion value+ and the +unit+.
|
206
|
+
#
|
207
|
+
# This method is used internally to parse the conversion value of the unit
|
208
|
+
# while calculating the conversion factor. It handles cases where the value
|
209
|
+
# can be provided as a string or an array containing a number and a unit.
|
210
|
+
#
|
211
|
+
# For example, if the value is provided as a string in the form of "10 m",
|
212
|
+
# it will be parsed to return 10.0 as the conversion value and "m" as the
|
213
|
+
# unit.
|
214
|
+
#
|
215
|
+
# This method returns conversion value in +rational+ number to avoid precision
|
216
|
+
# errors and frozen string of unit name.
|
217
|
+
#
|
218
|
+
# @param [String|Array] tokens
|
219
|
+
# The value to be parsed. It can be either a string or an array containing
|
220
|
+
# a number and a unit.
|
221
|
+
#
|
222
|
+
# @return [Array<Numeric, String>] The array of conversion value and the unit.
|
223
|
+
#
|
224
|
+
# @raise [BaseError]
|
225
|
+
# if +tokens+ is not an instance of +Array+ or +String+, or +tokens+ array
|
226
|
+
# contains more than two elements.
|
227
|
+
#
|
228
|
+
# @see #conversion_factor
|
229
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
230
|
+
# @since 1.2.0
|
231
|
+
def parse_value(tokens)
|
232
|
+
case tokens
|
233
|
+
when String
|
234
|
+
tokens = Parser.parse(value)
|
235
|
+
when Array
|
236
|
+
raise BaseError, "Cannot parse [number, unit] formatted tokens from #{tokens}." unless tokens.size == 2
|
237
|
+
else
|
238
|
+
raise BaseError, "Value of the unit must be defined as string or array, but received #{tokens}"
|
239
|
+
end
|
240
|
+
[tokens[0].to_r, tokens[1].freeze]
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|