minting 1.0.1 → 1.1.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/LICENSE +21 -0
- data/README.md +41 -1
- data/Rakefile +8 -1
- data/lib/minting/data/currencies.yaml +711 -0
- data/lib/minting/mint/currency.rb +9 -8
- data/lib/minting/mint/registry.rb +73 -138
- data/lib/minting/money/allocation.rb +24 -5
- data/lib/minting/money/arithmetics.rb +37 -2
- data/lib/minting/money/coercion.rb +14 -3
- data/lib/minting/money/comparable.rb +13 -16
- data/lib/minting/money/conversion.rb +30 -2
- data/lib/minting/money/formatting.rb +5 -4
- data/lib/minting/money/money.rb +24 -15
- data/lib/minting/money/parse.rb +82 -0
- data/lib/minting/money.rb +1 -0
- data/lib/minting/version.rb +3 -1
- data/minting.gemspec +1 -1
- metadata +5 -2
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module Mint
|
|
2
|
+
# nodoc
|
|
3
|
+
class Money
|
|
4
|
+
# Parses a human-readable money string into a {Money} object.
|
|
5
|
+
#
|
|
6
|
+
# @param input [String] Amount input, optionally including a currency symbol or code
|
|
7
|
+
# @param currency [String, Symbol, Currency, nil] ISO code when not present in +input+
|
|
8
|
+
# @return [Money]
|
|
9
|
+
# @raise [ArgumentError] when +input+ is invalid or currency cannot be determined
|
|
10
|
+
#
|
|
11
|
+
# @example With explicit currency
|
|
12
|
+
# Money.parse('19.99', 'USD') #=> [USD 19.99]
|
|
13
|
+
# Money.parse('1.234,56', 'EUR') #=> [EUR 1234.56]
|
|
14
|
+
#
|
|
15
|
+
# @example With symbol or code in the string
|
|
16
|
+
# Money.parse('$19.99') #=> [USD 19.99]
|
|
17
|
+
# Money.parse('19,99 €') #=> [EUR 19.99]
|
|
18
|
+
# Money.parse('USD 1,234.56') #=> [USD 1234.56]
|
|
19
|
+
def self.parse(input, currency = nil)
|
|
20
|
+
raise ArgumentError, 'input must be a String' unless input.is_a?(String)
|
|
21
|
+
|
|
22
|
+
input = input.strip
|
|
23
|
+
raise ArgumentError, 'input cannot be empty' if input.empty?
|
|
24
|
+
|
|
25
|
+
currency = currency ? Mint.currency(currency) : parse_currency(input)
|
|
26
|
+
raise ArgumentError, "Currency [#{currency}] not registered" unless currency
|
|
27
|
+
|
|
28
|
+
amount = parse_amount(input)
|
|
29
|
+
new(amount, currency)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Extracts a numeric value from input that should only contain an amount.
|
|
33
|
+
def self.parse_amount(input)
|
|
34
|
+
# Remove any charater that is not a digit, comma or period
|
|
35
|
+
numeric = input.scan(/[\d.\-,]/).join
|
|
36
|
+
numeric = normalize_separators(numeric)
|
|
37
|
+
Rational(numeric)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Converts locale-specific decimal/thousand separators into a plain decimal string.
|
|
41
|
+
def self.normalize_separators(numeric)
|
|
42
|
+
case [numeric.count(','), numeric.count('.')]
|
|
43
|
+
in [0, 0] | [0, 1] # Nothing to normalize (e.g. "1500" or "34.21").
|
|
44
|
+
numeric
|
|
45
|
+
in [1, 0] # Only one comma: decimal (e.g. 19,99 or 1,234).
|
|
46
|
+
numeric.tr(',', '.')
|
|
47
|
+
in [c, p] if c > 1 && p > 1 # Both separators appear multiple times
|
|
48
|
+
raise ArgumentError, "could not distinguish decimal and thousand separators in '#{numeric}'"
|
|
49
|
+
in [c, p] if c > 0 && p > 0 # Commas and dots: the rightmost one is the decimal separator.
|
|
50
|
+
if numeric.rindex(',') > numeric.rindex('.')
|
|
51
|
+
numeric.delete('.').tr(',', '.')
|
|
52
|
+
else
|
|
53
|
+
numeric.delete(',')
|
|
54
|
+
end
|
|
55
|
+
else # Multiple of the same separator only (e.g. 1,234,567) — all are thousands.
|
|
56
|
+
numeric.delete(',.')
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.parse_currency(input)
|
|
61
|
+
# Prefer an explicit ISO 4217 code (e.g. "USD 1,234.56") over symbol matching.
|
|
62
|
+
code = input[/\b([A-Z]{3})\b/, 1]
|
|
63
|
+
if code
|
|
64
|
+
currency = Mint.currency(code)
|
|
65
|
+
return currency if currency
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Fall back to registered symbols, longest first (HK$ before $).
|
|
69
|
+
Mint.currency_symbols.each do |symbol, currency|
|
|
70
|
+
next if symbol.empty?
|
|
71
|
+
|
|
72
|
+
return currency if input.include?(symbol)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
raise ArgumentError,
|
|
76
|
+
'currency could not be detected; pass a currency code as the second argument'
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private_class_method :parse_amount, :normalize_separators,
|
|
80
|
+
:parse_currency
|
|
81
|
+
end
|
|
82
|
+
end
|
data/lib/minting/money.rb
CHANGED
data/lib/minting/version.rb
CHANGED
data/minting.gemspec
CHANGED
|
@@ -29,7 +29,7 @@ Gem::Specification.new do |s|
|
|
|
29
29
|
s.required_ruby_version = '>= 3.2.0'
|
|
30
30
|
|
|
31
31
|
s.files = Dir.glob('{bin,doc,lib}/**/*')
|
|
32
|
-
s.files += %w[minting.gemspec Rakefile README.md]
|
|
32
|
+
s.files += %w[minting.gemspec Rakefile README.md LICENSE]
|
|
33
33
|
|
|
34
34
|
s.bindir = 'bin'
|
|
35
35
|
s.require_paths = ['lib']
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: minting
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gilson Ferraz
|
|
@@ -15,11 +15,13 @@ executables: []
|
|
|
15
15
|
extensions: []
|
|
16
16
|
extra_rdoc_files: []
|
|
17
17
|
files:
|
|
18
|
+
- LICENSE
|
|
18
19
|
- README.md
|
|
19
20
|
- Rakefile
|
|
20
21
|
- bin/console
|
|
21
22
|
- bin/setup
|
|
22
23
|
- lib/minting.rb
|
|
24
|
+
- lib/minting/data/currencies.yaml
|
|
23
25
|
- lib/minting/mint.rb
|
|
24
26
|
- lib/minting/mint/currency.rb
|
|
25
27
|
- lib/minting/mint/refinements.rb
|
|
@@ -32,6 +34,7 @@ files:
|
|
|
32
34
|
- lib/minting/money/conversion.rb
|
|
33
35
|
- lib/minting/money/formatting.rb
|
|
34
36
|
- lib/minting/money/money.rb
|
|
37
|
+
- lib/minting/money/parse.rb
|
|
35
38
|
- lib/minting/version.rb
|
|
36
39
|
- minting.gemspec
|
|
37
40
|
homepage: https://github.com/gferraz/minting
|
|
@@ -58,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
58
61
|
- !ruby/object:Gem::Version
|
|
59
62
|
version: '0'
|
|
60
63
|
requirements: []
|
|
61
|
-
rubygems_version:
|
|
64
|
+
rubygems_version: 4.0.9
|
|
62
65
|
specification_version: 4
|
|
63
66
|
summary: Library to manipulate currency values
|
|
64
67
|
test_files: []
|