composite_unit_measurements 0.1.0 → 0.3.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 +4 -4
- data/CHANGELOG.md +22 -0
- data/Gemfile.lock +3 -3
- data/README.md +104 -10
- data/lib/composite_unit_measurements/base.rb +50 -0
- data/lib/composite_unit_measurements/length.rb +145 -0
- data/lib/composite_unit_measurements/time.rb +105 -0
- data/lib/composite_unit_measurements/version.rb +23 -1
- data/lib/composite_unit_measurements/weight.rb +144 -0
- data/lib/composite_unit_measurements.rb +4 -4
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd67813e0e00bce4c907e7076ec4a62994570585875da38dfa72bc968b3c0c20
|
4
|
+
data.tar.gz: c9de7ccfd6e0ede94d8cd5976174a1a60ed4f4cf3566bc613349a211ea9e4309
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7291bb98bb1e404be485f5f89de9f7594a7093f89cb98c4fd27310051804bfd22ea891acdfffed137ed466b0d9e778d6034439561dffe5e1e5b8b354093044b0
|
7
|
+
data.tar.gz: d86f50e73b9044cd8248bf49454c8c036a99b0bd2577fe21554b2c52ff14d1951bf19a11c388b9c0ddfed1670a1d315b054cda0d191909b1ae29cdc8793bf1e9
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
## [0.3.0](https://github.com/shivam091/composite_unit_measurements/compare/v0.2.0...v0.3.0) - 2023-11-27
|
2
|
+
|
3
|
+
### What's new
|
4
|
+
|
5
|
+
- Added ability to parse `kilometre-metre` and `metre-centimetre` length measurements.
|
6
|
+
- Added ability to parse `hour-minute` time measurement.
|
7
|
+
- Added ability to parse `kilogramme-gramme` weight measurement.
|
8
|
+
|
9
|
+
-----------
|
10
|
+
|
11
|
+
## [0.2.0](https://github.com/shivam091/composite_unit_measurements/compare/v0.1.0...v0.2.0) - 2023-11-17
|
12
|
+
|
13
|
+
### What's new
|
14
|
+
|
15
|
+
- Added ability to parse composite measurements containing `real`, `scientific`,
|
16
|
+
`rational`, and `complex` numbers.
|
17
|
+
- Added ability to parse `foot-inch` length measurement.
|
18
|
+
- Added ability to parse `duration`.
|
19
|
+
- Added ability to parse `pound-ounce` and `stone-pound` weight measurement.
|
20
|
+
|
21
|
+
-----------
|
22
|
+
|
1
23
|
## 0.1.0 - 2023-11-09
|
2
24
|
|
3
25
|
### Initial release
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
composite_unit_measurements (0.
|
4
|
+
composite_unit_measurements (0.3.0)
|
5
5
|
activesupport (~> 7.0)
|
6
6
|
unit_measurements (~> 5)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activesupport (7.1.
|
11
|
+
activesupport (7.1.2)
|
12
12
|
base64
|
13
13
|
bigdecimal
|
14
14
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
@@ -54,7 +54,7 @@ GEM
|
|
54
54
|
simplecov_json_formatter (0.1.4)
|
55
55
|
tzinfo (2.0.6)
|
56
56
|
concurrent-ruby (~> 1.0)
|
57
|
-
unit_measurements (5.
|
57
|
+
unit_measurements (5.11.1)
|
58
58
|
activesupport (~> 7.0)
|
59
59
|
|
60
60
|
PLATFORMS
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Composite Unit Measurements
|
2
2
|
|
3
|
-
A
|
3
|
+
A collection of specialized parsers designed for handling composite measurement strings.
|
4
4
|
|
5
5
|
[](https://github.com/shivam091/composite_unit_measurements/actions/workflows/main.yml)
|
6
6
|
[](https://badge.fury.io/rb/composite_unit_measurements)
|
@@ -13,17 +13,18 @@ A set of specialized parsers for dealing with composite measurement strings.
|
|
13
13
|
|
14
14
|
## Introduction
|
15
15
|
|
16
|
-
The `CompositeUnitMeasurements` gem
|
17
|
-
composite measurement strings.
|
18
|
-
|
16
|
+
The `CompositeUnitMeasurements` gem offers versatile parsers for efficiently parsing
|
17
|
+
composite measurement strings. Leveraging the power of the `unit_measurements` gem,
|
18
|
+
it enables smooth handling of composite measurements in various units.
|
19
19
|
|
20
20
|
## Minimum Requirements
|
21
21
|
|
22
|
-
* Ruby 3.2.2+ (https://www.ruby-lang.org/en/downloads/branches/)
|
22
|
+
* Ruby 3.2.2+ ([Download Ruby](https://www.ruby-lang.org/en/downloads/branches/))
|
23
23
|
|
24
24
|
## Installation
|
25
25
|
|
26
|
-
|
26
|
+
To use `composite_unit_measurements-rails` in your Rails application, add the
|
27
|
+
following line to your Gemfile:
|
27
28
|
|
28
29
|
```ruby
|
29
30
|
gem "composite_unit_measurements"
|
@@ -37,13 +38,106 @@ Or otherwise simply install it yourself as:
|
|
37
38
|
|
38
39
|
`$ gem install composite_unit_measurements`
|
39
40
|
|
41
|
+
## Usage
|
42
|
+
|
43
|
+
Each packaged parser includes the `#parse` method to parse composite measurements.
|
44
|
+
You can use an appropriate parser to parse measurements. The final result of `#parse`
|
45
|
+
is returned in the leftmost unit of your measurement.
|
46
|
+
|
47
|
+
This gem internally uses [`unit_measurements`](https://github.com/shivam091/unit_measurements)
|
48
|
+
to perform conversions and arithmetic operations. You can build supported composite measurements
|
49
|
+
using any [unit alias](https://github.com/shivam091/unit_measurements/blob/main/units.md).
|
50
|
+
|
51
|
+
### Examples
|
52
|
+
|
53
|
+
**Parsing length measurements:**
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
CompositeUnitMeasurements::Length.parse("5 ft 6 in")
|
57
|
+
#=> 5.5 ft
|
58
|
+
CompositeUnitMeasurements::Length.parse("6 m 50 cm")
|
59
|
+
#=> 6.5 m
|
60
|
+
CompositeUnitMeasurements::Length.parse("5 km 500 m")
|
61
|
+
#=> 5.5 km
|
62
|
+
```
|
63
|
+
|
64
|
+
**Parsing weight measurements:**
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
CompositeUnitMeasurements::Weight.parse("8 lb 12 oz")
|
68
|
+
#=> 8.75 lb
|
69
|
+
CompositeUnitMeasurements::Weight.parse("2 st 6 lb")
|
70
|
+
#=> 2.428571428571429 st
|
71
|
+
CompositeUnitMeasurements::Weight.parse("2 st 6 lb")
|
72
|
+
# 4.5 kg
|
73
|
+
```
|
74
|
+
|
75
|
+
**Parsing time measurements:**
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
CompositeUnitMeasurements::Time.parse("3 h 45 min")
|
79
|
+
#=> 3.75 hx
|
80
|
+
CompositeUnitMeasurements::Time.parse("12:60:3600,360000000")
|
81
|
+
#=> 14.1 h
|
82
|
+
```
|
83
|
+
|
84
|
+
### Support for numeric types
|
85
|
+
|
86
|
+
Each parser can handle various numeric types, including scientific notation, rational numbers, and complex numbers.
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
CompositeUnitMeasurements::Length.parse("1+2i ft 12 in")
|
90
|
+
#=> 2.0+2.0i ft
|
91
|
+
CompositeUnitMeasurements::Length.parse("1.5 ft 12e2 in")
|
92
|
+
#=> 101.5 ft
|
93
|
+
CompositeUnitMeasurements::Length.parse("1 1/2 ft 1+2i in")
|
94
|
+
#=> 1.5833333333333333+0.16666666666666669i ft
|
95
|
+
CompositeUnitMeasurements::Length.parse("2 ft 1+2i in")
|
96
|
+
#=> 2.0833333333333335+0.16666666666666669i ft
|
97
|
+
CompositeUnitMeasurements::Length.parse("1e-2 ft 1+2i in")
|
98
|
+
#=> 0.09333333333333334+0.16666666666666669i ft
|
99
|
+
```
|
100
|
+
|
101
|
+
## Packaged parsers & supported composite measurements
|
102
|
+
|
103
|
+
The `composite_unit_measurements` gem supports parsing various composite measurements, including:
|
104
|
+
|
105
|
+
**1. CompositeUnitMeasurements::Length**
|
106
|
+
- foot-inch (5 ft 6 in)
|
107
|
+
- metre-centimetre (6 m 50 cm)
|
108
|
+
- kilometre-metre (5 km 500 m)
|
109
|
+
|
110
|
+
**2. CompositeUnitMeasurements::Weight**
|
111
|
+
- pound-ounce (8 lb 12 oz)
|
112
|
+
- stone-pound (2 st 6 lb)
|
113
|
+
- kilogramme-gramme (4 kg 500 g)
|
114
|
+
|
115
|
+
**3. CompositeUnitMeasurements::Time**
|
116
|
+
- hour-minute (3 h 45 min)
|
117
|
+
- hour-minute-second-microsecond (12:60,3600:360000000)
|
118
|
+
|
119
|
+
### Specifing parsers
|
120
|
+
|
121
|
+
By default, `composite_unit_measurements` includes all packaged parsers automatically
|
122
|
+
when required in your application. However, you can opt to use specific parsers as
|
123
|
+
needed:
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
require "composite_unit_measurements/base"
|
127
|
+
|
128
|
+
require "composite_unit_measurements/length"
|
129
|
+
require "composite_unit_measurements/weight"
|
130
|
+
```
|
131
|
+
|
40
132
|
## Contributing
|
41
133
|
|
42
|
-
|
43
|
-
|
134
|
+
Contributions to this project are welcomed! To contribute:
|
135
|
+
|
136
|
+
1. Fork this repository
|
137
|
+
2. Create a new branch (`git checkout -b my-new-feature`)
|
44
138
|
3. Commit your changes (`git commit -am "Add some feature"`)
|
45
|
-
4. Push to
|
46
|
-
5. Create new Pull Request
|
139
|
+
4. Push the changes to your branch (`git push origin my-new-feature`)
|
140
|
+
5. Create new **Pull Request**
|
47
141
|
|
48
142
|
## License
|
49
143
|
|
@@ -5,3 +5,53 @@
|
|
5
5
|
require "unit_measurements/base"
|
6
6
|
|
7
7
|
require "composite_unit_measurements/version"
|
8
|
+
|
9
|
+
module CompositeUnitMeasurements
|
10
|
+
# Matches real numbers in the form of 31, +72, or -12.
|
11
|
+
REAL_NUMBER = /
|
12
|
+
(?: # Start of non-capturing group
|
13
|
+
[+-]? # Optional plus (+) or minus (-) sign
|
14
|
+
\d+ # One or more digits
|
15
|
+
) # End of non-capturing group
|
16
|
+
/x.freeze
|
17
|
+
|
18
|
+
# Matches a rational number in the form of a/b (fractional) or a b/c (mixed fractional).
|
19
|
+
RATIONAL_NUMBER = /
|
20
|
+
(?: # Start of optional non-capturing group
|
21
|
+
[+-]? # Optional plus (+) or minus (-) sign
|
22
|
+
\d+ # One or more digits
|
23
|
+
\s+ # One or more whitespace
|
24
|
+
)? # End of optional non-capturing group
|
25
|
+
( # Start of capturing group for the fraction
|
26
|
+
(\d+) # Capture the numerator (one or more digits)
|
27
|
+
\/ # Match the forward slash, indicating division
|
28
|
+
(\d+) # Capture the denominator (one or more digits)
|
29
|
+
) # End of capturing group for the fraction
|
30
|
+
/x.freeze
|
31
|
+
|
32
|
+
# Matches a scientific number in various formats like 1.23E+4 or -5.67e-8.
|
33
|
+
SCIENTIFIC_NUMBER = /
|
34
|
+
(?: # Start of non-capturing group
|
35
|
+
[+-]? # Optional plus (+) or minus (-) sign
|
36
|
+
\d* # Zero or more digits (integer part)
|
37
|
+
\.? # Optional decimal point
|
38
|
+
\d+ # One or more digits (fractional part)
|
39
|
+
(?: # Start of non-capturing group for exponent part
|
40
|
+
[Ee] # Match 'E' or 'e' for exponentiation
|
41
|
+
[+-]? # Optional plus (+) or minus (-) sign for exponent
|
42
|
+
\d+ # One or more digits (exponent value)
|
43
|
+
)? # End of non-capturing group of exponent part (optional)
|
44
|
+
) # End of non-capturing group
|
45
|
+
/x.freeze
|
46
|
+
|
47
|
+
# Matches complex numbers in the form of a+bi, where both 'a' and 'b' can be
|
48
|
+
# in scientific notation. It captures the real and imaginary parts.
|
49
|
+
COMPLEX_NUMBER = /
|
50
|
+
#{SCIENTIFIC_NUMBER} # Pattern for scientific number
|
51
|
+
#{SCIENTIFIC_NUMBER} # Pattern for scientific number
|
52
|
+
i # Match the letter 'i' (the imaginary unit)
|
53
|
+
/x.freeze
|
54
|
+
|
55
|
+
# Matches any number, including scientific, complex, rational, and real numbers.
|
56
|
+
ANY_NUMBER = /(?<number>#{SCIENTIFIC_NUMBER}|#{COMPLEX_NUMBER}|#{RATIONAL_NUMBER}|#{REAL_NUMBER})/.freeze
|
57
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# -*- frozen_string_literal: true -*-
|
3
|
+
# -*- warn_indent: true -*-
|
4
|
+
|
5
|
+
require "unit_measurements/unit_groups/length"
|
6
|
+
|
7
|
+
module CompositeUnitMeasurements
|
8
|
+
# A parser handling +length+ measurements, particularly for composite units
|
9
|
+
# like +foot-inch+, +kilometre-metre+, +mile-yard+, etc.
|
10
|
+
#
|
11
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
12
|
+
# @since 0.2.0
|
13
|
+
class Length
|
14
|
+
class << self
|
15
|
+
# Parses a given +string+ into a +UnitMeasurements::Length+ object.
|
16
|
+
#
|
17
|
+
# @param [String] string The string to parse for length measurement.
|
18
|
+
# @return [UnitMeasurements::Length]
|
19
|
+
# Returns a UnitMeasurements::Length object if parsing is successful.
|
20
|
+
#
|
21
|
+
# @raise [UnitMeasurements::ParseError]
|
22
|
+
# If the string does not match any known format.
|
23
|
+
#
|
24
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
25
|
+
# @since 0.2.0
|
26
|
+
def parse(string)
|
27
|
+
case string
|
28
|
+
when FOOT_INCH then parse_foot_inch(string)
|
29
|
+
when KILOMETRE_METRE then parse_kilometre_metre(string)
|
30
|
+
when METRE_CENTIMETRE then parse_metre_centimetre(string)
|
31
|
+
else raise UnitMeasurements::ParseError, string
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# @private
|
38
|
+
# Parses a +string+ representing a length in the format of +foot-inch+.
|
39
|
+
#
|
40
|
+
# @param [String] string
|
41
|
+
# The string representing length measurement in the format of *foot-inch*.
|
42
|
+
# @return [UnitMeasurements::Length]
|
43
|
+
# Returns a UnitMeasurements::Length object if parsing is successful.
|
44
|
+
#
|
45
|
+
# @see FOOT_INCH
|
46
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
47
|
+
# @since 0.2.0
|
48
|
+
def parse_foot_inch(string)
|
49
|
+
foot, inch = string.match(FOOT_INCH)&.captures
|
50
|
+
|
51
|
+
if foot && inch
|
52
|
+
UnitMeasurements::Length.new(foot, "ft") + UnitMeasurements::Length.new(inch, "in")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# @private
|
57
|
+
# Parses a +string+ representing a length in the format of +metre-centimetre+.
|
58
|
+
#
|
59
|
+
# @param [String] string
|
60
|
+
# The string representing length measurement in the format of *metre-centimetre*.
|
61
|
+
# @return [UnitMeasurements::Length]
|
62
|
+
# Returns a UnitMeasurements::Length object if parsing is successful.
|
63
|
+
#
|
64
|
+
# @see METRE_CENTIMETRE
|
65
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
66
|
+
# @since 0.3.0
|
67
|
+
def parse_metre_centimetre(string)
|
68
|
+
metre, centimetre = string.match(METRE_CENTIMETRE)&.captures
|
69
|
+
|
70
|
+
if metre && centimetre
|
71
|
+
UnitMeasurements::Length.new(metre, "m") + UnitMeasurements::Length.new(centimetre, "cm")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @private
|
76
|
+
# Parses a +string+ representing a length in the format of +kilometre-metre+.
|
77
|
+
#
|
78
|
+
# @param [String] string
|
79
|
+
# The string representing length measurement in the format of *kilometre-metre*.
|
80
|
+
# @return [UnitMeasurements::Length]
|
81
|
+
# Returns a UnitMeasurements::Length object if parsing is successful.
|
82
|
+
#
|
83
|
+
# @see KILOMETRE_METRE
|
84
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
85
|
+
# @since 0.3.0
|
86
|
+
def parse_kilometre_metre(string)
|
87
|
+
kilometre, metre = string.match(KILOMETRE_METRE)&.captures
|
88
|
+
|
89
|
+
if kilometre && metre
|
90
|
+
UnitMeasurements::Length.new(kilometre, "km") + UnitMeasurements::Length.new(metre, "m")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
# Regex pattern for aliases of +foot+ unit.
|
98
|
+
#
|
99
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
100
|
+
# @since 0.2.0
|
101
|
+
FOOT_ALIASES = /(?:'|ft|foot|feet)/.freeze
|
102
|
+
|
103
|
+
# Regex pattern for aliases of +inch+ unit.
|
104
|
+
#
|
105
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
106
|
+
# @since 0.2.0
|
107
|
+
INCH_ALIASES = /(?:"|in|inch(?:es)?)/.freeze
|
108
|
+
|
109
|
+
# Regex pattern for aliases of +metre+ unit.
|
110
|
+
#
|
111
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
112
|
+
# @since 0.3.0
|
113
|
+
METRE_ALIASES = /(?:m|meter(?:s)?|metre(?:s)?)/.freeze
|
114
|
+
|
115
|
+
# Regex pattern for aliases of +centimetre+ unit.
|
116
|
+
#
|
117
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
118
|
+
# @since 0.3.0
|
119
|
+
CENTIMETRE_ALIASES = /(?:cm|centimeter(?:s)?|centimetre(?:s)?)/.freeze
|
120
|
+
|
121
|
+
# Regex pattern for aliases of +kilometre+ unit.
|
122
|
+
#
|
123
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
124
|
+
# @since 0.3.0
|
125
|
+
KILOMETRE_ALIASES = /(?:km|kilometer(?:s)?|kilometre(?:s)?)/.freeze
|
126
|
+
|
127
|
+
# Regex pattern for parsing a length measurement in the format of +foot-inch+.
|
128
|
+
#
|
129
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
130
|
+
# @since 0.2.0
|
131
|
+
FOOT_INCH = /\A#{ANY_NUMBER}\s*#{FOOT_ALIASES}\s*#{ANY_NUMBER}\s*#{INCH_ALIASES}\z/.freeze
|
132
|
+
|
133
|
+
# Regex pattern for parsing a length measurement in the format of +metre-centimetre+.
|
134
|
+
#
|
135
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
136
|
+
# @since 0.3.0
|
137
|
+
METRE_CENTIMETRE = /\A#{ANY_NUMBER}\s*#{METRE_ALIASES}\s*#{ANY_NUMBER}\s*#{CENTIMETRE_ALIASES}\z/.freeze
|
138
|
+
|
139
|
+
# Regex pattern for parsing a length measurement in the format of +kilometre-metre+.
|
140
|
+
#
|
141
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
142
|
+
# @since 0.3.0
|
143
|
+
KILOMETRE_METRE = /\A#{ANY_NUMBER}\s*#{KILOMETRE_ALIASES}\s*#{ANY_NUMBER}\s*#{METRE_ALIASES}\z/.freeze
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# -*- frozen_string_literal: true -*-
|
3
|
+
# -*- warn_indent: true -*-
|
4
|
+
|
5
|
+
require "unit_measurements/unit_groups/time"
|
6
|
+
|
7
|
+
module CompositeUnitMeasurements
|
8
|
+
# A parser handling +time+ measurements, particularly for composite units
|
9
|
+
# like +hour:minute:second,microsecond+, +minute-second+, +hour-minute+, etc.
|
10
|
+
#
|
11
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
12
|
+
# @since 0.2.0
|
13
|
+
class Time
|
14
|
+
class << self
|
15
|
+
# Parses a given +string+ into a +UnitMeasurements::Time+ object.
|
16
|
+
#
|
17
|
+
# @param [String] string The string to parse for time measurement.
|
18
|
+
# @return [UnitMeasurements::Time]
|
19
|
+
# Returns a UnitMeasurements::Time object if parsing is successful.
|
20
|
+
# @raise [UnitMeasurements::ParseError]
|
21
|
+
# If the string does not match any known format.
|
22
|
+
#
|
23
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
24
|
+
# @since 0.2.0
|
25
|
+
def parse(string)
|
26
|
+
case string
|
27
|
+
when HOUR_MINUTE then parse_hour_minute(string)
|
28
|
+
when DURATION then parse_duration(string)
|
29
|
+
else raise UnitMeasurements::ParseError, string
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# @private
|
36
|
+
# Parses a +string+ representing a time in the format of +hour-minute+.
|
37
|
+
#
|
38
|
+
# @param [String] string
|
39
|
+
# The string representing time measurement in the format of *hour-minute*.
|
40
|
+
# @return [UnitMeasurements::Time]
|
41
|
+
# Returns a UnitMeasurements::Time object if parsing is successful.
|
42
|
+
#
|
43
|
+
# @see HOUR_MINUTE
|
44
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
45
|
+
# @since 0.3.0
|
46
|
+
def parse_hour_minute(string)
|
47
|
+
hour, minute = string.match(HOUR_MINUTE)&.captures
|
48
|
+
|
49
|
+
if hour && minute
|
50
|
+
UnitMeasurements::Time.new(hour, "h") + UnitMeasurements::Time.new(minute, "min")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# @private
|
55
|
+
# Parses a +string+ representing time duration in the format of
|
56
|
+
# +hour:minute:second,microsecond+ or +hour:minute:second+.
|
57
|
+
#
|
58
|
+
# @param [String] string The string representing time duration.
|
59
|
+
# @return [UnitMeasurements::Time]
|
60
|
+
# Returns a UnitMeasurements::Time object if parsing is successful.
|
61
|
+
# @raise [ArgumentError]
|
62
|
+
# Raises an ArgumentError for an invalid duration format.
|
63
|
+
#
|
64
|
+
# @see DURATION
|
65
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
66
|
+
# @since 0.2.0
|
67
|
+
def parse_duration(string)
|
68
|
+
hour, minute, second, microsecond = string.match(DURATION)&.captures
|
69
|
+
raise ArgumentError, "Invalid Duration" if [hour, minute, second, microsecond].all?(&:nil?)
|
70
|
+
|
71
|
+
UnitMeasurements::Time.new((hour || 0), :h) +
|
72
|
+
UnitMeasurements::Time.new((minute || 0), :min) +
|
73
|
+
UnitMeasurements::Time.new((second || 0), :s) +
|
74
|
+
UnitMeasurements::Time.new((microsecond || 0), :μs)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# Regex pattern for aliases of +hour+ unit.
|
81
|
+
#
|
82
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
83
|
+
# @since 0.3.0
|
84
|
+
HOUR_ALIASES = /(?:h|hr|hour(?:s)?)/.freeze
|
85
|
+
|
86
|
+
# Regex pattern for aliases of +minute+ unit.
|
87
|
+
#
|
88
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
89
|
+
# @since 0.3.0
|
90
|
+
MINUTE_ALIASES = /(?:min|minute(?:s)?)/.freeze
|
91
|
+
|
92
|
+
# Regex pattern for parsing a time measurement in the format of +hour-minute+.
|
93
|
+
#
|
94
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
95
|
+
# @since 0.3.0
|
96
|
+
HOUR_MINUTE = /\A#{ANY_NUMBER}\s*#{HOUR_ALIASES}\s*#{ANY_NUMBER}\s*#{MINUTE_ALIASES}\z/.freeze
|
97
|
+
|
98
|
+
# Regex pattern for parsing duration in the format of +hour:minute:second+ or
|
99
|
+
# +hour:minute:second,microsecond+.
|
100
|
+
#
|
101
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
102
|
+
# @since 0.2.0
|
103
|
+
DURATION = /\A(?<hour>#{REAL_NUMBER}):(?<min>#{REAL_NUMBER}):(?:(?<sec>#{REAL_NUMBER}))?(?:,(?<msec>#{REAL_NUMBER}))?\z/.freeze
|
104
|
+
end
|
105
|
+
end
|
@@ -2,6 +2,28 @@
|
|
2
2
|
# -*- frozen_string_literal: true -*-
|
3
3
|
# -*- warn_indent: true -*-
|
4
4
|
|
5
|
+
# This module provides parsers and utilities for handling composite unit measurements.
|
6
|
+
# It allows parsing and manipulation of various composite measurements for units of
|
7
|
+
# +length+, +weight+, +time+ etc.
|
8
|
+
#
|
9
|
+
# @note
|
10
|
+
# This module serves as a namespace for classes and utilities related to composite
|
11
|
+
# unit measurements. To parse such measurements, refer to individual classes like
|
12
|
+
# {Length}, {Weight}, {Time}, etc. within this module.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# CompositeUnitMeasurements::Length.parse("5 feet 12 inches")
|
16
|
+
# => 6.0 ft
|
17
|
+
#
|
18
|
+
# CompositeUnitMeasurements::Weight.parse("8 lb 12 oz")
|
19
|
+
# => 8.75 lb
|
20
|
+
#
|
21
|
+
# CompositeUnitMeasurements::Time.parse("3 h 45 min")
|
22
|
+
# => 3.75 h
|
23
|
+
#
|
24
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
25
|
+
# @since 0.1.0
|
5
26
|
module CompositeUnitMeasurements
|
6
|
-
|
27
|
+
# Current stable version
|
28
|
+
VERSION = "0.3.0"
|
7
29
|
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# -*- frozen_string_literal: true -*-
|
3
|
+
# -*- warn_indent: true -*-
|
4
|
+
|
5
|
+
require "unit_measurements/unit_groups/weight"
|
6
|
+
|
7
|
+
module CompositeUnitMeasurements
|
8
|
+
# A parser handling +weight+ measurements, particularly for composite units
|
9
|
+
# like +pound-ounce+, +stone-pound+, +kilogramme-gramme+, etc.
|
10
|
+
#
|
11
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
12
|
+
# @since 0.2.0
|
13
|
+
class Weight
|
14
|
+
class << self
|
15
|
+
# Parses a given +string+ into a +UnitMeasurements::Weight+ object.
|
16
|
+
#
|
17
|
+
# @param [String] string The string to parse for weight measurement.
|
18
|
+
# @return [UnitMeasurements::Weight]
|
19
|
+
# Returns a UnitMeasurements::Weight object if parsing is successful.
|
20
|
+
# @raise [UnitMeasurements::ParseError]
|
21
|
+
# If the string does not match any known format.
|
22
|
+
#
|
23
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
24
|
+
# @since 0.2.0
|
25
|
+
def parse(string)
|
26
|
+
case string
|
27
|
+
when POUND_OUNCE then parse_pound_ounce(string)
|
28
|
+
when STONE_POUND then parse_stone_pound(string)
|
29
|
+
when KILOGRAMME_GRAMME then parse_kilogramme_gramme(string)
|
30
|
+
else raise UnitMeasurements::ParseError, string
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# @private
|
37
|
+
# Parses a +string+ representing a weight in the format of +pound-ounce+.
|
38
|
+
#
|
39
|
+
# @param [String] string
|
40
|
+
# The string representing weight measurement in the format of *pound-ounce*.
|
41
|
+
# @return [UnitMeasurements::Weight]
|
42
|
+
# Returns a UnitMeasurements::Weight object if parsing is successful.
|
43
|
+
#
|
44
|
+
# @see POUND_OUNCE
|
45
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
46
|
+
# @since 0.2.0
|
47
|
+
def parse_pound_ounce(string)
|
48
|
+
pound, ounce = string.match(POUND_OUNCE)&.captures
|
49
|
+
|
50
|
+
if pound && ounce
|
51
|
+
UnitMeasurements::Weight.new(pound, "lb") + UnitMeasurements::Weight.new(ounce, "oz")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# @private
|
56
|
+
# Parses a +string+ representing a weight in the format of +stone-pound+.
|
57
|
+
#
|
58
|
+
# @param [String] string
|
59
|
+
# The string representing weight measurement in the format of *stone-pound*.
|
60
|
+
# @return [UnitMeasurements::Weight]
|
61
|
+
# Returns a UnitMeasurements::Weight object if parsing is successful.
|
62
|
+
#
|
63
|
+
# @see STONE_POUND
|
64
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
65
|
+
# @since 0.2.0
|
66
|
+
def parse_stone_pound(string)
|
67
|
+
stone, pound = string.match(STONE_POUND)&.captures
|
68
|
+
|
69
|
+
if stone && pound
|
70
|
+
UnitMeasurements::Weight.new(stone, "st") + UnitMeasurements::Weight.new(pound, "lb")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# @private
|
75
|
+
# Parses a +string+ representing a weight in the format of +kilogramme-gramme+.
|
76
|
+
#
|
77
|
+
# @param [String] string
|
78
|
+
# The string representing weight measurement in the format of *kilogramme-gramme*.
|
79
|
+
# @return [UnitMeasurements::Weight]
|
80
|
+
# Returns a UnitMeasurements::Weight object if parsing is successful.
|
81
|
+
#
|
82
|
+
# @see KILOGRAMME_GRAMME
|
83
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
84
|
+
# @since 0.3.0
|
85
|
+
def parse_kilogramme_gramme(string)
|
86
|
+
kilogramme, gramme = string.match(KILOGRAMME_GRAMME)&.captures
|
87
|
+
|
88
|
+
if kilogramme && gramme
|
89
|
+
UnitMeasurements::Weight.new(kilogramme, "kg") + UnitMeasurements::Weight.new(gramme, "g")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
# Regex pattern for aliases of +pound+ unit.
|
97
|
+
#
|
98
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
99
|
+
# @since 0.2.0
|
100
|
+
POUND_ALIASES = /(?:#|lb|lbs|lbm|pound-mass|pound(?:s)?)/.freeze
|
101
|
+
|
102
|
+
# Regex pattern for aliases of +ounce+ unit.
|
103
|
+
#
|
104
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
105
|
+
# @since 0.2.0
|
106
|
+
OUNCE_ALIASES = /(?:oz|ounce(?:s)?)/.freeze
|
107
|
+
|
108
|
+
# Regex pattern for aliases of +stone+ unit.
|
109
|
+
#
|
110
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
111
|
+
# @since 0.2.0
|
112
|
+
STONE_ALIASES = /(?:st|stone(?:s)?)/.freeze
|
113
|
+
|
114
|
+
# Regex pattern for aliases of +gramme+ unit.
|
115
|
+
#
|
116
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
117
|
+
# @since 0.3.0
|
118
|
+
GRAMME_ALIASES = /(?:g|gram(?:s)?|gramme(?:s)?)/.freeze
|
119
|
+
|
120
|
+
# Regex pattern for aliases of +kilogramme+ unit.
|
121
|
+
#
|
122
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
123
|
+
# @since 0.3.0
|
124
|
+
KILOGRAMME_ALIASES = /(?:kg|kilogram(?:s)?|kilogramme(?:s)?)/.freeze
|
125
|
+
|
126
|
+
# Regex pattern for parsing a weight measurement in the format of +pound-ounce+.
|
127
|
+
#
|
128
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
129
|
+
# @since 0.2.0
|
130
|
+
POUND_OUNCE = /\A#{ANY_NUMBER}\s*#{POUND_ALIASES}\s*#{ANY_NUMBER}\s*#{OUNCE_ALIASES}\z/.freeze
|
131
|
+
|
132
|
+
# Regex pattern for parsing a weight measurement in the format of +stone-pound+.
|
133
|
+
#
|
134
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
135
|
+
# @since 0.2.0
|
136
|
+
STONE_POUND = /\A#{ANY_NUMBER}\s*#{STONE_ALIASES}\s*#{ANY_NUMBER}\s*#{POUND_ALIASES}\z/.freeze
|
137
|
+
|
138
|
+
# Regex pattern for parsing a weight measurement in the format of +kilogramme-gramme+.
|
139
|
+
#
|
140
|
+
# @author {Harshal V. Ladhe}[https://shivam091.github.io/]
|
141
|
+
# @since 0.3.0
|
142
|
+
KILOGRAMME_GRAMME = /\A#{ANY_NUMBER}\s*#{KILOGRAMME_ALIASES}\s*#{ANY_NUMBER}\s*#{GRAMME_ALIASES}\z/.freeze
|
143
|
+
end
|
144
|
+
end
|
@@ -2,8 +2,8 @@
|
|
2
2
|
# -*- frozen_string_literal: true -*-
|
3
3
|
# -*- warn_indent: true -*-
|
4
4
|
|
5
|
-
require "composite_unit_measurements/
|
5
|
+
require "composite_unit_measurements/base"
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
require "composite_unit_measurements/length"
|
8
|
+
require "composite_unit_measurements/time"
|
9
|
+
require "composite_unit_measurements/weight"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: composite_unit_measurements
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.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-11-
|
11
|
+
date: 2023-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -121,7 +121,10 @@ files:
|
|
121
121
|
- composite_unit_measurements.gemspec
|
122
122
|
- lib/composite_unit_measurements.rb
|
123
123
|
- lib/composite_unit_measurements/base.rb
|
124
|
+
- lib/composite_unit_measurements/length.rb
|
125
|
+
- lib/composite_unit_measurements/time.rb
|
124
126
|
- lib/composite_unit_measurements/version.rb
|
127
|
+
- lib/composite_unit_measurements/weight.rb
|
125
128
|
homepage: https://github.com/shivam091/composite_unit_measurements
|
126
129
|
licenses:
|
127
130
|
- MIT
|