composite_unit_measurements 0.1.0 → 0.3.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: 7e212c20da9787a853fef2791d5f95d0004e5e45225c3809088205a1375b600c
4
- data.tar.gz: 8b2c03cfdfba50cc0e13088bbfb8910afd249b98ec4048280441131f47a310f5
3
+ metadata.gz: cd67813e0e00bce4c907e7076ec4a62994570585875da38dfa72bc968b3c0c20
4
+ data.tar.gz: c9de7ccfd6e0ede94d8cd5976174a1a60ed4f4cf3566bc613349a211ea9e4309
5
5
  SHA512:
6
- metadata.gz: c1a6c264037d7db78d70676137d60a1085bb7126034674c6156de7806ef9c76263a8acd8bd4125fa3655d1c6c64c1ccec3bdd04d004dcc93dbd0e4ad6e056c86
7
- data.tar.gz: 394309d1a68c9eed5548f446fe3816ae467c7f2f6c4e66428d9957ae1ca5ed376659e4c7ff4fe1adc731cee85a8ea340577d120c65038b312398cf8f10dde6af
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.1.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.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.8.0)
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 set of specialized parsers for dealing with composite measurement strings.
3
+ A collection of specialized parsers designed for handling composite measurement strings.
4
4
 
5
5
  [![Ruby](https://github.com/shivam091/composite_unit_measurements/actions/workflows/main.yml/badge.svg)](https://github.com/shivam091/composite_unit_measurements/actions/workflows/main.yml)
6
6
  [![Gem Version](https://badge.fury.io/rb/composite_unit_measurements.svg)](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 is a versatile solution tailored for parsing
17
- composite measurement strings. By harnessing the capabilities of the `unit_measurements`
18
- gem, it empowers you to seamlessly handle composite measurements in various units.
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
- If using bundler, first add this line to your application's Gemfile:
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
- 1. Fork it
43
- 2. Create your feature branch (`git checkout -b my-new-feature`)
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 the branch (`git push origin my-new-feature`)
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
- VERSION = "0.1.0"
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/version"
5
+ require "composite_unit_measurements/base"
6
6
 
7
- module CompositeUnitMeasurements
8
- class Error < StandardError; end
9
- end
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.1.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-09 00:00:00.000000000 Z
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