monetize 2.0.0 → 2.0.1
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 +3 -0
- data/README.md +3 -3
- data/lib/monetize/parser.rb +53 -44
- data/lib/monetize/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 027fe3fe8fd8bf031ee1eeca954ccd33d64b09f7c1d611beef48758640f79ece
|
|
4
|
+
data.tar.gz: 252c3d7a5f4f922d0385ca6b7b10dffdbcf358a896afc5ba4a621298c966ae39
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 29bc1cef3e339731a0aa98f8d5198c81207f063c925650c5f42b8e23830f22dd1c35268b53d6f5296bfb0a15d59bbb08bc1b914967abc0eeda3282f7e0dcd8d4
|
|
7
|
+
data.tar.gz: af197d3990bc1a5488140912c7e5b39a9140a0bdf0247540ea3c9ef697044f20b8b9eab8691469bacf313a36e5ee3793c6c332e9353bf3cb676f98ba88bc1d8d
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 2.0.1
|
|
6
|
+
- Fix parsing of ISO codes not in `Monetize::Parser::CURRENCY_SYMBOLS`. `Monetize.parse('20.00 DKK')` returned 20.00 in the default currency instead of 20.00 DKK.
|
|
7
|
+
|
|
5
8
|
## 2.0.0
|
|
6
9
|
- **Breaking change**: Remove deprecated `Monetize.extract_cents`.
|
|
7
10
|
- **Breaking change**: Update Money gem dependency to ~> 7.0. See the [Money 7.0 upgrading guide](https://github.com/RubyMoney/money/blob/main/UPGRADING-7.0.md)
|
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Monetize
|
|
2
2
|
|
|
3
|
-
[](
|
|
3
|
+
[](https://rubygems.org/gems/monetize)
|
|
4
4
|
[](https://github.com/RubyMoney/monetize/actions/workflows/ruby.yml)
|
|
5
|
-
[](
|
|
5
|
+
[](https://opensource.org/license/MIT)
|
|
6
6
|
|
|
7
7
|
A library for converting various objects into `Money` objects.
|
|
8
8
|
|
|
@@ -53,7 +53,7 @@ this is not the case - a European site will show $10.000 because that's the loca
|
|
|
53
53
|
As a human, if this was a stock ticker we might expect fractional cents. If it's a retail price we know it's actually an incorrect thousands separator.
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
Monetize can also parse a list of values, returning an array-like object ([Monetize::Collection](lib/collection.rb)):
|
|
56
|
+
Monetize can also parse a list of values, returning an array-like object ([Monetize::Collection](lib/monetize/collection.rb)):
|
|
57
57
|
|
|
58
58
|
```ruby
|
|
59
59
|
Monetize.parse_collection("€80/$100") == [Money.new(80_00, "EUR"), Money.new(100_00, "USD")]
|
data/lib/monetize/parser.rb
CHANGED
|
@@ -35,6 +35,8 @@ module Monetize
|
|
|
35
35
|
MULTIPLIER_REGEXP = Regexp.new(format('^(.*?\d)(%s)\b([^\d]*)$', MULTIPLIER_SUFFIXES.keys.join('|')), 'i')
|
|
36
36
|
|
|
37
37
|
DEFAULT_DECIMAL_MARK = '.'.freeze
|
|
38
|
+
DEFAULT_MINOR = "00".freeze
|
|
39
|
+
private_constant :DEFAULT_MINOR
|
|
38
40
|
|
|
39
41
|
def initialize(input, fallback_currency = Money.default_currency, options = {})
|
|
40
42
|
@input = input.to_s.strip
|
|
@@ -43,19 +45,13 @@ module Monetize
|
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
def parse
|
|
46
|
-
currency = Money::Currency.wrap(parse_currency)
|
|
47
|
-
|
|
48
48
|
multiplier_exp, input = extract_multiplier
|
|
49
49
|
|
|
50
50
|
num = input.gsub(/(?:^#{currency.symbol}|[^\d.,'-]+)/, '')
|
|
51
51
|
|
|
52
52
|
negative, num = extract_sign(num)
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
major, minor = extract_major_minor(num, currency)
|
|
57
|
-
|
|
58
|
-
amount = to_big_decimal([major, minor].join(DEFAULT_DECIMAL_MARK))
|
|
54
|
+
amount = to_big_decimal(normalize_number(num))
|
|
59
55
|
amount = apply_multiplier(multiplier_exp, amount)
|
|
60
56
|
amount = apply_sign(negative, amount)
|
|
61
57
|
|
|
@@ -64,6 +60,12 @@ module Monetize
|
|
|
64
60
|
|
|
65
61
|
private
|
|
66
62
|
|
|
63
|
+
def normalize_number(num)
|
|
64
|
+
clean_num = num.sub(/[\.|,]$/, "")
|
|
65
|
+
|
|
66
|
+
extract_major_minor(clean_num).join(DEFAULT_DECIMAL_MARK)
|
|
67
|
+
end
|
|
68
|
+
|
|
67
69
|
def to_big_decimal(value)
|
|
68
70
|
BigDecimal(value)
|
|
69
71
|
rescue ::ArgumentError => err
|
|
@@ -72,10 +74,14 @@ module Monetize
|
|
|
72
74
|
|
|
73
75
|
attr_reader :input, :fallback_currency, :options
|
|
74
76
|
|
|
77
|
+
def currency
|
|
78
|
+
@currency ||= Money::Currency.wrap(parse_currency)
|
|
79
|
+
end
|
|
80
|
+
|
|
75
81
|
def parse_currency
|
|
76
82
|
computed_currency = nil
|
|
77
83
|
computed_currency = input[/[A-Z]{2,3}/]
|
|
78
|
-
computed_currency = nil unless
|
|
84
|
+
computed_currency = nil unless Money::Currency.find(computed_currency)
|
|
79
85
|
computed_currency ||= compute_currency if assume_from_symbol?
|
|
80
86
|
|
|
81
87
|
found = computed_currency || fallback_currency || Money.default_currency
|
|
@@ -104,64 +110,65 @@ module Monetize
|
|
|
104
110
|
CURRENCY_SYMBOLS[match.to_s] if match
|
|
105
111
|
end
|
|
106
112
|
|
|
107
|
-
def
|
|
113
|
+
def remove_separator(num, separator)
|
|
114
|
+
num.gsub(separator, "")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def extract_major_minor(num)
|
|
108
118
|
used_delimiters = num.scan(/[^\d]/).uniq
|
|
109
119
|
|
|
110
120
|
case used_delimiters.length
|
|
111
121
|
when 0
|
|
112
|
-
[num,
|
|
122
|
+
[num, DEFAULT_MINOR]
|
|
123
|
+
when 1
|
|
124
|
+
extract_major_minor_with_single_delimiter(num, used_delimiters.first)
|
|
113
125
|
when 2
|
|
114
126
|
thousands_separator, decimal_mark = used_delimiters
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
127
|
+
num = remove_separator(num, thousands_separator)
|
|
128
|
+
|
|
129
|
+
split_major_minor(num, decimal_mark)
|
|
118
130
|
else
|
|
119
131
|
fail ParseError, 'Invalid amount'
|
|
120
132
|
end
|
|
121
133
|
end
|
|
122
134
|
|
|
123
|
-
def
|
|
124
|
-
minor.length == currency.
|
|
135
|
+
def minor_has_correct_decimal_places_for_currency?(minor)
|
|
136
|
+
minor.length == currency.decimal_places
|
|
125
137
|
end
|
|
126
138
|
|
|
127
|
-
def extract_major_minor_with_single_delimiter(num,
|
|
139
|
+
def extract_major_minor_with_single_delimiter(num, delimiter)
|
|
128
140
|
if expect_whole_subunits?
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
extract_major_minor_with_tentative_delimiter(num, delimiter)
|
|
134
|
-
end
|
|
135
|
-
else
|
|
136
|
-
if delimiter == currency.decimal_mark
|
|
137
|
-
split_major_minor(num, delimiter)
|
|
138
|
-
elsif Monetize.enforce_currency_delimiters && delimiter == currency.thousands_separator
|
|
139
|
-
[num.gsub(delimiter, ''), 0]
|
|
140
|
-
else
|
|
141
|
-
extract_major_minor_with_tentative_delimiter(num, delimiter)
|
|
141
|
+
possible_major, possible_minor = split_major_minor(num, delimiter)
|
|
142
|
+
|
|
143
|
+
if minor_has_correct_decimal_places_for_currency?(possible_minor)
|
|
144
|
+
return [possible_major, possible_minor]
|
|
142
145
|
end
|
|
146
|
+
elsif delimiter == currency.decimal_mark
|
|
147
|
+
return split_major_minor(num, delimiter)
|
|
148
|
+
elsif Monetize.enforce_currency_delimiters && delimiter == currency.thousands_separator
|
|
149
|
+
return [remove_separator(num, delimiter), DEFAULT_MINOR]
|
|
143
150
|
end
|
|
151
|
+
|
|
152
|
+
extract_major_minor_with_tentative_delimiter(num, delimiter)
|
|
144
153
|
end
|
|
145
154
|
|
|
146
155
|
def extract_major_minor_with_tentative_delimiter(num, delimiter)
|
|
147
156
|
if num.scan(delimiter).length > 1
|
|
148
157
|
# Multiple matches; treat as thousands separator
|
|
149
|
-
[num
|
|
150
|
-
|
|
151
|
-
possible_major, possible_minor = split_major_minor(num, delimiter)
|
|
158
|
+
return [remove_separator(num, delimiter), DEFAULT_MINOR]
|
|
159
|
+
end
|
|
152
160
|
|
|
153
|
-
|
|
154
|
-
is_decimal_mark = possible_minor.length != 3 ||
|
|
155
|
-
possible_major.length > 3 ||
|
|
156
|
-
possible_major.to_i == 0 ||
|
|
157
|
-
(!expect_whole_subunits? && delimiter == '.')
|
|
161
|
+
possible_major, possible_minor = split_major_minor(num, delimiter)
|
|
158
162
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
# Doesn't look like thousands separator
|
|
164
|
+
is_decimal_mark = possible_minor.length != 3 ||
|
|
165
|
+
possible_major.length > 3 ||
|
|
166
|
+
possible_major.to_i == 0 ||
|
|
167
|
+
(!expect_whole_subunits? && delimiter == ".")
|
|
168
|
+
|
|
169
|
+
return [possible_major, possible_minor] if is_decimal_mark
|
|
170
|
+
|
|
171
|
+
["#{possible_major}#{possible_minor}", DEFAULT_MINOR]
|
|
165
172
|
end
|
|
166
173
|
|
|
167
174
|
def extract_multiplier
|
|
@@ -183,7 +190,9 @@ module Monetize
|
|
|
183
190
|
splits = num.split(delimiter)
|
|
184
191
|
fail ParseError, 'Invalid amount (multiple delimiters)' if splits.length > 2
|
|
185
192
|
|
|
186
|
-
|
|
193
|
+
splits[1] ||= DEFAULT_MINOR
|
|
194
|
+
|
|
195
|
+
splits
|
|
187
196
|
end
|
|
188
197
|
end
|
|
189
198
|
end
|
data/lib/monetize/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: monetize
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shane Emmons
|
|
@@ -69,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
69
69
|
- !ruby/object:Gem::Version
|
|
70
70
|
version: '0'
|
|
71
71
|
requirements: []
|
|
72
|
-
rubygems_version: 4.0.
|
|
72
|
+
rubygems_version: 4.0.17
|
|
73
73
|
specification_version: 4
|
|
74
74
|
summary: A library for converting various objects into `Money` objects.
|
|
75
75
|
test_files: []
|