money-6.16.0/0000755000004100000410000000000014054035243012763 5ustar www-datawww-datamoney-6.16.0/README.md0000644000004100000410000004512214054035243014246 0ustar www-datawww-data# RubyMoney - Money [![Gem Version](https://badge.fury.io/rb/money.svg)](https://rubygems.org/gems/money) [![Build Status](https://travis-ci.org/RubyMoney/money.svg?branch=master)](https://travis-ci.org/RubyMoney/money) [![Code Climate](https://codeclimate.com/github/RubyMoney/money.svg)](https://codeclimate.com/github/RubyMoney/money) [![Inline docs](https://inch-ci.org/github/RubyMoney/money.svg)](https://inch-ci.org/github/RubyMoney/money) [![License](https://img.shields.io/github/license/RubyMoney/money.svg)](https://opensource.org/licenses/MIT) :warning: Please read the [migration notes](#migration-notes) before upgrading to a new major version. If you miss String parsing, check out the new [monetize gem](https://github.com/RubyMoney/monetize). ## Contributing See the [Contribution Guidelines](https://github.com/RubyMoney/money/blob/master/CONTRIBUTING.md) ## Introduction A Ruby Library for dealing with money and currency conversion. ### Features - Provides a `Money` class which encapsulates all information about a certain amount of money, such as its value and its currency. - Provides a `Money::Currency` class which encapsulates all information about a monetary unit. - Represents monetary values as integers, in cents. This avoids floating point rounding errors. - Represents currency as `Money::Currency` instances providing a high level of flexibility. - Provides APIs for exchanging money from one currency to another. ### Resources - [Website](https://rubymoney.github.io/money/) - [API Documentation](http://www.rubydoc.info/gems/money/frames) - [Git Repository](https://github.com/RubyMoney/money) ### Notes - Your app must use UTF-8 to function with this library. There are a number of non-ASCII currency attributes. - This app requires JSON. If you're using JRuby < 1.7.0 you'll need to add `gem "json"` to your Gemfile or similar. ## Downloading Install stable releases with the following command: gem install money The development version (hosted on Github) can be installed with: git clone git://github.com/RubyMoney/money.git cd money rake install ## Usage ``` ruby require 'money' # 10.00 USD money = Money.from_cents(1000, "USD") money.cents #=> 1000 money.currency #=> Currency.new("USD") # Comparisons Money.from_cents(1000, "USD") == Money.from_cents(1000, "USD") #=> true Money.from_cents(1000, "USD") == Money.from_cents(100, "USD") #=> false Money.from_cents(1000, "USD") == Money.from_cents(1000, "EUR") #=> false Money.from_cents(1000, "USD") != Money.from_cents(1000, "EUR") #=> true # Arithmetic Money.from_cents(1000, "USD") + Money.from_cents(500, "USD") == Money.from_cents(1500, "USD") Money.from_cents(1000, "USD") - Money.from_cents(200, "USD") == Money.from_cents(800, "USD") Money.from_cents(1000, "USD") / 5 == Money.from_cents(200, "USD") Money.from_cents(1000, "USD") * 5 == Money.from_cents(5000, "USD") # Unit to subunit conversions Money.from_amount(5, "USD") == Money.from_cents(500, "USD") # 5 USD Money.from_amount(5, "JPY") == Money.from_cents(5, "JPY") # 5 JPY Money.from_amount(5, "TND") == Money.from_cents(5000, "TND") # 5 TND # Currency conversions some_code_to_setup_exchange_rates Money.from_cents(1000, "USD").exchange_to("EUR") == Money.from_cents(some_value, "EUR") # Swap currency Money.from_cents(1000, "USD").with_currency("EUR") == Money.from_cents(1000, "EUR") # Formatting (see Formatting section for more options) Money.from_cents(100, "USD").format #=> "$1.00" Money.from_cents(100, "GBP").format #=> "£1.00" Money.from_cents(100, "EUR").format #=> "€1.00" ``` ## Currency Currencies are consistently represented as instances of `Money::Currency`. The most part of `Money` APIs allows you to supply either a `String` or a `Money::Currency`. ``` ruby Money.from_cents(1000, "USD") == Money.from_cents(1000, Money::Currency.new("USD")) Money.from_cents(1000, "EUR").currency == Money::Currency.new("EUR") ``` A `Money::Currency` instance holds all the information about the currency, including the currency symbol, name and much more. ``` ruby currency = Money.from_cents(1000, "USD").currency currency.iso_code #=> "USD" currency.name #=> "United States Dollar" ``` To define a new `Money::Currency` use `Money::Currency.register` as shown below. ``` ruby curr = { priority: 1, iso_code: "USD", iso_numeric: "840", name: "United States Dollar", symbol: "$", subunit: "Cent", subunit_to_unit: 100, decimal_mark: ".", thousands_separator: "," } Money::Currency.register(curr) ``` The pre-defined set of attributes includes: - `:priority` a numerical value you can use to sort/group the currency list - `:iso_code` the international 3-letter code as defined by the ISO 4217 standard - `:iso_numeric` the international 3-digit code as defined by the ISO 4217 standard - `:name` the currency name - `:symbol` the currency symbol (UTF-8 encoded) - `:subunit` the name of the fractional monetary unit - `:subunit_to_unit` the proportion between the unit and the subunit - `:decimal_mark` character between the whole and fraction amounts - `:thousands_separator` character between each thousands place All attributes except `:iso_code` are optional. Some attributes, such as `:symbol`, are used by the Money class to print out a representation of the object. Other attributes, such as `:name` or `:priority`, exist to provide a basic API you can take advantage of to build your application. ### :priority The priority attribute is an arbitrary numerical value you can assign to the `Money::Currency` and use in sorting/grouping operation. For instance, let's assume your Rails application needs to render a currency selector like the one available [here](https://finance.yahoo.com/currency-converter/). You can create a couple of custom methods to return the list of major currencies and all currencies as follows: ``` ruby # Returns an array of currency id where # priority < 10 def major_currencies(hash) hash.inject([]) do |array, (id, attributes)| priority = attributes[:priority] if priority && priority < 10 array[priority] ||= [] array[priority] << id end array end.compact.flatten end # Returns an array of all currency id def all_currencies(hash) hash.keys end major_currencies(Money::Currency.table) # => [:usd, :eur, :gbp, :aud, :cad, :jpy] all_currencies(Money::Currency.table) # => [:aed, :afn, :all, ...] ``` ### Default Currency By default `Money` defaults to USD as its currency. This can be overwritten using: ``` ruby Money.default_currency = Money::Currency.new("CAD") ``` If you use [Rails](https://github.com/RubyMoney/money/tree/master#ruby-on-rails), then `config/initializers/money.rb` is a very good place to put this. ### Currency Exponent The exponent of a money value is the number of digits after the decimal separator (which separates the major unit from the minor unit). See e.g. [ISO 4217](https://www.currency-iso.org/en/shared/amendments/iso-4217-amendment.html) for more information. You can find the exponent (as an `Integer`) by ``` ruby Money::Currency.new("USD").exponent # => 2 Money::Currency.new("JPY").exponent # => 0 Money::Currency.new("MGA").exponent # => 1 ``` ### Currency Lookup To find a given currency by ISO 4217 numeric code (three digits) you can do ``` ruby Money::Currency.find_by_iso_numeric(978) #=> Money::Currency.new(:eur) ``` ## Currency Exchange Exchanging money is performed through an exchange bank object. The default exchange bank object requires one to manually specify the exchange rate. Here's an example of how it works: ``` ruby Money.add_rate("USD", "CAD", 1.24515) Money.add_rate("CAD", "USD", 0.803115) Money.us_dollar(100).exchange_to("CAD") # => Money.from_cents(124, "CAD") Money.ca_dollar(100).exchange_to("USD") # => Money.from_cents(80, "USD") ``` Comparison and arithmetic operations work as expected: ``` ruby Money.from_cents(1000, "USD") <=> Money.from_cents(900, "USD") # => 1; 9.00 USD is smaller Money.from_cents(1000, "EUR") + Money.from_cents(10, "EUR") == Money.from_cents(1010, "EUR") Money.add_rate("USD", "EUR", 0.5) Money.from_cents(1000, "EUR") + Money.from_cents(1000, "USD") == Money.from_cents(1500, "EUR") ``` ### Exchange rate stores The default bank is initialized with an in-memory store for exchange rates. ```ruby Money.default_bank = Money::Bank::VariableExchange.new(Money::RatesStore::Memory.new) ``` You can pass your own store implementation, i.e. for storing and retrieving rates off a database, file, cache, etc. ```ruby Money.default_bank = Money::Bank::VariableExchange.new(MyCustomStore.new) ``` Stores must implement the following interface: ```ruby # Add new exchange rate. # @param [String] iso_from Currency ISO code. ex. 'USD' # @param [String] iso_to Currency ISO code. ex. 'CAD' # @param [Numeric] rate Exchange rate. ex. 0.0016 # # @return [Numeric] rate. def add_rate(iso_from, iso_to, rate); end # Get rate. Must be idempotent. i.e. adding the same rate must not produce duplicates. # @param [String] iso_from Currency ISO code. ex. 'USD' # @param [String] iso_to Currency ISO code. ex. 'CAD' # # @return [Numeric] rate. def get_rate(iso_from, iso_to); end # Iterate over rate tuples (iso_from, iso_to, rate) # # @yieldparam iso_from [String] Currency ISO string. # @yieldparam iso_to [String] Currency ISO string. # @yieldparam rate [Numeric] Exchange rate. # # @return [Enumerator] # # @example # store.each_rate do |iso_from, iso_to, rate| # puts [iso_from, iso_to, rate].join # end def each_rate(&block); end # Wrap store operations in a thread-safe transaction # (or IO or Database transaction, depending on your implementation) # # @yield [n] Block that will be wrapped in transaction. # # @example # store.transaction do # store.add_rate('USD', 'CAD', 0.9) # store.add_rate('USD', 'CLP', 0.0016) # end def transaction(&block); end # Serialize store and its content to make Marshal.dump work. # # Returns an array with store class and any arguments needed to initialize the store in the current state. # @return [Array] [class, arg1, arg2] def marshal_dump; end ``` The following example implements an `ActiveRecord` store to save exchange rates to a database. ```ruby # rails g model exchange_rate from:string to:string rate:float class ExchangeRate < ApplicationRecord def self.get_rate(from_iso_code, to_iso_code) rate = find_by(from: from_iso_code, to: to_iso_code) rate&.rate end def self.add_rate(from_iso_code, to_iso_code, rate) exrate = find_or_initialize_by(from: from_iso_code, to: to_iso_code) exrate.rate = rate exrate.save! end def self.each_rate return find_each unless block_given? find_each do |rate| yield rate.from, rate.to, rate.rate end end end ``` Now you can use it with the default bank. ```ruby # For Rails 6 pass model name as a string to make it compatible with zeitwerk # Money.default_bank = Money::Bank::VariableExchange.new("ExchangeRate") Money.default_bank = Money::Bank::VariableExchange.new(ExchangeRate) # Add to the underlying store Money.default_bank.add_rate('USD', 'CAD', 0.9) # Retrieve from the underlying store Money.default_bank.get_rate('USD', 'CAD') # => 0.9 # Exchanging amounts just works. Money.from_cents(1000, 'USD').exchange_to('CAD') #=> # ``` There is nothing stopping you from creating store objects which scrapes [XE](http://www.xe.com) for the current rates or just returns `rand(2)`: ``` ruby Money.default_bank = Money::Bank::VariableExchange.new(StoreWhichScrapesXeDotCom.new) ``` You can also implement your own Bank to calculate exchanges differently. Different banks can share Stores. ```ruby Money.default_bank = MyCustomBank.new(Money::RatesStore::Memory.new) ``` If you wish to disable automatic currency conversion to prevent arithmetic when currencies don't match: ``` ruby Money.disallow_currency_conversion! ``` ### Implementations The following is a list of Money.gem compatible currency exchange rate implementations. - [eu_central_bank](https://github.com/RubyMoney/eu_central_bank) - [google_currency](https://github.com/RubyMoney/google_currency) - [currencylayer](https://github.com/askuratovsky/currencylayer) - [nordea](https://github.com/matiaskorhonen/nordea) - [nbrb_currency](https://github.com/slbug/nbrb_currency) - [money-currencylayer-bank](https://github.com/phlegx/money-currencylayer-bank) - [money-open-exchange-rates](https://github.com/spk/money-open-exchange-rates) - [money-historical-bank](https://github.com/atwam/money-historical-bank) - [russian_central_bank](https://github.com/rmustafin/russian_central_bank) - [money-uphold-bank](https://github.com/subvisual/money-uphold-bank) ## Formatting There are several formatting rules for when `Money#format` is called. For more information, check out the [formatting module source](https://github.com/RubyMoney/money/blob/master/lib/money/money/formatter.rb), or read the latest release's [rdoc version](http://www.rubydoc.info/gems/money/Money/Formatter). If you wish to format money according to the EU's [Rules for expressing monetary units](http://publications.europa.eu/code/en/en-370303.htm#position) in either English, Irish, Latvian or Maltese: ```ruby m = Money.from_cents('123', :gbp) # => # m.format(symbol: m.currency.to_s + ' ') # => "GBP 1.23" ``` ## Rounding By default, `Money` objects are rounded to the nearest cent and the additional precision is not preserved: ```ruby Money.from_amount(2.34567).format #=> "$2.35" ``` To retain the additional precision, you will also need to set `infinite_precision` to `true`. ```ruby Money.default_infinite_precision = true Money.from_amount(2.34567).format #=> "$2.34567" ``` To round to the nearest cent (or anything more precise), you can use the `round` method. However, note that the `round` method on a `Money` object does not work the same way as a normal Ruby `Float` object. Money's `round` method accepts different arguments. The first argument to the round method is the rounding mode, while the second argument is the level of precision relative to the cent. ``` # Float 2.34567.round #=> 2 2.34567.round(2) #=> 2.35 # Money Money.default_infinite_precision = true Money.from_cents(2.34567).format #=> "$0.0234567" Money.from_cents(2.34567).round.format #=> "$0.02" Money.from_cents(2.34567).round(BigDecimal::ROUND_HALF_UP, 2).format #=> "$0.0235" ``` You can set the default rounding mode by passing one of the `BigDecimal` mode enumerables like so: ```ruby Money.rounding_mode = BigDecimal::ROUND_HALF_EVEN ``` See [BigDecimal::ROUND_MODE](https://ruby-doc.org/stdlib-2.5.1/libdoc/bigdecimal/rdoc/BigDecimal.html#ROUND_MODE) for more information ## Ruby on Rails To integrate money in a Rails application use [money-rails](https://github.com/RubyMoney/money-rails). For deprecated methods of integrating with Rails, check [the wiki](https://github.com/RubyMoney/money/wiki). ## Localization In order to localize formatting you can use `I18n` gem: ```ruby Money.locale_backend = :i18n ``` With this enabled a thousands seperator and a decimal mark will get looked up in your `I18n` translation files. In a Rails application this may look like: ```yml # config/locale/en.yml en: number: currency: format: delimiter: "," separator: "." # falling back to number: format: delimiter: "," separator: "." ``` For this example `Money.from_cents(123456789, "SEK").format` will return `1,234,567.89 kr` which otherwise would have returned `1 234 567,89 kr`. This will work seamlessly with [rails-i18n](https://github.com/svenfuchs/rails-i18n) gem that already has a lot of locales defined. If you wish to disable this feature and use defaults instead: ``` ruby Money.locale_backend = nil ``` ### Deprecation The current default behaviour always checks the I18n locale first, falling back to "per currency" localization. This is now deprecated and will be removed in favour of explicitly defined behaviour in the next major release. If you would like to use I18n localization (formatting depends on the locale): ```ruby Money.locale_backend = :i18n # example (using default localization from rails-i18n): I18n.locale = :en Money.from_cents(10_000_00, 'USD').format # => $10,000.00 Money.from_cents(10_000_00, 'EUR').format # => €10,000.00 I18n.locale = :es Money.from_cents(10_000_00, 'USD').format # => $10.000,00 Money.from_cents(10_000_00, 'EUR').format # => €10.000,00 ``` If you need to localize the position of the currency symbol, you have to pass it manually. *Note: this will become the default formatting behavior in the next version.* ```ruby I18n.locale = :fr format = I18n.t :format, scope: 'number.currency.format' Money.from_cents(10_00, 'EUR').format(format: format) # => 10,00 € ``` For the legacy behaviour of "per currency" localization (formatting depends only on currency): ```ruby Money.locale_backend = :currency # example: Money.from_cents(10_000_00, 'USD').format # => $10,000.00 Money.from_cents(10_000_00, 'EUR').format # => €10.000,00 ``` In case you don't need localization and would like to use default values (can be redefined using `Money.default_formatting_rules`): ```ruby Money.locale_backend = nil # example: Money.from_cents(10_000_00, 'USD').format # => $10000.00 Money.from_cents(10_000_00, 'EUR').format # => €10000.00 ``` ## Collection In case you're working with collections of `Money` instances, have a look at [money-collection](https://github.com/RubyMoney/money-collection) for improved performance and accuracy. ### Troubleshooting If you don't have some locale and don't want to get a runtime error such as: I18n::InvalidLocale: :en is not a valid locale Set the following: ``` ruby I18n.enforce_available_locales = false ``` ## Heuristics Prior to v6.9.0 heuristic analysis of string input was part of this gem. Since then it was extracted in to [money-heuristics gem](https://github.com/RubyMoney/money-heuristics). ## Migration Notes #### Version 6.0.0 - The `Money#dollars` and `Money#amount` methods now return instances of `BigDecimal` rather than `Float`. We should avoid representing monetary values with floating point types so to avoid a whole class of errors relating to lack of precision. There are two migration options for this change: * The first is to test your application and where applicable update the application to accept a `BigDecimal` return value. This is the recommended path. * The second is to migrate from the `#amount` and `#dollars` methods to use the `#to_f` method instead. This option should only be used where `Float` is the desired type and nothing else will do for your application's requirements. money-6.16.0/money.gemspec0000644000004100000410000000272314054035243015463 0ustar www-datawww-data# -*- encoding: utf-8 -*- lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require "money/version" Gem::Specification.new do |s| s.name = "money" s.version = Money::VERSION s.platform = Gem::Platform::RUBY s.authors = ['Shane Emmons', 'Anthony Dmitriyev'] s.email = ['shane@emmons.io', 'anthony.dmitriyev@gmail.com'] s.homepage = "https://rubymoney.github.io/money" s.summary = "A Ruby Library for dealing with money and currency conversion." s.description = "A Ruby Library for dealing with money and currency conversion." s.license = "MIT" s.add_dependency 'i18n', [">= 0.6.4", '<= 2'] s.add_development_dependency "bundler" s.add_development_dependency "rake" s.add_development_dependency "rspec", "~> 3.4" s.add_development_dependency "yard", "~> 0.9.11" s.add_development_dependency "kramdown", "~> 2.3" s.files = `git ls-files -z -- config/* lib/* CHANGELOG.md LICENSE money.gemspec README.md`.split("\x0") s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) } s.test_files = s.files.grep(%r{^(test|spec|features)/}) s.require_paths = ["lib"] if s.respond_to?(:metadata) s.metadata['changelog_uri'] = 'https://github.com/RubyMoney/money/blob/master/CHANGELOG.md' s.metadata['source_code_uri'] = 'https://github.com/RubyMoney/money/' s.metadata['bug_tracker_uri'] = 'https://github.com/RubyMoney/money/issues' end end money-6.16.0/CHANGELOG.md0000644000004100000410000006640414054035243014606 0ustar www-datawww-data# Changelog ## 6.16.0 - Add `Money.from_cents` alias as a more explicit initializer, it's the same as `Money.new` ## 6.15.0 - Add :delimiter_pattern option to the Formatter ## 6.14.1 - Fix CHF format regression introduced in v6.14.0 - Fix deprecation warning in #format_decimal_part ## 6.14.0 - Fix Bahraini dinar symbol - Raise exception when default currency is not set or passed as parameter - Allow specifying default_bank as a lambda - Allow passing a default format in currencies definition only valid without symbol_position - Always allow comparison with zero Money - Rename Money.infinite_precision to default_infinite_precision - Add Currency.reset! method to reload all the default currency definitions - Fix edgecase for Money#allocate when applying to array of all zero values ## 6.13.8 - Update symbol for XOF - Update UYU currency symbol - Allow double conversion using same bank - Warn when using unsafe serializer for rate import - Move Icelandic symbol after the amount ## 6.13.7 - Improve deprecation warnings for the upcoming major release ## 6.13.6 - Fix a regression introduced in 6.13.5 that broken RatesStore::Memory subclasses ## 6.13.5 - Raise warning on using Money.default_currency - Raise warning on using default Money.rounding_mode - Add Second Ouguiya MRU 929 to currency iso file - Add symbol for UZS - Use monitor for recursive mutual exclusion in RatesStore::Memory - Allow passing store as a string to Money::Bank::VariableExchange (to support Rails 6) ## 6.13.4 - Update currency config for Zambian Kwacha (ZMW) - Do not modify options passed to FormattingRules ## 6.13.3 - Remove specs from the packaged gem - Use Currency::Loader directly without extending - Add Money.with_rounding_mode as a replacement for calling Money.rounding_mode with a block - Fix currency search for two digit ISO numbers - Add description to TypeError raised by +/- operations ## 6.13.2 - Prevent Money initialization with non-finite amounts - Convert the fractional value of a Money object to BigDecimal when initializing - Offer replacements for currency position deprecations - Fix Peruvian Sol symbol - Lock i18n to <= 1.2.0 for older (< 2.3) rubies - Prevent Divide By Zero in `Money#allocate` ## 6.13.1 - Add bolívar soberano (VES) - Deprecate bolívar fuerte (VEF) - Deprecate old `#format` rules passed as a symbol - Clarify `use_i18n` deprecation - Add `:currency` locale_backend for explicit per-currency localization ## 6.13.0 - Add :format option to the Formatter - Add ruby 2.6.0 support - Performance improvement (lazy stringify currency keys) - Add `Money.locale_backend` for translation lookups - Deprecate `use_i18n` flag in favour of `locale_backend = :i18n` - Deprecate old formatting rules in favour of `:format` - LVL and LTL are no longer used - Add `Currency#iso?` for checking if currency is iso or not - Relax versions-lock of `i18n` and `rspec` dependencies - Add Bitcoin Cash - Fix incorrect behaviour of `Currency#find_by_currency_iso` when given empty input ## 6.12.0 - Remove caching of `.empty`/`.zero` - Preserve assigned bank when rounding - Always round the fractional part when calling `#round` - Wrap all amount parts when `:html_wrap` option is used - Deprecate `#currency_as_string` and `#currency_as_string=` (in favour of `#with_currency`) - Add `#with_currency` for swapping the currency - Rewrite allocate/split (fixing some penny losing issues) ## 6.11.3 - Fix regression: if enabled use i18n locales in Money#to_s ## 6.11.2 - Fix regression: ignore formatting defaults for Money#to_s ## 6.11.1 - Fix issue with adding non-USD money to zero (used when calling `.sum` on an array) ## 6.11.0 - Support i18n 1.0 - Update yard dependency to 0.9.11 - Support for ruby 2.5.0 - Add inheritance for currency definitions - Added new symbol for bitcoin denomination - Specify custom rounding precision when using `infinite_precision` - Allow splits with sums greater than 1 - Prevent arithmetic methods from losing reference to the bank - Fix coerced zero numeric subtraction - Fix south asian formatting to support whole numbers - Refactor formatting logic ## 6.10.1 - Fix an issue with Money.empty memoization ## 6.10.0 - Added support for i18n version 0.9 - Disabled rounding when verifying allocation splits - Added Chinese Yuan Offshore (CNH) - Fixed html_entity for ARS - Fixed KZT symbol - Allowed comparing cross currency when both are zero - Fixed memory rate store - Corrected HUF subunit and thousands separator config ## 6.9.0 - Extracted heuristics into money-heuristics gem ## 6.8.4 - Resolving NIO ambiguity with CAD - Display the BBD $ symbol before digits - Symbol first for NIO and PAB currencies ## 6.8.3 - Added support for the British Penny (GBX) - Fixed LKR currency html_entity symbol ## 6.8.2 - Removed subunits for HUF - Fixed `#from_amount` accepting `nil` as currency_code - Relaxed i18n version (< 0.9) - Set symbol for UZS - Added disambiguate_symbol for XFU - Fixed Peruvian Sol name - Fixed symbol_first for VND (now `false`) ## 6.8.1 - Fixed issue with calling `format` on a frozen `Money` object ## 6.8.0 - Ruby 2.4.0 support - Fixed UZS syntax - Fixed HUF smallest denomination - Fixed ruby 1.9 issues - Fixed html entity for COP - Updated all currency decimals to ISO-4217 - Fixed money allocation for negative amounts - Fixed symbol_first for RON - Fixed disambiguate option when symbol is set to true - Fixed thousands separator for CZK - Improved formatter performance by precaching I18n calls ## 6.7.1 - Changed DKK symbol from 'kr' to 'kr.' - Improved Money::Formatting#format docs - Updated VEF symbol from 'Bs F' to 'Bs' - `Currency#exponent` now returns Fixnum - Fixed coercion issues - Fixed edge case with explicit override of thousands separator and decimal mark - `Money#==` will now raise error for non-zero numeric values - Fixed divmod - Added disambiguation symbol to USD Dollar - Use disambiguation symbol when both disambiguate and symbol are true in `format` method ## 6.7.0 - Changed `Money#<=>` to return `nil` if the comparison is inappropriate. (#584) - Remove implicit conversion of values being compared. Only accept `Money` and subclasses of `Money` for comparisons and raise TypeError otherwise. - When comparing fails due to `Money::Bank::UnknownRate` `Money#<=>` will now return `nil` as `Comparable#==` will not rescue exceptions in the next release. - Fix `Currency` specs for `#exponent` and `#decimal_places` not making assertions. - Fix a couple of Ruby warnings found in specs. - Fix `Money#-`,`Money#+` arithmetics for Ruby 2.3+ : check for zero value without using eql? with a Fixnum. (#577) - Use `Money#decimal_mark` when formatting with `rounded_infinite_precision` rule set to `true`. - Replaced meta-defined `thousands_separator` and `decimal_mark` methods with regular methods. (#579) ## 6.6.0 - Fixed VariableExchange#exchange_with for big numbers. - Add Currency symbol translation support - `Currency.all` raises a more helpful error message (`Currency::MissingAttributeError`)if a currency has no priority - `Currency` implements `Enumerable`. - `Currency#<=>` sorts alphabetically by `id` if the `priority`s are the same, and no longer raises an error if one of the priorities is missing. - `Money::Currency.unregister` can take an ISO code argument in addition to a hash. - `Money::Currency.unregister` returns `true` if the given currency previously existed, and `false` if it didn't. - Fix symbol for SZL currency - Trying to create a Currency without an `iso_code` now raises a more helpful error message. - Add `Money.usd`, `.cad` and `.eur` as aliases for `.us_dollar`, `.ca_dollar`, and `.euro`. - Add helper methods for British pounds: `Money.pound_sterling` and `Money.gbp`. - Add `Money.from_amount` to create money from a value in units instead of fractional units. - Changed CHF symbol from 'Fr' to 'CHF' - Changed CLF exponent from 0 to 4 - Changed CLP subunit_to_unit from 1 to 100 - Minor fixes to prevent warnings on unused variables and the redefinition of `Money.default_currency` - `Money#==` changed to acknowledge that 0 in one currency is equal to 0 in any currency. - Changed KRW subunit_to_unit from 100 to 1 - Decouple exchange rates storage from bank objects and formalize storage public API. Default is `Money::RatesStore::Memory`. - `Currency.new` now a singleton by its id ## 6.5.1 - Fix format for BYR currency ## 6.5.0 - Add method to round a given amount of money to the nearest possible value in cash (aka Swedish rounding). - Fixed the subunit_to_unit values of the CLP and KRW currencies - Add option for `disambiguate` symbols for formatting - Fixed the subunit_to_unit values of the VND currency - Fix formatting of NGN - show symbol before amount - Switch default and alternate symbols for RUB currency - Fix symbol for TRY currency - Add `Money.default_formatting_rules` hash, meant to define default rules for everytime `Money#format` is called. They can be overwritten if provided on method call - Add support for the new official symbol for Russian Ruble (RUB) — «₽» ## 6.2.1 - Ensure set is loaded ## 6.2.0 - Fixes formatting error when both `thousands_separator` and `decimal_mark` was added to Money#format as options. - Add Money#to_i which returns the whole part of the value. i.e. Money.new(100, "USD").to_i # => 1 - Fix output on Ukrainian Hryvnia symbol in HTML. - Add documentation about i18n in README. - Update iso code, symbol, subunit for the new Turkmenistani manat (GH-181) - Performance Improvements (1.99x faster on MRI, 1.85x on Rubinius, 41.4x faster on JRuby) - Money can now add and subtract Fixnum 0 - Money#new uses Money.default_currency if currency arg is nil (GH-410) - Fixed formatting of NOK, putting the symbol after numbers - Fixed issue where rounded_infinite_precision formatting fails for some localized currencies (GH-422) ## 6.1.1 - Remove lingering Monetize call ## 6.1.0 - Remove deprecated methods. - Fix issue with block form of rounding_mode. ## 6.0.1 - Deprecated methods lists caller on print out for easier updating. - Added support for Money::Currency#to_str and Money::Currency#to_sym - Added ability to temporally change the rounding methond inside a given block - Replaced parsing and core extensions with the monetize gem ## 6.0.0 - Fix BTC subunit - New option :sign_positive to add a + sign to positive numbers - Only allow to multiply a money by a number (int, float) - Fix typo - Wrap the currency symbol in a span if :html is specified in the rules - Added Money::Currency.all method - Allow combined comparison operator to handle zero values without rates - Added Money::Currency.unregister method - Works on Ruby 1.8.7 - Update deps - Depreciate Money.parse - Passing symbol: false when formatting 'JPY' currency in :ja locale will work as expected - Divide now obeys the specified rounding mode - Add Money#round method. This is helpful when working in infinite_precision mode and would like to perform rounding at specific points in your work flow. - In infinite precision mode, deserialized Money objects no longer return Float values from the `fractional` method. - Changed `thousands_separator` for Swedish Krona from dot to blank space. - Allow mathematical operations with first argument being not an instance of Money (eg. 2 * money instead of money * 2). - Money#dollars and Money#amount methods return numbers of type BigDecimal. - Change Money.from_bigdecimal (and in that way .to_money too) to keep precision when using `Money.infinite_precision = true` - Add :rounded_infinite_precision option to .format - Changed the New Taiwan Dollar symbol position from after the amount to before the amount. - Passing a Money instance to the Money constructor will obtain a new Money object with the same property values as the original - Add deprecation warning to comparators - Add Money.disallow_currency_conversion! option - Allow to inherits from `Money` ## 5.1.1 - Added :sign_before_symbol option to format negative numbers as -£1 rather than £-1 - Ensure BigDecimal.new always receives a string - compatibility fix for ruby-1.9.2-p320 - Update Maldivian Currency to MVR and fix ރ. to be ރ - Add exponent to currency - Add find_numeric to find currencies by ISO 4217 numeric code. - Fixed regression where thousands separator was missing on certain currencies. (GH-245) - Added :symbol_before_without_space option to add a space between currency symbol and amount. ## 5.1.0 - Fix currency assumption when parsing $ with a non-USD default currency. - Changed the Bulgarian lev symbol position from before the amount to after the amount. - Changed the symbol and html entity for INR. It is now "₹" instead of "₨". - Added Money::Currency.analyze for determining potential currencies for a given string using powereful algorithms - will detect symbols, iso codes and names even if mixed with text. - Changed UGX symbol from 'Sh' to 'USh'. - Changed SYP symbol from "£ or ل.س" to "£S". The previous symbols remain as alternates. - Changed RWF symbol from 'FR' to 'FRw'. - Changed RSD symbol from "din. or дин." to 'РСД'. The previous symbols remain as alternates. - Added MGA symbol 'Ar' - Added KGS symbol 'som' - Changed KES symbol from 'Sh' to 'KSh' - Added ETB symbol 'Br' - Changed EGP symbol from "£ or ج.م" to "ج.م" - Changed DJF symbol from 'Fr' to 'Fdj' - Changed CVE symbol from '$ or Esc' to '$'. 'Esc' remains as an alternate symbol. - Added BTN symbol 'Nu.' - Changed BAM symbol from 'KM or КМ' to 'КМ', the alternate (cyrillic script) remains as an alternate symbol. - Added alternate symbols for all currencies. For example, USD can be written as both '$' and 'US$', SEK can be 'Kr' or ':-', etc. - Renamed Money#cents to Money#fractional. Money#cents can still be used as a synonym and equivalent of Money#fractional. - Added Money.new_with_amount and Money#amount. Money.new_with_dollars and Money#dollars remain as synonyms. - Calling Bank::Base.instance doesn't make Bank::VariableExchange.instance return Bank::Base.instance anymore (semaperepelitsa) - Update Turkmenistan manat from TMM to TMT currency (GH-181). [Thanks @Exoth] - Moved ZWD Zimbabwean dollars to currency_bc.json, also added there ZWL, ZWN, and ZWR Zimbabwean dollars (GH-184). - Switch to multi_json gem (GH-170) - Fix "warning: ambiguous first argument..." (GH-166) - Update dependencies to latest and greatest (GH-172) - TravisBot is now watching Pull Request!!! (GH-171) - Minor code cleaning - Remove subunit from South Korean won (KRW) - Fixed bug where bankers rounding wasn't being used everywhere. ## 5.0.0 - Minor bugfix - incorrect use of character range resulted in botched results for Money::Parsing#extract_cents (GH-162) - Money::Currency::TABLE removed. Use Money::Currency.register to add additional currencies (GH-143) - Fix rounding error in Numeric.to_money (GH-145) - Allow on-the-fly calculation of decimal places if not known already (GH-146,GH-147,GH-148) - Move Euro symbol ahead of amount (GH-151) - Changed settings for Polish currency (GH-152) - Fall back to symbol if there is no html_entity present (GH-153) - Optionally Allow parsing of money values prefixed by symbols in key currencies (GH-155) - Fix bug where rates exported to a file from VariableExchange leave the File object open (GH-154) - Added Money#positive? and Money#negative? methods (GH-157) - Fix format function output for custom currencies (GH-156) - Fix parsing of strings with 3 decimal digits (GH-158) - Updated development dependencies - Said goodbye to RubyForge ## 4.0.2 - Money.to_money now understands a currency option (GH-121) - Added Money#-@ method to change object polarity (GH-122) - Added Money#symbol_or_iso_code utility method (GH-128) - Money.parse now understands trailing - as negative inputs (GH-133) - Money::Currency.new now validates input to avoid memory leaks (GH-137) - Forced UTF-8 encoding on currency JSON (GH-117) - Fixed position of Philippine peso sign (GH-124) - Fixed position of Danish currency sign (GH-127) ## 4.0.1 - Add missing config dir. Money 4.0.0 =========== The big change this release is moving the currency information into a JSON file. This should make it easier for users to add and test things. Thanks to Steve Morris for working on this during his Mendicant University course. In addition to this big change there were well over a dozen other minor changes. Features -------- - a new exchange bank nordea has been added to the README. (k33l0r) - a new exchange bank nbrb_currency has been added to the README. (slbug) - update Rake tasks - See our CI status in the README - Add syntax highlighting to the README (phlipper) - Remove minor unit from YEN (pwim) - Format YEN (pwim) - Update README for `_as_string` (mjankowski) - Update Lebanon currency (kaleemullah) - Update Polish złoty (holek) - Move currency information into JSON storage! (stevemorris) - Add ISO4217 Numeric codes (alovak) Bugfixes -------- - EEK currency is no longer used, kept for BC ([#issue/110](http://github.com/RubyMoney/money/issues/110)) - Lithuanian Litas symbol position fixed (laurynas) - Fixed README typos (phlipper) - Fixed README typos (pwim) - Fix specs (alovak) Money 3.7.1 =========== Bugfixes -------- - Add encoding indicator to top of Gemspec Money 3.7.0 =========== Features -------- - add Money#to_d (thanks Andrew White) - Add Money.use_i18n, this allows you to enable/disable i18n from being used, even if it's required in your app. Money 3.6.2 =========== Features -------- - i18n enhancements (thanks eloyesp [link](https://github.com/RubyMoney/money/commit/b2cab76c78ae04f40251fa20c4ab18faa968dc53)) - README updates (thanks pconnor) - Break into modules - Added `:no_cents_if_whole` format option - Update HKD from Ho to Cent - Performance improvements (thanks weppos) - Added Symbol#to_currency - Added Gemfile for development - Updated HUF currency to use `symbol_first => false` - Updated "Turkish New Lira" to "Turkish Lira" Money 3.6.1 =========== Bugfixes -------- - Floating point comparison needs to Epsilon aware (thanks Tobias Luetke) - reimplement fix for #issue/43, enable Marshal.(load/dump) Money 3.6.0 =========== Features -------- - Add a symbol position option for Money#format (thanks Romain, Gil and Julien) - Updated CNY to use "Fen" and subunit_to_unit of 100 - Updates to work with gem-testers.org Bugfixes -------- - Fixed issue with #format(no_cents: true) (thanks Romain & Julien) Money 3.5.5 =========== Features -------- - Enhancements to Money::Currency (thanks Matthew McEachen) - Replace delimiter with thousands_separator - Replace separator with decimal_mark - Added symbol_first and html_entity - Added allocation algorithm for fair(ish) splitting of money between parties without losing pennies (thanks Tobias Luetke) Bugfixes -------- - Always store cents as an Integer (thanks Abhay Kumar) - Fixed TypeError in rate exchange (thanks Christian Billen) - Cleanup #parse (thanks Tom Lianza) Money 3.5.4 =========== Features -------- - Added Currency#decimal_places. Bugfixes -------- - Fixed error with Money#to_s error with negative amounts that are only cents. Money 3.5.3 =========== Bugfixes -------- - Fixed an error in #to_s when cents is negative Money 3.5.2 =========== Bugfixes -------- - Fixed an error in #to_s which appended extra 0s incorrectly Money 3.5.1 =========== Bugfixes -------- - Removed erroneous require. Money 3.5.0 =========== Features -------- - Updated to RSpec2. - Use i18n to lookup separator and delimiter signs. - Removed all deprecated methods up to v3.5.0, including the following: - Using Money#format with params instead of a Hash. - Using a Hash with Money#new. - Using Bank#exchange, use Bank#exchange_with instead. Bugfixes -------- - Updated Money#to_s to respect :separator and :subunit_to_unit. - Fixed Money#format for :subunit_to_unit != 100. ([#issue/37](http://github.com/RubyMoney/money/issue/37)) - Fixed String#to_money for :subunit_to_unit != 100. ([#issue/36](http://github.com/RubyMoney/money/issue/36)) - Removed duplicate currencies. ([#issue/38](http://github.com/RubyMoney/money/issue/38)) - Fixed issue related to JRuby returning 2 for Math.log10(1000).floor instead of correctly returning 3. Money 3.1.5 =========== Features -------- - Added support for creating objects with the main monetary unit instead of cents. ([#issue/25](http://github.com/RubyMoney/money/issues/25)) - Deprecated `Money#format` with separate params instead of Hash. Deprecation target set to Money 3.5.0. ([#issue/31](http://github.com/RubyMoney/money/issues/31)) - Deprecated `Money#new(0, currency: "EUR")` in favor of `Money#new(0, "EUR")`. Deprecation target set to Money 3.5.0. ([#issue/31](http://github.com/RubyMoney/money/issues/31)) - Throw ArgumentError when trying to multiply two Money objects together. ([#issue/29](http://github.com/RubyMoney/money/issues/29)) - Update Money#parse to use :subunit_to_unit ([#issue/30](http://github.com/RubyMoney/money/issues/30)) Bugfixes -------- - Downgraded required_rubygems_version to >= 1.3.6. ([#issue/26](http://github.com/RubyMoney/money/issues/26)) - Use BigDecimal when floating point calculations are needed. - Ruby 1.9.2 compatibility enhancements. Money 3.1.0 =========== Features -------- - Implemented `Money::Bank::Base`. ([#issue/14](http://github.com/RubyMoney/money/issues/14)) - Added `Money::Bank::Base#exchange_with`. - Deprecated `Money::Bank::Base#exchange`. Deprecation target set to Money 3.2.0. - Implented `Money::Bank::VariableExchange` - Deprecated `Money::VariableExchangeBank`. Deprecation target set to Money 3.2.0. - Deprecate `Money::SYMBOLS`, `Money::SEPARATORS` and `Money::DELIMITERS`. Deprecation target set to Money 3.2.0. ([#issue/16](http://github.com/RubyMoney/money/issues/16)) - Implemented `#has` for `Money` and `Money::Currency`. - Refactored test suite to conform to RSpec conventions. - Moved project from [FooBarWidget](http://github.com/FooBarWidget) to [RubyMoney](http://github.com/RubyMoney) - Added Simone Carletti to list of authors. - Moved `@rounding_method` from `Money::Bank::VariableExchange` to `Money::Bank::Base`. ([#issue/18](http://github.com/RubyMoney/money/issues/18)) - Added `#setup` to `Money::Bank::Base`. Called from `#initialize`. ([#issue/19](http://github.com/RubyMoney/money/issues/19)) - Added [google_currency](http://github.com/RubyMoney/google_currency) to list of Currency Exchange Implementations. - Added `#export_rates` to `Money::Bank::VariableExchange`. ([#issue/21](http://github.com/RubyMoney/money/issues/21)) - Added `#import_rates` to `Money::Bank::VariableExchange`. ([#issue/21](http://github.com/RubyMoney/money/issues/21)) - Removed dependency on Jeweler. - Replaced usage of hanna with yardoc. - Rewrote/reformatted all documentation. Bugfixes -------- - Fixed incorrect URLs in documentation. ([#issue/17](http://github.com/RubyMoney/money/issues/17)) - Updated `:subunit_to_unit` for HKD from 10 to 100. ([#issue/20](http://github.com/RubyMoney/money/issues/20)) - Updated Ghanaian Cedi to use correct ISO Code, GHS. ([#issue/22](http://github.com/RubyMoney/money/issues/22)) - Make `default` rake task call `spec`. ([#issue/23](http://github.com/RubyMoney/money/issues/23)) Money 3.1.0.pre3 ================ Features -------- - Added [google_currency](http://github.com/RubyMoney/google_currency) to list of Currency Exchange Implementations. - Added `#export_rates` to `Money::Bank::VariableExchange`. ([#issue/21](http://github.com/RubyMoney/money/issues/21)) - Added `#import_rates` to `Money::Bank::VariableExchange`. ([#issue/21](http://github.com/RubyMoney/money/issues/21)) Bugfixes -------- - Updated `:subunit_to_unit` for HKD from 10 to 100. ([#issue/20](http://github.com/RubyMoney/money/issues/20)) Money 3.1.0.pre2 ================ Features -------- - Moved `@rounding_method` from `Money::Bank::VariableExchange` to `Money::Bank::Base`. ([#issue/18](http://github.com/RubyMoney/money/issues/18)) - Added `#setup` to `Money::Bank::Base`. Called from `#initialize`. ([#issue/19](http://github.com/RubyMoney/money/issues/19)) Bugfixes -------- - Fixed incorrect URLs in documentation. ([#issue/17](http://github.com/RubyMoney/money/issues/17)) Money 3.1.0.pre1 ================ Features -------- - Implemented `Money::Bank::Base`. ([#issue/14](http://github.com/RubyMoney/money/issues/14)) - Added `Money::Bank::Base#exchange_with`. - Deprecated `Money::Bank::Base#exchange`. Deprecation target set to Money 3.2.0. - Implented `Money::Bank::VariableExchange` - Deprecated `Money::VariableExchangeBank`. Deprecation target set to Money 3.2.0. - Deprecate `Money::SYMBOLS`, `Money::SEPARATORS` and `Money::DELIMITERS`. Deprecation target set to Money 3.2.0. ([#issue/16](http://github.com/RubyMoney/money/issues/16)) - Implemented `#has` for `Money` and `Money::Currency`. - Refactored test suite to conform to RSpec conventions. - Moved project from [FooBarWidget](http://github.com/FooBarWidget) to [RubyMoney](http://github.com/RubyMoney) - Added Simone Carletti to list of authors. Bugfixes -------- - Fixed rounding error in `Numeric#to_money`. ([#issue/15](http://github.com/RubyMoney/money/issues/15)) Money 3.0.5 =========== Features -------- - Added `Money#abs`. - Added ability to pass a block to `VariableExchangeBank#new` or `#exchange`, specifying a custom truncation method - Added optional `currency` argument to` Numeric#to_money`. ([#issue/11](http://github.com/RubyMoney/money/issues/11)) - Added optional `currency` argument to `String#to_money`. ([#issue/11](http://github.com/RubyMoney/money/issues/11)) - Use '¤' as the default currency symbol. ([#issue/10](http://github.com/RubyMoney/money/issues/10)) Bugfixes -------- - Updated `Currency#subunit_to_unit` documentation (it's an integer not a string). - Fixed issue when exchanging currencies with different `:subunit_to_unit` values. - `Numeric#to_money` now respects `:subunit_to_unit`. ([#issue/12](http://github.com/RubyMoney/money/issues/12)) Money 3.0.4 =========== Features -------- - Use `:subunit_to_unit` in `#to_s`, `#to_f` and `#format`. - Deprecated `Money#SEPARATORS` and `Money#DELIMITERS`. Bugfixes -------- - Updated `#exchange` to avoid floating point rounding errors. - Added `:separator` and `:delimiter` to `Currency` - Updated the attributes of the Chilean Peso. Money 3.0.3 =========== Features -------- - Added `#currency_as_string` and `#currency_as_string=` for easier integration with ActiveRecord/Rails Money 3.0.2 =========== Features -------- - Added `#div`, `#divmod`, `#modulo`, `#%` and `#remainder` to `Money`. Money 3.0.1 =========== Features -------- - Added `#eql?` to `Money` - Updated `Numeric#to_money` to work with all children of `Numeric` (i.e. `BigDecimal`, `Integer`, `Fixnum`, `Float`, etc) Money 3.0.0 =========== Features -------- - Version Bump due to compatibility changes with ActiveRecord. See conversation [here](http://github.com/RubyMoney/money/issues#issue/4/comment/224880) for more information. Money 2.3.0 =========== Features -------- - Currency is now represented by a `Currency` Object instead of a `String`. Money 2.2.0 =========== Features -------- - Can now divide two Money objects by one another using `#/`. - Can now convert a Money object to a float using `#to_f`. - Users can now specify Separators and Delimiters when using `#format`. - Support for Brazilian Real `Money.new(1_00, :BRL)` - Migrated to Jeweler money-6.16.0/LICENSE0000644000004100000410000000215014054035243013766 0ustar www-datawww-dataMIT License Copyright (c) 2005 Tobias Lutke Copyright (c) 2008 Phusion Copyright (c) 2021 Shane Emmons Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. money-6.16.0/lib/0000755000004100000410000000000014054035243013531 5ustar www-datawww-datamoney-6.16.0/lib/money/0000755000004100000410000000000014054035243014660 5ustar www-datawww-datamoney-6.16.0/lib/money/version.rb0000644000004100000410000000004514054035243016671 0ustar www-datawww-dataclass Money VERSION = '6.16.0' end money-6.16.0/lib/money/currency.rb0000644000004100000410000003445714054035243017054 0ustar www-datawww-data# encoding: utf-8 require "json" require "money/currency/loader" require "money/currency/heuristics" class Money # Represents a specific currency unit. # # @see https://en.wikipedia.org/wiki/Currency # @see http://iso4217.net/ class Currency include Comparable extend Enumerable extend Money::Currency::Heuristics # Keeping cached instances in sync between threads @@mutex = Mutex.new @@instances = {} # Thrown when a Currency has been registered without all the attributes # which are required for the current action. class MissingAttributeError < StandardError def initialize(method, currency, attribute) super( "Can't call Currency.#{method} - currency '#{currency}' is missing "\ "the attribute '#{attribute}'" ) end end # Thrown when an unknown currency is requested. class UnknownCurrency < ArgumentError; end class << self def new(id) id = id.to_s.downcase unless stringified_keys.include?(id) raise UnknownCurrency, "Unknown currency '#{id}'" end _instances[id] || @@mutex.synchronize { _instances[id] ||= super } end def _instances @@instances end # Lookup a currency with given +id+ an returns a +Currency+ instance on # success, +nil+ otherwise. # # @param [String, Symbol, #to_s] id Used to look into +table+ and # retrieve the applicable attributes. # # @return [Money::Currency] # # @example # Money::Currency.find(:eur) #=> # # Money::Currency.find(:foo) #=> nil def find(id) id = id.to_s.downcase.to_sym new(id) rescue UnknownCurrency nil end # Lookup a currency with given +num+ as an ISO 4217 numeric and returns an # +Currency+ instance on success, +nil+ otherwise. # # @param [#to_s] num used to look into +table+ in +iso_numeric+ and find # the right currency id. # # @return [Money::Currency] # # @example # Money::Currency.find_by_iso_numeric(978) #=> # # Money::Currency.find_by_iso_numeric(51) #=> # # Money::Currency.find_by_iso_numeric('001') #=> nil def find_by_iso_numeric(num) num = num.to_s.rjust(3, '0') return if num.empty? id, _ = self.table.find { |key, currency| currency[:iso_numeric] == num } new(id) rescue UnknownCurrency nil end # Wraps the object in a +Currency+ unless it's already a +Currency+ # object. # # @param [Object] object The object to attempt and wrap as a +Currency+ # object. # # @return [Money::Currency] # # @example # c1 = Money::Currency.new(:usd) # Money::Currency.wrap(nil) #=> nil # Money::Currency.wrap(c1) #=> # # Money::Currency.wrap("usd") #=> # def wrap(object) if object.nil? nil elsif object.is_a?(Currency) object else Currency.new(object) end end # List of known currencies. # # == monetary unit # The standard unit of value of a currency, as the dollar in the United States or the peso in Mexico. # https://www.answers.com/topic/monetary-unit # == fractional monetary unit, subunit # A monetary unit that is valued at a fraction (usually one hundredth) of the basic monetary unit # https://www.answers.com/topic/fractional-monetary-unit-subunit # # See https://en.wikipedia.org/wiki/List_of_circulating_currencies and # http://search.cpan.org/~tnguyen/Locale-Currency-Format-1.28/Format.pm def table @table ||= Loader.load_currencies end # List the currencies imported and registered # @return [Array] # # @example # Money::Currency.all() # [#, 'CAD', 'EUR']... def all table.keys.map do |curr| c = Currency.new(curr) if c.priority.nil? raise MissingAttributeError.new(:all, c.id, :priority) end c end.sort_by(&:priority) end # We need a string-based validator before creating an unbounded number of # symbols. # http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol#11 # https://github.com/RubyMoney/money/issues/132 # # @return [Set] def stringified_keys @stringified_keys ||= stringify_keys end # Register a new currency # # @param curr [Hash] information about the currency # @option priority [Numeric] a numerical value you can use to sort/group # the currency list # @option iso_code [String] the international 3-letter code as defined # by the ISO 4217 standard # @option iso_numeric [Integer] the international 3-digit code as # defined by the ISO 4217 standard # @option name [String] the currency name # @option symbol [String] the currency symbol (UTF-8 encoded) # @option subunit [String] the name of the fractional monetary unit # @option subunit_to_unit [Numeric] the proportion between the unit and # the subunit # @option separator [String] character between the whole and fraction # amounts # @option delimiter [String] character between each thousands place def register(curr) key = curr.fetch(:iso_code).downcase.to_sym @@mutex.synchronize { _instances.delete(key.to_s) } @table[key] = curr @stringified_keys = nil end # Inherit a new currency from existing one # # @param parent_iso_code [String] the international 3-letter code as defined # @param curr [Hash] See {register} method for hash structure def inherit(parent_iso_code, curr) parent_iso_code = parent_iso_code.downcase.to_sym curr = @table.fetch(parent_iso_code, {}).merge(curr) register(curr) end # Unregister a currency. # # @param [Object] curr A Hash with the key `:iso_code`, or the ISO code # as a String or Symbol. # # @return [Boolean] true if the currency previously existed, false # if it didn't. def unregister(curr) if curr.is_a?(Hash) key = curr.fetch(:iso_code).downcase.to_sym else key = curr.downcase.to_sym end existed = @table.delete(key) @stringified_keys = nil if existed existed ? true : false end def each all.each { |c| yield(c) } end def reset! @@instances = {} @table = Loader.load_currencies end private def stringify_keys table.keys.each_with_object(Set.new) { |k, set| set.add(k.to_s.downcase) } end end # @!attribute [r] id # @return [Symbol] The symbol used to identify the currency, usually THE # lowercase +iso_code+ attribute. # @!attribute [r] priority # @return [Integer] A numerical value you can use to sort/group the # currency list. # @!attribute [r] iso_code # @return [String] The international 3-letter code as defined by the ISO # 4217 standard. # @!attribute [r] iso_numeric # @return [String] The international 3-numeric code as defined by the ISO # 4217 standard. # @!attribute [r] name # @return [String] The currency name. # @!attribute [r] symbol # @return [String] The currency symbol (UTF-8 encoded). # @!attribute [r] disambiguate_symbol # @return [String] Alternative currency used if symbol is ambiguous # @!attribute [r] html_entity # @return [String] The html entity for the currency symbol # @!attribute [r] subunit # @return [String] The name of the fractional monetary unit. # @!attribute [r] subunit_to_unit # @return [Integer] The proportion between the unit and the subunit # @!attribute [r] decimal_mark # @return [String] The decimal mark, or character used to separate the # whole unit from the subunit. # @!attribute [r] thousands_separator # @return [String] The character used to separate thousands grouping of # the whole unit. # @!attribute [r] symbol_first # @return [Boolean] Should the currency symbol precede the amount, or # should it come after? # @!attribute [r] smallest_denomination # @return [Integer] Smallest amount of cash possible (in the subunit of # this currency) attr_reader :id, :priority, :iso_code, :iso_numeric, :name, :symbol, :disambiguate_symbol, :html_entity, :subunit, :subunit_to_unit, :decimal_mark, :thousands_separator, :symbol_first, :smallest_denomination, :format alias_method :separator, :decimal_mark alias_method :delimiter, :thousands_separator alias_method :eql?, :== # Create a new +Currency+ object. # # @param [String, Symbol, #to_s] id Used to look into +table+ and retrieve # the applicable attributes. # # @return [Money::Currency] # # @example # Money::Currency.new(:usd) #=> # def initialize(id) @id = id.to_sym initialize_data! end # Compares +self+ with +other_currency+ against the value of +priority+ # attribute. # # @param [Money::Currency] other_currency The currency to compare to. # # @return [-1,0,1] -1 if less than, 0 is equal to, 1 if greater than # # @example # c1 = Money::Currency.new(:usd) # c2 = Money::Currency.new(:jpy) # c1 <=> c2 #=> 1 # c2 <=> c1 #=> -1 # c1 <=> c1 #=> 0 def <=>(other_currency) # <=> returns nil when one of the values is nil comparison = self.priority <=> other_currency.priority || 0 if comparison == 0 self.id <=> other_currency.id else comparison end end # Compares +self+ with +other_currency+ and returns +true+ if the are the # same or if their +id+ attributes match. # # @param [Money::Currency] other_currency The currency to compare to. # # @return [Boolean] # # @example # c1 = Money::Currency.new(:usd) # c2 = Money::Currency.new(:jpy) # c1 == c1 #=> true # c1 == c2 #=> false def ==(other_currency) self.equal?(other_currency) || compare_ids(other_currency) end def compare_ids(other_currency) other_currency_id = if other_currency.is_a?(Currency) other_currency.id.to_s.downcase else other_currency.to_s.downcase end self.id.to_s.downcase == other_currency_id end private :compare_ids # Returns a Integer hash value based on the +id+ attribute in order to use # functions like & (intersection), group_by, etc. # # @return [Integer] # # @example # Money::Currency.new(:usd).hash #=> 428936 def hash id.hash end # Returns a human readable representation. # # @return [String] # # @example # Money::Currency.new(:usd) #=> # def inspect "#<#{self.class.name} id: #{id}, priority: #{priority}, symbol_first: #{symbol_first}, thousands_separator: #{thousands_separator}, html_entity: #{html_entity}, decimal_mark: #{decimal_mark}, name: #{name}, symbol: #{symbol}, subunit_to_unit: #{subunit_to_unit}, exponent: #{exponent}, iso_code: #{iso_code}, iso_numeric: #{iso_numeric}, subunit: #{subunit}, smallest_denomination: #{smallest_denomination}, format: #{format}>" end # Returns a string representation corresponding to the upcase +id+ # attribute. # # -- # DEV: id.to_s.upcase corresponds to iso_code but don't use ISO_CODE for consistency. # # @return [String] # # @example # Money::Currency.new(:usd).to_s #=> "USD" # Money::Currency.new(:eur).to_s #=> "EUR" def to_s id.to_s.upcase end # Returns a string representation corresponding to the upcase +id+ # attribute. Useful in cases where only implicit conversions are made. # # @return [String] # # @example # Money::Currency.new(:usd).to_str #=> "USD" # Money::Currency.new(:eur).to_str #=> "EUR" def to_str id.to_s.upcase end # Returns a symbol representation corresponding to the upcase +id+ # attribute. # # @return [Symbol] # # @example # Money::Currency.new(:usd).to_sym #=> :USD # Money::Currency.new(:eur).to_sym #=> :EUR def to_sym id.to_s.upcase.to_sym end # Conversion to +self+. # # @return [self] def to_currency self end # Returns currency symbol or iso code for currencies with no symbol. # # @return [String] def code symbol || iso_code end def symbol_first? !!@symbol_first end # Returns if a code currency is ISO. # # @return [Boolean] # # @example # Money::Currency.new(:usd).iso? # def iso? iso_numeric && iso_numeric != '' end # Returns the relation between subunit and unit as a base 10 exponent. # # Note that MGA and MRU are exceptions and are rounded to 1 # @see https://en.wikipedia.org/wiki/ISO_4217#Active_codes # # @return [Integer] def exponent Math.log10(subunit_to_unit).round end alias decimal_places exponent private def initialize_data! data = self.class.table[@id] @alternate_symbols = data[:alternate_symbols] @decimal_mark = data[:decimal_mark] @disambiguate_symbol = data[:disambiguate_symbol] @html_entity = data[:html_entity] @iso_code = data[:iso_code] @iso_numeric = data[:iso_numeric] @name = data[:name] @priority = data[:priority] @smallest_denomination = data[:smallest_denomination] @subunit = data[:subunit] @subunit_to_unit = data[:subunit_to_unit] @symbol = data[:symbol] @symbol_first = data[:symbol_first] @thousands_separator = data[:thousands_separator] @format = data[:format] end end end money-6.16.0/lib/money/rates_store/0000755000004100000410000000000014054035243017212 5ustar www-datawww-datamoney-6.16.0/lib/money/rates_store/memory.rb0000644000004100000410000000730414054035243021053 0ustar www-datawww-datarequire 'monitor' class Money module RatesStore # Class for thread-safe storage of exchange rate pairs. # Used by instances of +Money::Bank::VariableExchange+. # # @example # store = Money::RatesStore::Memory.new # store.add_rate 'USD', 'CAD', 0.98 # store.get_rate 'USD', 'CAD' # => 0.98 # # iterates rates # store.each_rate {|iso_from, iso_to, rate| puts "#{from} -> #{to}: #{rate}" } class Memory INDEX_KEY_SEPARATOR = '_TO_'.freeze # Initializes a new +Money::RatesStore::Memory+ object. # # @param [Hash] opts Optional store options. # @option opts [Boolean] :without_mutex disables the usage of a mutex # @param [Hash] rates Optional initial exchange rate data. def initialize(opts = {}, rates = {}) @rates = rates @options = opts @guard = Monitor.new end # Registers a conversion rate and returns it. Uses +Mutex+ to synchronize data access. # # @param [String] currency_iso_from Currency to exchange from. # @param [String] currency_iso_to Currency to exchange to. # @param [Numeric] rate Rate to use when exchanging currencies. # # @return [Numeric] # # @example # store = Money::RatesStore::Memory.new # store.add_rate("USD", "CAD", 1.24515) # store.add_rate("CAD", "USD", 0.803115) def add_rate(currency_iso_from, currency_iso_to, rate) guard.synchronize do rates[rate_key_for(currency_iso_from, currency_iso_to)] = rate end end # Retrieve the rate for the given currencies. Uses +Mutex+ to synchronize data access. # Delegates to +Money::RatesStore::Memory+ # # @param [String] currency_iso_from Currency to exchange from. # @param [String] currency_iso_to Currency to exchange to. # # @return [Numeric] # # @example # store = Money::RatesStore::Memory.new # store.add_rate("USD", "CAD", 1.24515) # # store.get_rate("USD", "CAD") #=> 1.24515 def get_rate(currency_iso_from, currency_iso_to) guard.synchronize do rates[rate_key_for(currency_iso_from, currency_iso_to)] end end def marshal_dump guard.synchronize do return [self.class, options, rates.dup] end end # Wraps block execution in a thread-safe transaction def transaction(&block) guard.synchronize do yield end end # Iterate over rate tuples (iso_from, iso_to, rate) # # @yieldparam iso_from [String] Currency ISO string. # @yieldparam iso_to [String] Currency ISO string. # @yieldparam rate [Numeric] Exchange rate. # # @return [Enumerator] # # @example # store.each_rate do |iso_from, iso_to, rate| # puts [iso_from, iso_to, rate].join # end def each_rate(&block) return to_enum(:each_rate) unless block_given? guard.synchronize do rates.each do |key, rate| iso_from, iso_to = key.split(INDEX_KEY_SEPARATOR) yield iso_from, iso_to, rate end end end private attr_reader :rates, :options, :guard # Return the rate hashkey for the given currencies. # # @param [String] currency_iso_from The currency to exchange from. # @param [String] currency_iso_to The currency to exchange to. # # @return [String] # # @example # rate_key_for("USD", "CAD") #=> "USD_TO_CAD" def rate_key_for(currency_iso_from, currency_iso_to) [currency_iso_from, currency_iso_to].join(INDEX_KEY_SEPARATOR).upcase end end end end money-6.16.0/lib/money/money/0000755000004100000410000000000014054035243016007 5ustar www-datawww-datamoney-6.16.0/lib/money/money/formatter.rb0000644000004100000410000003605014054035243020343 0ustar www-datawww-data# encoding: UTF-8 require 'money/money/formatting_rules' class Money class Formatter DEFAULTS = { thousands_separator: '', decimal_mark: '.' }.freeze # Creates a formatted price string according to several rules. # # @param [Hash] rules The options used to format the string. # # @return [String] # # @option rules [Boolean, String] :display_free (false) Whether a zero # amount of money should be formatted of "free" or as the supplied string. # # @example # Money.us_dollar(0).format(display_free: true) #=> "free" # Money.us_dollar(0).format(display_free: "gratis") #=> "gratis" # Money.us_dollar(0).format #=> "$0.00" # # @option rules [Boolean] :with_currency (false) Whether the currency name # should be appended to the result string. # # @example # Money.ca_dollar(100).format #=> "$1.00" # Money.ca_dollar(100).format(with_currency: true) #=> "$1.00 CAD" # Money.us_dollar(85).format(with_currency: true) #=> "$0.85 USD" # # @option rules [Boolean] :rounded_infinite_precision (false) Whether the # amount of money should be rounded when using {infinite_precision} # # @example # Money.us_dollar(100.1).format #=> "$1.001" # Money.us_dollar(100.1).format(rounded_infinite_precision: true) #=> "$1" # Money.us_dollar(100.9).format(rounded_infinite_precision: true) #=> "$1.01" # # @option rules [Boolean] :no_cents (false) Whether cents should be omitted. # # @example # Money.ca_dollar(100).format(no_cents: true) #=> "$1" # Money.ca_dollar(599).format(no_cents: true) #=> "$5" # # @option rules [Boolean] :no_cents_if_whole (false) Whether cents should be # omitted if the cent value is zero # # @example # Money.ca_dollar(10000).format(no_cents_if_whole: true) #=> "$100" # Money.ca_dollar(10034).format(no_cents_if_whole: true) #=> "$100.34" # # @option rules [Boolean, String, nil] :symbol (true) Whether a money symbol # should be prepended to the result string. The default is true. This method # attempts to pick a symbol that's suitable for the given currency. # # @example # Money.new(100, "USD") #=> "$1.00" # Money.new(100, "GBP") #=> "£1.00" # Money.new(100, "EUR") #=> "€1.00" # # # Same thing. # Money.new(100, "USD").format(symbol: true) #=> "$1.00" # Money.new(100, "GBP").format(symbol: true) #=> "£1.00" # Money.new(100, "EUR").format(symbol: true) #=> "€1.00" # # # You can specify a false expression or an empty string to disable # # prepending a money symbol.§ # Money.new(100, "USD").format(symbol: false) #=> "1.00" # Money.new(100, "GBP").format(symbol: nil) #=> "1.00" # Money.new(100, "EUR").format(symbol: "") #=> "1.00" # # # If the symbol for the given currency isn't known, then it will default # # to "¤" as symbol. # Money.new(100, "AWG").format(symbol: true) #=> "¤1.00" # # # You can specify a string as value to enforce using a particular symbol. # Money.new(100, "AWG").format(symbol: "ƒ") #=> "ƒ1.00" # # # You can specify a indian currency format # Money.new(10000000, "INR").format(south_asian_number_formatting: true) #=> "1,00,000.00" # Money.new(10000000).format(south_asian_number_formatting: true) #=> "$1,00,000.00" # # @option rules [Boolean, nil] :symbol_before_without_space (true) Whether # a space between the money symbol and the amount should be inserted when # +:symbol_position+ is +:before+. The default is true (meaning no space). Ignored # if +:symbol+ is false or +:symbol_position+ is not +:before+. # # @example # # Default is to not insert a space. # Money.new(100, "USD").format #=> "$1.00" # # # Same thing. # Money.new(100, "USD").format(symbol_before_without_space: true) #=> "$1.00" # # # If set to false, will insert a space. # Money.new(100, "USD").format(symbol_before_without_space: false) #=> "$ 1.00" # # @option rules [Boolean, nil] :symbol_after_without_space (false) Whether # a space between the amount and the money symbol should be inserted when # +:symbol_position+ is +:after+. The default is false (meaning space). Ignored # if +:symbol+ is false or +:symbol_position+ is not +:after+. # # @example # # Default is to insert a space. # Money.new(100, "USD").format(symbol_position: :after) #=> "1.00 $" # # # If set to true, will not insert a space. # Money.new(100, "USD").format(symbol_position: :after, symbol_after_without_space: true) #=> "1.00$" # # @option rules [Boolean, String, nil] :decimal_mark (true) Whether the # currency should be separated by the specified character or '.' # # @example # # If a string is specified, it's value is used. # Money.new(100, "USD").format(decimal_mark: ",") #=> "$1,00" # # # If the decimal_mark for a given currency isn't known, then it will default # # to "." as decimal_mark. # Money.new(100, "FOO").format #=> "$1.00" # # @option rules [Boolean, String, nil] :thousands_separator (true) Whether # the currency should be delimited by the specified character or ',' # # @example # # If false is specified, no thousands_separator is used. # Money.new(100000, "USD").format(thousands_separator: false) #=> "1000.00" # Money.new(100000, "USD").format(thousands_separator: nil) #=> "1000.00" # Money.new(100000, "USD").format(thousands_separator: "") #=> "1000.00" # # # If a string is specified, it's value is used. # Money.new(100000, "USD").format(thousands_separator: ".") #=> "$1.000.00" # # # If the thousands_separator for a given currency isn't known, then it will # # default to "," as thousands_separator. # Money.new(100000, "FOO").format #=> "$1,000.00" # # @option rules [Boolean] :html (false) Whether the currency should be # HTML-formatted. Only useful in combination with +:with_currency+. # # @example # Money.ca_dollar(570).format(html: true, with_currency: true) # #=> "$5.70 CAD" # # @option rules [Boolean] :html_wrap (false) Whether all currency parts should be HTML-formatted. # # @example # Money.ca_dollar(570).format(html_wrap: true, with_currency: true) # #=> "$5.70 CAD" # # @option rules [Boolean] :sign_before_symbol (false) Whether the sign should be # before the currency symbol. # # @example # # You can specify to display the sign before the symbol for negative numbers # Money.new(-100, "GBP").format(sign_before_symbol: true) #=> "-£1.00" # Money.new(-100, "GBP").format(sign_before_symbol: false) #=> "£-1.00" # Money.new(-100, "GBP").format #=> "£-1.00" # # @option rules [Boolean] :sign_positive (false) Whether positive numbers should be # signed, too. # # @example # # You can specify to display the sign with positive numbers # Money.new(100, "GBP").format(sign_positive: true, sign_before_symbol: true) #=> "+£1.00" # Money.new(100, "GBP").format(sign_positive: true, sign_before_symbol: false) #=> "£+1.00" # Money.new(100, "GBP").format(sign_positive: false, sign_before_symbol: true) #=> "£1.00" # Money.new(100, "GBP").format(sign_positive: false, sign_before_symbol: false) #=> "£1.00" # Money.new(100, "GBP").format #=> "£+1.00" # # @option rules [Boolean] :disambiguate (false) Prevents the result from being ambiguous # due to equal symbols for different currencies. Uses the `disambiguate_symbol`. # # @example # Money.new(10000, "USD").format(disambiguate: false) #=> "$100.00" # Money.new(10000, "CAD").format(disambiguate: false) #=> "$100.00" # Money.new(10000, "USD").format(disambiguate: true) #=> "$100.00" # Money.new(10000, "CAD").format(disambiguate: true) #=> "C$100.00" # # @option rules [Boolean] :html_wrap_symbol (false) Wraps the currency symbol # in a html tag. # # @example # Money.new(10000, "USD").format(disambiguate: false) # #=> "$100.00 # # @option rules [Symbol] :symbol_position (:before) `:before` if the currency # symbol goes before the amount, `:after` if it goes after. # # @example # Money.new(10000, "USD").format(symbol_position: :before) #=> "$100.00" # Money.new(10000, "USD").format(symbol_position: :after) #=> "100.00 $" # # @option rules [Boolean] :translate (true) `true` Checks for custom # symbol definitions using I18n. # # @example # # With the following entry in the translation files: # # en: # # number: # # currency: # # symbol: # # CAD: "CAD$" # Money.new(10000, "CAD").format(translate: true) #=> "CAD$100.00" # # @option rules [Boolean] :drop_trailing_zeros (false) Ignore trailing zeros after # the decimal mark # # @example # Money.new(89000, :btc).format(drop_trailing_zeros: true) #=> B⃦0.00089 # Money.new(110, :usd).format(drop_trailing_zeros: true) #=> $1.1 # # @option rules [Boolean] :delimiter_pattern (/(\d)(?=(?:\d{3})+(?:[^\d]{1}|$))/) Regular expression to set the placement # for the thousands delimiter # # @example # Money.new(89000, :btc).format(delimiter_pattern: /(\d)(?=\d)/) #=> B⃦8,9,0.00 # # @option rules [String] :format (nil) Provide a template for formatting. `%u` will be replaced # with the symbol (if present) and `%n` will be replaced with the number. # # @example # Money.new(10000, "USD").format(format: '%u %n') #=> "$ 100.00" # Money.new(10000, "USD").format(format: '%u%n') #=> "$100.00" # # Note that the default rules can be defined through {Money.default_formatting_rules} hash. # # @see Money.default_formatting_rules Money.default_formatting_rules for more information. def initialize(money, *rules) @money = money @currency = money.currency @rules = FormattingRules.new(@currency, *rules) end def to_s return free_text if show_free_text? result = format_number formatted = append_sign(result) append_currency_symbol(formatted) end def thousands_separator lookup :thousands_separator end def decimal_mark lookup :decimal_mark end alias_method :delimiter, :thousands_separator alias_method :separator, :decimal_mark private attr_reader :money, :currency, :rules def format_number whole_part, decimal_part = extract_whole_and_decimal_parts # Format whole and decimal parts separately decimal_part = format_decimal_part(decimal_part) whole_part = format_whole_part(whole_part) # Assemble the final formatted amount if rules[:html_wrap] if decimal_part.nil? html_wrap(whole_part, "whole") else [ html_wrap(whole_part, "whole"), html_wrap(decimal_mark, "decimal-mark"), html_wrap(decimal_part, "decimal") ].join end else [whole_part, decimal_part].compact.join(decimal_mark) end end def append_sign(formatted_number) sign = money.negative? ? '-' : '' if rules[:sign_positive] == true && money.positive? sign = '+' end if rules[:sign_before_symbol] == true sign_before = sign sign = '' end symbol_value = symbol_value_from(rules) if symbol_value && !symbol_value.empty? if rules[:html_wrap_symbol] symbol_value = "#{symbol_value}" elsif rules[:html_wrap] symbol_value = html_wrap(symbol_value, "currency-symbol") end rules[:format] .gsub('%u', [sign_before, symbol_value].join) .gsub('%n', [sign, formatted_number].join) else formatted_number = "#{sign_before}#{sign}#{formatted_number}" end end def append_currency_symbol(formatted_number) if rules[:with_currency] formatted_number << " " if rules[:html] formatted_number << "#{currency.to_s}" elsif rules[:html_wrap] formatted_number << html_wrap(currency.to_s, "currency") else formatted_number << currency.to_s end end formatted_number end def show_free_text? money.zero? && rules[:display_free] end def html_wrap(string, class_name) "#{string}" end def free_text rules[:display_free].respond_to?(:to_str) ? rules[:display_free] : 'free' end def format_whole_part(value) # Apply thousands_separator value.gsub(rules[:delimiter_pattern]) do |digit_to_delimit| "#{digit_to_delimit}#{thousands_separator}" end end def extract_whole_and_decimal_parts fractional = money.fractional.abs # Round the infinite precision part if needed fractional = fractional.round if rules[:rounded_infinite_precision] # Translate subunits into units fractional_units = BigDecimal(fractional) / currency.subunit_to_unit # Split the result and return whole and decimal parts separately fractional_units.to_s('F').split('.') end def format_decimal_part(value) return nil if currency.decimal_places == 0 && !Money.default_infinite_precision return nil if rules[:no_cents] return nil if rules[:no_cents_if_whole] && value.to_i == 0 # Pad value, making up for missing zeroes at the end value = value.ljust(currency.decimal_places, '0') # Drop trailing zeros if needed value.gsub!(/0*$/, '') if rules[:drop_trailing_zeros] value.empty? ? nil : value end def lookup(key) return rules[key] || DEFAULTS[key] if rules.has_key?(key) (Money.locale_backend && Money.locale_backend.lookup(key, currency)) || DEFAULTS[key] end def symbol_value_from(rules) if rules.has_key?(:symbol) if rules[:symbol] === true if rules[:disambiguate] && currency.disambiguate_symbol currency.disambiguate_symbol else money.symbol end elsif rules[:symbol] rules[:symbol] else "" end elsif rules[:html] || rules[:html_wrap] currency.html_entity == '' ? currency.symbol : currency.html_entity elsif rules[:disambiguate] && currency.disambiguate_symbol currency.disambiguate_symbol else money.symbol end end end end money-6.16.0/lib/money/money/arithmetic.rb0000644000004100000410000002350314054035243020470 0ustar www-datawww-dataclass Money module Arithmetic # Wrapper for coerced numeric values to distinguish # when numeric was on the 1st place in operation. CoercedNumeric = Struct.new(:value) do # Proxy #zero? method to skip unnecessary typecasts. See #- and #+. def zero? value.zero? end end # Returns a money object with changed polarity. # # @return [Money] # # @example # - Money.new(100) #=> # def -@ dup_with(fractional: -fractional) end # Checks whether two Money objects have the same currency and the same # amount. If Money objects have a different currency it will only be true # if the amounts are both zero. Checks against objects that are not Money or # a subclass will always return false. # # @param [Money] other_money Value to compare with. # # @return [Boolean] # # @example # Money.new(100).eql?(Money.new(101)) #=> false # Money.new(100).eql?(Money.new(100)) #=> true # Money.new(100, "USD").eql?(Money.new(100, "GBP")) #=> false # Money.new(0, "USD").eql?(Money.new(0, "EUR")) #=> true # Money.new(100).eql?("1.00") #=> false def eql?(other_money) if other_money.is_a?(Money) (fractional == other_money.fractional && currency == other_money.currency) || (fractional == 0 && other_money.fractional == 0) else false end end # Compares two Money objects. If money objects have a different currency it # will attempt to convert the currency. # # @param [Money] other Value to compare with. # # @return [Integer] # # @raise [TypeError] when other object is not Money # def <=>(other) unless other.is_a?(Money) return unless other.respond_to?(:zero?) && other.zero? return other.is_a?(CoercedNumeric) ? 0 <=> fractional : fractional <=> 0 end # Always allow comparison with zero if zero? || other.zero? return fractional <=> other.fractional end other = other.exchange_to(currency) fractional <=> other.fractional rescue Money::Bank::UnknownRate end # Uses Comparable's implementation but raises ArgumentError if non-zero # numeric value is given. def ==(other) if other.is_a?(Numeric) && !other.zero? raise ArgumentError, 'Money#== supports only zero numerics' end super end # Test if the amount is positive. Returns +true+ if the money amount is # greater than 0, +false+ otherwise. # # @return [Boolean] # # @example # Money.new(1).positive? #=> true # Money.new(0).positive? #=> false # Money.new(-1).positive? #=> false def positive? fractional > 0 end # Test if the amount is negative. Returns +true+ if the money amount is # less than 0, +false+ otherwise. # # @return [Boolean] # # @example # Money.new(-1).negative? #=> true # Money.new(0).negative? #=> false # Money.new(1).negative? #=> false def negative? fractional < 0 end # @method +(other) # Returns a new Money object containing the sum of the two operands' monetary # values. If +other_money+ has a different currency then its monetary value # is automatically exchanged to this object's currency using +exchange_to+. # # @param [Money] other Other +Money+ object to add. # # @return [Money] # # @example # Money.new(100) + Money.new(100) #=> # # # @method -(other) # Returns a new Money object containing the difference between the two # operands' monetary values. If +other_money+ has a different currency then # its monetary value is automatically exchanged to this object's currency # using +exchange_to+. # # @param [Money] other Other +Money+ object to subtract. # # @return [Money] # # @example # Money.new(100) - Money.new(99) #=> # [:+, :-].each do |op| non_zero_message = lambda do |value| "Can't add or subtract a non-zero #{value.class.name} value" end define_method(op) do |other| case other when Money other = other.exchange_to(currency) new_fractional = fractional.public_send(op, other.fractional) dup_with(fractional: new_fractional) when CoercedNumeric raise TypeError, non_zero_message.call(other.value) unless other.zero? dup_with(fractional: other.value.public_send(op, fractional)) when Numeric raise TypeError, non_zero_message.call(other) unless other.zero? self else raise TypeError, "Unsupported argument type: #{other.class.name}" end end end # Multiplies the monetary value with the given number and returns a new # +Money+ object with this monetary value and the same currency. # # Note that you can't multiply a Money object by an other +Money+ object. # # @param [Numeric] value Number to multiply by. # # @return [Money] The resulting money. # # @raise [TypeError] If +value+ is NOT a number. # # @example # Money.new(100) * 2 #=> # # def *(value) value = value.value if value.is_a?(CoercedNumeric) if value.is_a? Numeric dup_with(fractional: fractional * value) else raise TypeError, "Can't multiply a #{self.class.name} by a #{value.class.name}'s value" end end # Divides the monetary value with the given number and returns a new +Money+ # object with this monetary value and the same currency. # Can also divide by another +Money+ object to get a ratio. # # +Money/Numeric+ returns +Money+. +Money/Money+ returns +Float+. # # @param [Money, Numeric] value Number to divide by. # # @return [Money] The resulting money if you divide Money by a number. # @return [Float] The resulting number if you divide Money by a Money. # # @example # Money.new(100) / 10 #=> # # Money.new(100) / Money.new(10) #=> 10.0 # def /(value) if value.is_a?(self.class) fractional / as_d(value.exchange_to(currency).fractional).to_f else raise TypeError, 'Can not divide by Money' if value.is_a?(CoercedNumeric) dup_with(fractional: fractional / as_d(value)) end end # Synonym for +#/+. # # @param [Money, Numeric] value Number to divide by. # # @return [Money] The resulting money if you divide Money by a number. # @return [Float] The resulting number if you divide Money by a Money. # # @see #/ # def div(value) self / value end # Divide money by money or fixnum and return array containing quotient and # modulus. # # @param [Money, Integer] val Number to divmod by. # # @return [Array,Array] # # @example # Money.new(100).divmod(9) #=> [#, #] # Money.new(100).divmod(Money.new(9)) #=> [11, #] def divmod(val) if val.is_a?(Money) divmod_money(val) else divmod_other(val) end end def divmod_money(val) cents = val.exchange_to(currency).cents quotient, remainder = fractional.divmod(cents) [quotient, dup_with(fractional: remainder)] end private :divmod_money def divmod_other(val) quotient, remainder = fractional.divmod(as_d(val)) [dup_with(fractional: quotient), dup_with(fractional: remainder)] end private :divmod_other # Equivalent to +self.divmod(val)[1]+ # # @param [Money, Integer] val Number take modulo with. # # @return [Money] # # @example # Money.new(100).modulo(9) #=> # # Money.new(100).modulo(Money.new(9)) #=> # def modulo(val) divmod(val)[1] end # Synonym for +#modulo+. # # @param [Money, Integer] val Number take modulo with. # # @return [Money] # # @see #modulo def %(val) modulo(val) end # If different signs +self.modulo(val) - val+ otherwise +self.modulo(val)+ # # @param [Money, Integer] val Number to rake remainder with. # # @return [Money] # # @example # Money.new(100).remainder(9) #=> # def remainder(val) if val.is_a?(Money) && currency != val.currency val = val.exchange_to(currency) end if (fractional < 0 && val < 0) || (fractional > 0 && val > 0) self.modulo(val) else self.modulo(val) - (val.is_a?(Money) ? val : dup_with(fractional: val)) end end # Return absolute value of self as a new Money object. # # @return [Money] # # @example # Money.new(-100).abs #=> # def abs dup_with(fractional: fractional.abs) end # Test if the money amount is zero. # # @return [Boolean] # # @example # Money.new(100).zero? #=> false # Money.new(0).zero? #=> true def zero? fractional == 0 end # Test if the money amount is non-zero. Returns this money object if it is # non-zero, or nil otherwise, like +Numeric#nonzero?+. # # @return [Money, nil] # # @example # Money.new(100).nonzero? #=> # # Money.new(0).nonzero? #=> nil def nonzero? fractional != 0 ? self : nil end # Used to make Money instance handle the operations when arguments order is reversed # @return [Array] # # @example # 2 * Money.new(10) #=> # def coerce(other) [self, CoercedNumeric.new(other)] end end end money-6.16.0/lib/money/money/formatting_rules.rb0000644000004100000410000001037314054035243021724 0ustar www-datawww-data# encoding: UTF-8 class Money class FormattingRules def initialize(currency, *raw_rules) @currency = currency # support for old format parameters @rules = normalize_formatting_rules(raw_rules) @rules = default_formatting_rules.merge(@rules) unless @rules[:ignore_defaults] @rules = localize_formatting_rules(@rules) @rules = translate_formatting_rules(@rules) if @rules[:translate] @rules[:format] ||= determine_format_from_formatting_rules(@rules) @rules[:delimiter_pattern] ||= delimiter_pattern_rule(@rules) warn_about_deprecated_rules(@rules) end def [](key) @rules[key] end def has_key?(key) @rules.has_key? key end private attr_reader :currency # Cleans up formatting rules. # # @param [Hash] rules # # @return [Hash] def normalize_formatting_rules(rules) if rules.size == 0 rules = {} elsif rules.size == 1 rules = rules.pop rules = rules.dup if rules.is_a?(Hash) if rules.is_a?(Symbol) warn '[DEPRECATION] Use Hash when passing rules to Money#format.' rules = { rules => true } end end if !rules.include?(:decimal_mark) && rules.include?(:separator) rules[:decimal_mark] = rules[:separator] end if !rules.include?(:thousands_separator) && rules.include?(:delimiter) rules[:thousands_separator] = rules[:delimiter] end rules end def default_formatting_rules Money.default_formatting_rules || {} end def translate_formatting_rules(rules) begin rules[:symbol] = I18n.t currency.iso_code, scope: "number.currency.symbol", raise: true rescue I18n::MissingTranslationData # Do nothing end rules end def localize_formatting_rules(rules) if currency.iso_code == "JPY" && I18n.locale == :ja rules[:symbol] = "円" unless rules[:symbol] == false rules[:format] = '%n%u' end rules end def determine_format_from_formatting_rules(rules) return currency.format if currency.format && !rules.has_key?(:symbol_position) symbol_position = symbol_position_from(rules) if symbol_position == :before rules.fetch(:symbol_before_without_space, true) ? '%u%n' : '%u %n' else rules[:symbol_after_without_space] ? '%n%u' : '%n %u' end end def delimiter_pattern_rule(rules) if rules[:south_asian_number_formatting] # from http://blog.revathskumar.com/2014/11/regex-comma-seperated-indian-currency-format.html /(\d+?)(?=(\d\d)+(\d)(?!\d))(\.\d+)?/ else /(\d)(?=(?:\d{3})+(?:[^\d]{1}|$))/ end end def symbol_position_from(rules) if rules.has_key?(:symbol_position) if [:before, :after].include?(rules[:symbol_position]) return rules[:symbol_position] else raise ArgumentError, ":symbol_position must be ':before' or ':after'" end elsif currency.symbol_first? :before else :after end end def warn_about_deprecated_rules(rules) if rules.has_key?(:symbol_position) position = rules[:symbol_position] template = position == :before ? '%u %n' : '%n %u' warn "[DEPRECATION] `symbol_position: :#{position}` is deprecated - you can replace it with `format: #{template}`" end if rules.has_key?(:symbol_before_without_space) warn "[DEPRECATION] `symbol_before_without_space:` option is deprecated - you can replace it with `format: '%u%n'`" end if rules.has_key?(:symbol_after_without_space) warn "[DEPRECATION] `symbol_after_without_space:` option is deprecated - you can replace it with `format: '%n%u'`" end if rules.has_key?(:html) warn "[DEPRECATION] `html` is deprecated - use `html_wrap` instead. Please note that `html_wrap` will wrap all parts of currency and if you use `with_currency` option, currency element class changes from `currency` to `money-currency`." end if rules.has_key?(:html_wrap_symbol) warn "[DEPRECATION] `html_wrap_symbol` is deprecated - use `html_wrap` instead. Please note that `html_wrap` will wrap all parts of currency." end end end end money-6.16.0/lib/money/money/allocation.rb0000644000004100000410000000246514054035243020470 0ustar www-datawww-data# encoding: utf-8 class Money class Allocation # Splits a given amount in parts without losing pennies. # The left-over pennies will be distributed round-robin amongst the parts. This means that # parts listed first will likely receive more pennies than the ones listed later. # # The results should always add up to the original amount. # # The parts can be specified as: # Numeric — performs the split between a given number of parties evenely # Array — allocates the amounts proportionally to the given array # def self.generate(amount, parts, whole_amounts = true) parts = if parts.is_a?(Numeric) Array.new(parts, 1) elsif parts.all?(&:zero?) Array.new(parts.count, 1) else parts.dup end raise ArgumentError, 'need at least one party' if parts.empty? result = [] remaining_amount = amount until parts.empty? do parts_sum = parts.inject(0, :+) part = parts.pop current_split = 0 if parts_sum > 0 current_split = remaining_amount * part / parts_sum current_split = current_split.truncate if whole_amounts end result.unshift current_split remaining_amount -= current_split end result end end end money-6.16.0/lib/money/money/constructors.rb0000644000004100000410000000361214054035243021106 0ustar www-datawww-dataclass Money module Constructors # Create a new money object with value 0. # # @param [Currency, String, Symbol] currency The currency to use. # # @return [Money] # # @example # Money.empty #=> # def empty(currency = default_currency) new(0, currency) end alias_method :zero, :empty # Creates a new Money object of the given value, using the Canadian # dollar currency. # # @param [Integer] cents The cents value. # # @return [Money] # # @example # n = Money.ca_dollar(100) # n.cents #=> 100 # n.currency #=> # def ca_dollar(cents) new(cents, "CAD") end alias_method :cad, :ca_dollar # Creates a new Money object of the given value, using the American dollar # currency. # # @param [Integer] cents The cents value. # # @return [Money] # # @example # n = Money.us_dollar(100) # n.cents #=> 100 # n.currency #=> # def us_dollar(cents) new(cents, "USD") end alias_method :usd, :us_dollar # Creates a new Money object of the given value, using the Euro currency. # # @param [Integer] cents The cents value. # # @return [Money] # # @example # n = Money.euro(100) # n.cents #=> 100 # n.currency #=> # def euro(cents) new(cents, "EUR") end alias_method :eur, :euro # Creates a new Money object of the given value, in British pounds. # # @param [Integer] pence The pence value. # # @return [Money] # # @example # n = Money.pound_sterling(100) # n.fractional #=> 100 # n.currency #=> # def pound_sterling(pence) new(pence, "GBP") end alias_method :gbp, :pound_sterling end end money-6.16.0/lib/money/money/locale_backend.rb0000644000004100000410000000100714054035243021240 0ustar www-datawww-data# encoding: UTF-8 require 'money/locale_backend/errors' require 'money/locale_backend/legacy' require 'money/locale_backend/i18n' require 'money/locale_backend/currency' class Money module LocaleBackend BACKENDS = { legacy: Money::LocaleBackend::Legacy, i18n: Money::LocaleBackend::I18n, currency: Money::LocaleBackend::Currency }.freeze def self.find(name) raise Unknown, "Unknown locale backend: #{name}" unless BACKENDS.key?(name) BACKENDS[name].new end end end money-6.16.0/lib/money/bank/0000755000004100000410000000000014054035243015573 5ustar www-datawww-datamoney-6.16.0/lib/money/bank/base.rb0000644000004100000410000001054414054035243017036 0ustar www-datawww-dataclass Money # Provides classes that aid in the ability of exchange one currency with # another. module Bank # The lowest Money::Bank error class. # All Money::Bank errors should inherit from it. class Error < StandardError end # Raised when the bank doesn't know about the conversion rate # for specified currencies. class UnknownRate < Error end # Money::Bank::Base is the basic interface for creating a money exchange # object, also called Bank. # # A Bank is responsible for storing exchange rates, take a Money object as # input and returns the corresponding Money object converted into an other # currency. # # This class exists for aiding in the creating of other classes to exchange # money between different currencies. When creating a subclass you will # need to implement the following methods to exchange money between # currencies: # # - #exchange_with(Money) #=> Money # # See Money::Bank::VariableExchange for a real example. # # Also, you can extend +Money::Bank::VariableExchange+ instead of # +Money::Bank::Base+ if your bank implementation needs to store rates # internally. # # @abstract Subclass and override +#exchange_with+ to implement a custom # +Money::Bank+ class. You can also override +#setup+ instead of # +#initialize+ to setup initial variables, etc. class Base # Returns the singleton instance of the Base bank. # # @return [Money::Bank::Base] def self.instance @singleton ||= self.new end # The rounding method to use when exchanging rates. # # @return [Proc] attr_reader :rounding_method # Initializes a new +Money::Bank::Base+ object. An optional block can be # passed to dictate the rounding method that +#exchange_with+ can use. # # @yield [n] Optional block to use when rounding after exchanging one # currency for another. # @yieldparam [Float] n The resulting float after exchanging one currency # for another. # @yieldreturn [Integer] # # @return [Money::Bank::Base] # # @example # Money::Bank::Base.new #=> # # Money::Bank::Base.new {|n| # n.floor # } #=> #> def initialize(&block) @rounding_method = block setup end # Called after initialize. Subclasses can use this method to setup # variables, etc that they normally would in +#initialize+. # # @abstract Subclass and override +#setup+ to implement a custom # +Money::Bank+ class. # # @return [self] def setup end # Exchanges the given +Money+ object to a new +Money+ object in # +to_currency+. # # @abstract Subclass and override +#exchange_with+ to implement a custom # +Money::Bank+ class. # # @raise NotImplementedError # # @param [Money] from The +Money+ object to exchange from. # @param [Money::Currency, String, Symbol] to_currency The currency # string or object to exchange to. # @yield [n] Optional block to use to round the result after making # the exchange. # @yieldparam [Float] n The result after exchanging from one currency to # the other. # @yieldreturn [Integer] # # @return [Money] def exchange_with(from, to_currency, &block) raise NotImplementedError, "#exchange_with must be implemented" end # Given two currency strings or object, checks whether they're both the # same currency. Return +true+ if the currencies are the same, +false+ # otherwise. # # @param [Money::Currency, String, Symbol] currency1 The first currency # to compare. # @param [Money::Currency, String, Symbol] currency2 The second currency # to compare. # # @return [Boolean] # # @example # same_currency?("usd", "USD") #=> true # same_currency?("usd", "EUR") #=> false # same_currency?("usd", Currency.new("USD")) #=> true # same_currency?("usd", "USD") #=> true def same_currency?(currency1, currency2) Currency.wrap(currency1) == Currency.wrap(currency2) end end end end money-6.16.0/lib/money/bank/single_currency.rb0000644000004100000410000000161114054035243021312 0ustar www-datawww-datarequire 'money/bank/base' class Money module Bank # Raised when trying to exchange currencies class DifferentCurrencyError < Error; end # Class to ensure client code is operating in a single currency # by raising if an exchange attempts to happen. # # This is useful when an application uses multiple currencies but # it usually deals with only one currency at a time so any arithmetic # where exchanges happen are erroneous. Using this as the default bank # means that that these mistakes don't silently do the wrong thing. class SingleCurrency < Base # Raises a DifferentCurrencyError to remove possibility of accidentally # exchanging currencies def exchange_with(from, to_currency, &block) raise DifferentCurrencyError, "No exchanging of currencies allowed: #{from} #{from.currency} to #{to_currency}" end end end end money-6.16.0/lib/money/bank/variable_exchange.rb0000644000004100000410000002361414054035243021555 0ustar www-datawww-datarequire 'money/bank/base' require 'money/rates_store/memory' require 'json' require 'yaml' class Money module Bank # Thrown when an unknown rate format is requested. class UnknownRateFormat < StandardError; end # Class for aiding in exchanging money between different currencies. By # default, the +Money+ class uses an object of this class (accessible # through +Money#bank+) for performing currency exchanges. # # By default, +Money::Bank::VariableExchange+ has no knowledge about # conversion rates. One must manually specify them with +add_rate+, after # which one can perform exchanges with +#exchange_with+. # # Exchange rates are stored in memory using +Money::RatesStore::Memory+ by default. # Pass custom rates stores for other types of storage (file, database, etc) # # @example # bank = Money::Bank::VariableExchange.new # bank.add_rate("USD", "CAD", 1.24515) # bank.add_rate("CAD", "USD", 0.803115) # # c1 = Money.new(100_00, "USD") # c2 = Money.new(100_00, "CAD") # # # Exchange 100 USD to CAD: # bank.exchange_with(c1, "CAD") #=> # # # # Exchange 100 CAD to USD: # bank.exchange_with(c2, "USD") #=> # # # # With custom exchange rates storage # redis_store = MyCustomRedisStore.new(host: 'localhost:6379') # bank = Money::Bank::VariableExchange.new(redis_store) # # Store rates in redis # bank.add_rate 'USD', 'CAD', 0.98 # # Get rate from redis # bank.get_rate 'USD', 'CAD' class VariableExchange < Base attr_reader :mutex # Available formats for importing/exporting rates. RATE_FORMATS = [:json, :ruby, :yaml].freeze SERIALIZER_SEPARATOR = '_TO_'.freeze FORMAT_SERIALIZERS = {json: JSON, ruby: Marshal, yaml: YAML}.freeze # Initializes a new +Money::Bank::VariableExchange+ object. # It defaults to using an in-memory, thread safe store instance for # storing exchange rates. # # @param [RateStore] st An exchange rate store, used to persist exchange rate pairs. # @yield [n] Optional block to use when rounding after exchanging one # currency for another. See +Money::bank::base+ def initialize(st = Money::RatesStore::Memory.new, &block) @store = st super(&block) end def store @store.is_a?(String) ? Object.const_get(@store) : @store end def marshal_dump [store.marshal_dump, @rounding_method] end def marshal_load(arr) store_info = arr[0] @store = store_info.shift.new(*store_info) @rounding_method = arr[1] end # Exchanges the given +Money+ object to a new +Money+ object in # +to_currency+. # # @param [Money] from # The +Money+ object to exchange. # @param [Currency, String, Symbol] to_currency # The currency to exchange to. # # @yield [n] Optional block to use when rounding after exchanging one # currency for another. # @yieldparam [Float] n The resulting float after exchanging one currency # for another. # @yieldreturn [Integer] # # @return [Money] # # @raise +Money::Bank::UnknownRate+ if the conversion rate is unknown. # # @example # bank = Money::Bank::VariableExchange.new # bank.add_rate("USD", "CAD", 1.24515) # bank.add_rate("CAD", "USD", 0.803115) # # c1 = Money.new(100_00, "USD") # c2 = Money.new(100_00, "CAD") # # # Exchange 100 USD to CAD: # bank.exchange_with(c1, "CAD") #=> # # # # Exchange 100 CAD to USD: # bank.exchange_with(c2, "USD") #=> # def exchange_with(from, to_currency, &block) to_currency = Currency.wrap(to_currency) if from.currency == to_currency from else if rate = get_rate(from.currency, to_currency) fractional = calculate_fractional(from, to_currency) from.dup_with( fractional: exchange(fractional, rate, &block), currency: to_currency, bank: self ) else raise UnknownRate, "No conversion rate known for '#{from.currency.iso_code}' -> '#{to_currency}'" end end end def calculate_fractional(from, to_currency) BigDecimal(from.fractional.to_s) / ( BigDecimal(from.currency.subunit_to_unit.to_s) / BigDecimal(to_currency.subunit_to_unit.to_s) ) end def exchange(fractional, rate, &block) ex = fractional * BigDecimal(rate.to_s) if block_given? yield ex elsif @rounding_method @rounding_method.call(ex) else ex end end # Registers a conversion rate and returns it (uses +#set_rate+). # Delegates to +Money::RatesStore::Memory+ # # @param [Currency, String, Symbol] from Currency to exchange from. # @param [Currency, String, Symbol] to Currency to exchange to. # @param [Numeric] rate Rate to use when exchanging currencies. # # @return [Numeric] # # @example # bank = Money::Bank::VariableExchange.new # bank.add_rate("USD", "CAD", 1.24515) # bank.add_rate("CAD", "USD", 0.803115) def add_rate(from, to, rate) set_rate(from, to, rate) end # Set the rate for the given currencies. # access. # Delegates to +Money::RatesStore::Memory+ # # @param [Currency, String, Symbol] from Currency to exchange from. # @param [Currency, String, Symbol] to Currency to exchange to. # @param [Numeric] rate Rate to use when exchanging currencies. # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only. # # @return [Numeric] # # @example # bank = Money::Bank::VariableExchange.new # bank.set_rate("USD", "CAD", 1.24515) # bank.set_rate("CAD", "USD", 0.803115) def set_rate(from, to, rate, opts = {}) store.add_rate(Currency.wrap(from).iso_code, Currency.wrap(to).iso_code, rate) end # Retrieve the rate for the given currencies. # data access. # Delegates to +Money::RatesStore::Memory+ # # @param [Currency, String, Symbol] from Currency to exchange from. # @param [Currency, String, Symbol] to Currency to exchange to. # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only. # # @return [Numeric] # # @example # bank = Money::Bank::VariableExchange.new # bank.set_rate("USD", "CAD", 1.24515) # bank.set_rate("CAD", "USD", 0.803115) # # bank.get_rate("USD", "CAD") #=> 1.24515 # bank.get_rate("CAD", "USD") #=> 0.803115 def get_rate(from, to, opts = {}) store.get_rate(Currency.wrap(from).iso_code, Currency.wrap(to).iso_code) end # Return the known rates as a string in the format specified. If +file+ # is given will also write the string out to the file specified. # Available formats are +:json+, +:ruby+ and +:yaml+. # # @param [Symbol] format Request format for the resulting string. # @param [String] file Optional file location to write the rates to. # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only. # # @return [String] # # @raise +Money::Bank::UnknownRateFormat+ if format is unknown. # # @example # bank = Money::Bank::VariableExchange.new # bank.set_rate("USD", "CAD", 1.24515) # bank.set_rate("CAD", "USD", 0.803115) # # s = bank.export_rates(:json) # s #=> "{\"USD_TO_CAD\":1.24515,\"CAD_TO_USD\":0.803115}" def export_rates(format, file = nil, opts = {}) raise Money::Bank::UnknownRateFormat unless RATE_FORMATS.include?(format) store.transaction do s = FORMAT_SERIALIZERS[format].dump(rates) unless file.nil? File.open(file, "w") {|f| f.write(s) } end s end end # This should be deprecated. def rates store.each_rate.each_with_object({}) do |(from,to,rate),hash| hash[[from, to].join(SERIALIZER_SEPARATOR)] = rate end end # Loads rates provided in +s+ given the specified format. Available # formats are +:json+, +:ruby+ and +:yaml+. # Delegates to +Money::RatesStore::Memory+ # # @param [Symbol] format The format of +s+. # @param [String] s The rates string. # @param [Hash] opts Options hash to set special parameters. Backwards compatibility only. # # @return [self] # # @raise +Money::Bank::UnknownRateFormat+ if format is unknown. # # @example # s = "{\"USD_TO_CAD\":1.24515,\"CAD_TO_USD\":0.803115}" # bank = Money::Bank::VariableExchange.new # bank.import_rates(:json, s) # # bank.get_rate("USD", "CAD") #=> 1.24515 # bank.get_rate("CAD", "USD") #=> 0.803115 def import_rates(format, s, opts = {}) raise Money::Bank::UnknownRateFormat unless RATE_FORMATS.include?(format) if format == :ruby warn '[WARNING] Using :ruby format when importing rates is potentially unsafe and ' \ 'might lead to remote code execution via Marshal.load deserializer. Consider using ' \ 'safe alternatives such as :json and :yaml.' end store.transaction do data = FORMAT_SERIALIZERS[format].load(s) data.each do |key, rate| from, to = key.split(SERIALIZER_SEPARATOR) store.add_rate from, to, rate end end self end end end end money-6.16.0/lib/money/money.rb0000644000004100000410000005124014054035243016336 0ustar www-datawww-data# encoding: utf-8 require "money/bank/variable_exchange" require "money/bank/single_currency" require "money/money/arithmetic" require "money/money/constructors" require "money/money/formatter" require "money/money/allocation" require "money/money/locale_backend" # "Money is any object or record that is generally accepted as payment for # goods and services and repayment of debts in a given socio-economic context # or country." -Wikipedia # # An instance of Money represents an amount of a specific currency. # # Money is a value object and should be treated as immutable. # # @see http://en.wikipedia.org/wiki/Money class Money include Comparable include Money::Arithmetic extend Constructors # Raised when smallest denomination of a currency is not defined class UndefinedSmallestDenomination < StandardError; end # Convenience method for fractional part of the amount. Synonym of #fractional # # @return [Integer] when infinite_precision is false # @return [BigDecimal] when infinite_precision is true # # @see infinite_precision def cents fractional end # The value of the monetary amount represented in the fractional or subunit # of the currency. # # For example, in the US dollar currency the fractional unit is cents, and # there are 100 cents in one US dollar. So given the Money representation of # one US dollar, the fractional interpretation is 100. # # Another example is that of the Kuwaiti dinar. In this case the fractional # unit is the fils and there 1000 fils to one Kuwaiti dinar. So given the # Money representation of one Kuwaiti dinar, the fractional interpretation is # 1000. # # @return [Integer] when infinite_precision is false # @return [BigDecimal] when infinite_precision is true # # @see infinite_precision def fractional # Ensure we have a BigDecimal. If the Money object is created # from YAML, @fractional can end up being set to a Float. fractional = as_d(@fractional) return_value(fractional) end # Round a given amount of money to the nearest possible amount in cash value. For # example, in Swiss franc (CHF), the smallest possible amount of cash value is # CHF 0.05. Therefore, this method rounds CHF 0.07 to CHF 0.05, and CHF 0.08 to # CHF 0.10. # # @return [Integer] when infinite_precision is false # @return [BigDecimal] when infinite_precision is true # # @see infinite_precision def round_to_nearest_cash_value unless self.currency.smallest_denomination raise UndefinedSmallestDenomination, 'Smallest denomination of this currency is not defined' end fractional = as_d(@fractional) smallest_denomination = as_d(self.currency.smallest_denomination) rounded_value = (fractional / smallest_denomination).round(0, self.class.rounding_mode) * smallest_denomination return_value(rounded_value) end # @!attribute [r] currency # @return [Currency] The money's currency. # @!attribute [r] bank # @return [Money::Bank::Base] The +Money::Bank+-based object which currency # exchanges are performed with. attr_reader :currency, :bank # Class Methods class << self # @!attribute [rw] default_bank # Used to set a default bank for currency exchange. # # Each Money object is associated with a bank # object, which is responsible for currency exchange. This property # allows you to specify the default bank object. The default value for # this property is an instance of +Bank::VariableExchange.+ It allows # one to specify custom exchange rates. # # @return [Money::Bank::Base] # # @!attribute default_formatting_rules # Used to define a default hash of rules for every time # +Money#format+ is called. Rules provided on method call will be # merged with the default ones. To overwrite a rule, just provide the # intended value while calling +format+. # # @see Money::Formatter#initialize Money::Formatter for more details # # @example # Money.default_formatting_rules = { display_free: true } # Money.new(0, "USD").format # => "free" # Money.new(0, "USD").format(display_free: false) # => "$0.00" # # @return [Hash] # # @!attribute [rw] use_i18n # Used to disable i18n even if it's used by other components of your app. # # @return [Boolean] # # @!attribute [rw] default_infinite_precision # @return [Boolean] Use this to enable infinite precision cents as the # global default # # @!attribute [rw] conversion_precision # Used to specify precision for converting Rational to BigDecimal # # @return [Integer] attr_accessor :default_formatting_rules, :default_infinite_precision, :conversion_precision attr_reader :use_i18n, :locale_backend attr_writer :default_bank def infinite_precision warn '[DEPRECATION] `Money.infinite_precision` is deprecated - use `Money.default_infinite_precision` instead' default_infinite_precision end def infinite_precision=(value) warn '[DEPRECATION] `Money.infinite_precision=` is deprecated - use `Money.default_infinite_precision= ` instead' self.default_infinite_precision = value end end # @!attribute default_currency # @return [Money::Currency] The default currency, which is used when # +Money.new+ is called without an explicit currency argument. The # default value is Currency.new("USD"). The value must be a valid # +Money::Currency+ instance. def self.default_currency if @using_deprecated_default_currency warn '[WARNING] The default currency will change from `USD` to `nil` in the next major release. Make ' \ 'sure to set it explicitly using `Money.default_currency=` to avoid potential issues' @using_deprecated_default_currency = false end if @default_currency.respond_to?(:call) Money::Currency.new(@default_currency.call) else Money::Currency.new(@default_currency) end end def self.default_currency=(currency) @using_deprecated_default_currency = false @default_currency = currency end def self.default_bank if @default_bank.respond_to?(:call) @default_bank.call else @default_bank end end def self.locale_backend=(value) @locale_backend = value ? LocaleBackend.find(value) : nil end # @attr_writer rounding_mode Use this to specify the rounding mode def self.rounding_mode=(new_rounding_mode) @using_deprecated_default_rounding_mode = false @rounding_mode = new_rounding_mode end def self.use_i18n=(value) if value warn '[DEPRECATION] `use_i18n` is deprecated - use `Money.locale_backend = :i18n` instead for locale based formatting' else warn '[DEPRECATION] `use_i18n` is deprecated - use `Money.locale_backend = :currency` instead for currency based formatting' end @use_i18n = value end def self.setup_defaults # Set the default bank for creating new +Money+ objects. self.default_bank = Bank::VariableExchange.instance # Set the default currency for creating new +Money+ object. self.default_currency = Currency.new("USD") @using_deprecated_default_currency = true # Default to using i18n @use_i18n = true # Default to using legacy locale backend self.locale_backend = :legacy # Default to not using infinite precision cents self.default_infinite_precision = false # Default to bankers rounding self.rounding_mode = BigDecimal::ROUND_HALF_EVEN @using_deprecated_default_rounding_mode = true # Default the conversion of Rationals precision to 16 self.conversion_precision = 16 end def self.inherited(base) base.setup_defaults end setup_defaults # Use this to return the rounding mode. # # @param [BigDecimal::ROUND_MODE] mode # # @return [BigDecimal::ROUND_MODE] rounding mode def self.rounding_mode(mode = nil) if mode warn "[DEPRECATION] calling `rounding_mode` with a block is deprecated. Please use `.with_rounding_mode` instead." return with_rounding_mode(mode) { yield } end return Thread.current[:money_rounding_mode] if Thread.current[:money_rounding_mode] if @using_deprecated_default_rounding_mode warn '[WARNING] The default rounding mode will change from `ROUND_HALF_EVEN` to `ROUND_HALF_UP` in the ' \ 'next major release. Set it explicitly using `Money.rounding_mode=` to avoid potential problems.' @using_deprecated_default_rounding_mode = false end @rounding_mode end # Temporarily changes the rounding mode in a given block. # # @param [BigDecimal::ROUND_MODE] mode # # @yield The block within which rounding mode will be changed. Its return # value will also be the return value of the whole method. # # @return [Object] block results # # @example # fee = Money.with_rounding_mode(BigDecimal::ROUND_HALF_UP) do # Money.new(1200) * BigDecimal('0.029') # end def self.with_rounding_mode(mode) Thread.current[:money_rounding_mode] = mode yield ensure Thread.current[:money_rounding_mode] = nil end # Adds a new exchange rate to the default bank and return the rate. # # @param [Currency, String, Symbol] from_currency Currency to exchange from. # @param [Currency, String, Symbol] to_currency Currency to exchange to. # @param [Numeric] rate Rate to exchange with. # # @return [Numeric] # # @example # Money.add_rate("USD", "CAD", 1.25) #=> 1.25 def self.add_rate(from_currency, to_currency, rate) Money.default_bank.add_rate(from_currency, to_currency, rate) end # Sets the default bank to be a SingleCurrency bank that raises on # currency exchange. Useful when apps operate in a single currency at a time. def self.disallow_currency_conversion! self.default_bank = Bank::SingleCurrency.instance end # Creates a new Money object of value given in the +unit+ of the given # +currency+. # # @param [Numeric] amount The numerical value of the money. # @param [Currency, String, Symbol] currency The currency format. # @param [Hash] options Optional settings for the new Money instance # @option [Money::Bank::*] :bank The exchange bank to use. # # @example # Money.from_amount(23.45, "USD") # => # # Money.from_amount(23.45, "JPY") # => # # # @return [Money] # # @see #initialize def self.from_amount(amount, currency = default_currency, options = {}) raise ArgumentError, "'amount' must be numeric" unless Numeric === amount currency = Currency.wrap(currency) || Money.default_currency value = amount.to_d * currency.subunit_to_unit new(value, currency, options) end class << self alias_method :from_cents, :new end # Creates a new Money object of value given in the # +fractional unit+ of the given +currency+. # # Alternatively you can use the convenience # methods like {Money.ca_dollar} and {Money.us_dollar}. # # @param [Object] obj Either the fractional value of the money, # a Money object, or a currency. (If passed a currency as the first # argument, a Money will be created in that currency with fractional value # = 0. # @param [Currency, String, Symbol] currency The currency format. # @param [Hash] options Optional settings for the new Money instance # @option [Money::Bank::*] :bank The exchange bank to use. # # @return [Money] # # @example # Money.new(100) #=> # # Money.new(100, "USD") #=> # # Money.new(100, "EUR") #=> # # def initialize( obj, currency = Money.default_currency, options = {}) # For backwards compatability, if options is not a Hash, treat it as a bank parameter unless options.is_a?(Hash) options = { bank: options } end @fractional = as_d(obj.respond_to?(:fractional) ? obj.fractional : obj) @currency = obj.respond_to?(:currency) ? obj.currency : Currency.wrap(currency) @currency ||= Money.default_currency @bank = obj.respond_to?(:bank) ? obj.bank : options[:bank] @bank ||= Money.default_bank # BigDecimal can be Infinity and NaN, money of that amount does not make sense raise ArgumentError, 'must be initialized with a finite value' unless @fractional.finite? end # Assuming using a currency using dollars: # Returns the value of the money in dollars, # instead of in the fractional unit cents. # # Synonym of #amount # # @return [BigDecimal] # # @example # Money.new(1_00, "USD").dollars # => BigDecimal("1.00") # # @see #amount # @see #to_d # @see #cents # def dollars amount end # Returns the numerical value of the money # # @return [BigDecimal] # # @example # Money.new(1_00, "USD").amount # => BigDecimal("1.00") # # @see #to_d # @see #fractional # def amount to_d end # Return string representation of currency object # # @return [String] # # @example # Money.new(100, :USD).currency_as_string #=> "USD" def currency_as_string warn "[DEPRECATION] `currency_as_string` is deprecated. Please use `.currency.to_s` instead." currency.to_s end # Set currency object using a string # # @param [String] val The currency string. # # @return [Money::Currency] # # @example # Money.new(100).currency_as_string("CAD") #=> # def currency_as_string=(val) warn "[DEPRECATION] `currency_as_string=` is deprecated - Money instances are immutable." \ " Please use `with_currency` instead." @currency = Currency.wrap(val) end # Returns a Integer hash value based on the +fractional+ and +currency+ attributes # in order to use functions like & (intersection), group_by, etc. # # @return [Integer] # # @example # Money.new(100).hash #=> 908351 def hash [fractional.hash, currency.hash].hash end # Uses +Currency#symbol+. If +nil+ is returned, defaults to "¤". # # @return [String] # # @example # Money.new(100, "USD").symbol #=> "$" def symbol currency.symbol || "¤" end # Common inspect function # # @return [String] def inspect "#<#{self.class.name} fractional:#{fractional} currency:#{currency}>" end # Returns the amount of money as a string. # # @return [String] # # @example # Money.ca_dollar(100).to_s #=> "1.00" def to_s format thousands_separator: '', no_cents_if_whole: currency.decimal_places == 0, symbol: false, ignore_defaults: true end # Return the amount of money as a BigDecimal. # # @return [BigDecimal] # # @example # Money.us_dollar(1_00).to_d #=> BigDecimal("1.00") def to_d as_d(fractional) / as_d(currency.subunit_to_unit) end # Return the amount of money as a Integer. # # @return [Integer] # # @example # Money.us_dollar(1_00).to_i #=> 1 def to_i to_d.to_i end # Return the amount of money as a float. Floating points cannot guarantee # precision. Therefore, this function should only be used when you no longer # need to represent currency or working with another system that requires # floats. # # @return [Float] # # @example # Money.us_dollar(100).to_f #=> 1.0 def to_f to_d.to_f end # Returns a new Money instance in a given currency leaving the amount intact # and not performing currency conversion. # # @param [Currency, String, Symbol] new_currency Currency of the new object. # # @return [self] def with_currency(new_currency) new_currency = Currency.wrap(new_currency) if !new_currency || currency == new_currency self else dup_with(currency: new_currency) end end # Conversion to +self+. # # @return [self] def to_money(given_currency = nil) given_currency = Currency.wrap(given_currency) if given_currency.nil? || self.currency == given_currency self else exchange_to(given_currency) end end # Receive the amount of this money object in another Currency. # # @param [Currency, String, Symbol] other_currency Currency to exchange to. # # @yield [n] Optional block to use when rounding after exchanging one currency # for another. # @yieldparam [Float] n The resulting float after exchanging one currency for # another. # @yieldreturn [Integer] # # @return [Money] # # @example # Money.new(2000, "USD").exchange_to("EUR") # Money.new(2000, "USD").exchange_to("EUR") {|x| x.round} # Money.new(2000, "USD").exchange_to(Currency.new("EUR")) def exchange_to(other_currency, &rounding_method) other_currency = Currency.wrap(other_currency) if self.currency == other_currency self else @bank.exchange_with(self, other_currency, &rounding_method) end end # Receive a money object with the same amount as the current Money object # in United States dollar. # # @return [Money] # # @example # n = Money.new(100, "CAD").as_us_dollar # n.currency #=> # def as_us_dollar exchange_to("USD") end # Receive a money object with the same amount as the current Money object # in Canadian dollar. # # @return [Money] # # @example # n = Money.new(100, "USD").as_ca_dollar # n.currency #=> # def as_ca_dollar exchange_to("CAD") end # Receive a money object with the same amount as the current Money object # in euro. # # @return [Money] # # @example # n = Money.new(100, "USD").as_euro # n.currency #=> # def as_euro exchange_to("EUR") end # Splits a given amount in parts without losing pennies. The left-over pennies will be # distributed round-robin amongst the parties. This means that parts listed first will likely # receive more pennies than ones listed later. # # Pass [2, 1, 1] as input to give twice as much to part1 as part2 or # part3 which results in 50% of the cash to party1, 25% to part2, and 25% to part3. Passing a # number instead of an array will split the amount evenly (without losing pennies when rounding). # # @param [Array, Numeric] parts how amount should be distributed to parts # # @return [Array] # # @example # Money.new(5, "USD").allocate([3, 7]) #=> [Money.new(2), Money.new(3)] # Money.new(100, "USD").allocate([1, 1, 1]) #=> [Money.new(34), Money.new(33), Money.new(33)] # Money.new(100, "USD").allocate(2) #=> [Money.new(50), Money.new(50)] # Money.new(100, "USD").allocate(3) #=> [Money.new(34), Money.new(33), Money.new(33)] # def allocate(parts) amounts = Money::Allocation.generate(fractional, parts, !Money.default_infinite_precision) amounts.map { |amount| dup_with(fractional: amount) } end alias_method :split, :allocate # Round the monetary amount to smallest unit of coinage. # # @note # This method is only useful when operating with infinite_precision turned # on. Without infinite_precision values are rounded to the smallest unit of # coinage automatically. # # @return [Money] # # @example # Money.new(10.1, 'USD').round #=> Money.new(10, 'USD') # # @see # Money.default_infinite_precision # def round(rounding_mode = self.class.rounding_mode, rounding_precision = 0) rounded_amount = as_d(@fractional).round(rounding_precision, rounding_mode) dup_with(fractional: rounded_amount) end # Creates a formatted price string according to several rules. # # @param [Hash] rules See {Money::Formatter Money::Formatter} for the list of formatting options # # @return [String] # def format(*rules) Money::Formatter.new(self, *rules).to_s end # Returns a thousands separator according to the locale # # @return [String] # def thousands_separator (locale_backend && locale_backend.lookup(:thousands_separator, currency)) || Money::Formatter::DEFAULTS[:thousands_separator] end # Returns a decimal mark according to the locale # # @return [String] # def decimal_mark (locale_backend && locale_backend.lookup(:decimal_mark, currency)) || Money::Formatter::DEFAULTS[:decimal_mark] end def dup_with(options = {}) self.class.new( options[:fractional] || fractional, options[:currency] || currency, bank: options[:bank] || bank ) end private def as_d(num) if num.respond_to?(:to_d) num.is_a?(Rational) ? num.to_d(self.class.conversion_precision) : num.to_d else BigDecimal(num.to_s.empty? ? 0 : num.to_s) end end def return_value(value) if self.class.default_infinite_precision value else value.round(0, self.class.rounding_mode).to_i end end def locale_backend self.class.locale_backend end end money-6.16.0/lib/money/locale_backend/0000755000004100000410000000000014054035243017566 5ustar www-datawww-datamoney-6.16.0/lib/money/locale_backend/currency.rb0000644000004100000410000000033514054035243021746 0ustar www-datawww-datarequire 'money/locale_backend/base' class Money module LocaleBackend class Currency < Base def lookup(key, currency) currency.public_send(key) if currency.respond_to?(key) end end end end money-6.16.0/lib/money/locale_backend/i18n.rb0000644000004100000410000000112014054035243020664 0ustar www-datawww-datarequire 'money/locale_backend/base' class Money module LocaleBackend class I18n < Base KEY_MAP = { thousands_separator: :delimiter, decimal_mark: :separator, symbol: :unit }.freeze def initialize raise NotSupported, 'I18n not found' unless defined?(::I18n) end def lookup(key, _) i18n_key = KEY_MAP[key] ::I18n.t i18n_key, scope: 'number.currency.format', raise: true rescue ::I18n::MissingTranslationData ::I18n.t i18n_key, scope: 'number.format', default: nil end end end end money-6.16.0/lib/money/locale_backend/errors.rb0000644000004100000410000000020014054035243021417 0ustar www-datawww-dataclass Money module LocaleBackend class NotSupported < StandardError; end class Unknown < ArgumentError; end end end money-6.16.0/lib/money/locale_backend/base.rb0000644000004100000410000000015014054035243021021 0ustar www-datawww-datarequire 'money/locale_backend/errors' class Money module LocaleBackend class Base; end end end money-6.16.0/lib/money/locale_backend/legacy.rb0000644000004100000410000000136414054035243021363 0ustar www-datawww-datarequire 'money/locale_backend/base' require 'money/locale_backend/i18n' class Money module LocaleBackend class Legacy < Base def initialize raise NotSupported, 'I18n not found' if Money.use_i18n && !defined?(::I18n) end def lookup(key, currency) warn '[DEPRECATION] You are using the default localization behaviour that will change in the next major release. Find out more - https://github.com/RubyMoney/money#deprecation' if Money.use_i18n i18n_backend.lookup(key, nil) || currency.public_send(key) else currency.public_send(key) end end private def i18n_backend @i18n_backend ||= Money::LocaleBackend::I18n.new end end end end money-6.16.0/lib/money/currency/0000755000004100000410000000000014054035243016512 5ustar www-datawww-datamoney-6.16.0/lib/money/currency/heuristics.rb0000644000004100000410000000032714054035243021223 0ustar www-datawww-data# encoding: utf-8 class Money class Currency module Heuristics def analyze(str) raise StandardError, 'Heuristics deprecated, add `gem "money-heuristics"` to Gemfile' end end end end money-6.16.0/lib/money/currency/loader.rb0000644000004100000410000000144014054035243020304 0ustar www-datawww-dataclass Money class Currency module Loader DATA_PATH = File.expand_path("../../../../config", __FILE__) class << self # Loads and returns the currencies stored in JSON files in the config directory. # # @return [Hash] def load_currencies currencies = parse_currency_file("currency_iso.json") currencies.merge! parse_currency_file("currency_non_iso.json") currencies.merge! parse_currency_file("currency_backwards_compatible.json") end private def parse_currency_file(filename) json = File.read("#{DATA_PATH}/#{filename}") json.force_encoding(::Encoding::UTF_8) if defined?(::Encoding) JSON.parse(json, symbolize_names: true) end end end end end money-6.16.0/lib/money.rb0000644000004100000410000000017314054035243015206 0ustar www-datawww-datarequire "bigdecimal" require "bigdecimal/util" require "set" require "i18n" require "money/currency" require "money/money" money-6.16.0/config/0000755000004100000410000000000014054035243014230 5ustar www-datawww-datamoney-6.16.0/config/currency_non_iso.json0000644000004100000410000000612114054035243020501 0ustar www-datawww-data{ "bch": { "priority": 100, "iso_code": "BCH", "name": "Bitcoin Cash", "symbol": "₿", "disambiguate_symbol": "₿CH", "alternate_symbols": ["BCH"], "subunit": "Satoshi", "subunit_to_unit": 100000000, "symbol_first": false, "format": "%n %u", "html_entity": "₿", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "", "smallest_denomination": 1 }, "btc": { "priority": 100, "iso_code": "BTC", "name": "Bitcoin", "symbol": "₿", "alternate_symbols": [], "subunit": "Satoshi", "subunit_to_unit": 100000000, "symbol_first": true, "html_entity": "₿", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "", "smallest_denomination": 1 }, "jep": { "priority": 100, "iso_code": "JEP", "name": "Jersey Pound", "symbol": "£", "disambiguate_symbol": "JEP", "alternate_symbols": [], "subunit": "Penny", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "", "smallest_denomination": 1 }, "ggp": { "priority": 100, "iso_code": "GGP", "name": "Guernsey Pound", "symbol": "£", "disambiguate_symbol": "GGP", "alternate_symbols": [], "subunit": "Penny", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "", "smallest_denomination": 1 }, "imp": { "priority": 100, "iso_code": "IMP", "name": "Isle of Man Pound", "symbol": "£", "disambiguate_symbol": "IMP", "alternate_symbols": ["M£"], "subunit": "Penny", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "", "smallest_denomination": 1 }, "xfu": { "priority": 100, "iso_code": "XFU", "name": "UIC Franc", "symbol": "", "disambiguate_symbol": "XFU", "alternate_symbols": [], "subunit": "", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "", "smallest_denomination": "" }, "gbx": { "priority": 100, "iso_code": "GBX", "name": "British Penny", "symbol": "", "disambiguate_symbol": "GBX", "alternate_symbols": [], "subunit": "", "subunit_to_unit": 1, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "", "smallest_denomination": 1 }, "cnh": { "priority": 100, "iso_code": "CNH", "name": "Chinese Renminbi Yuan Offshore", "symbol": "¥", "disambiguate_symbol": "CNH", "alternate_symbols": ["CN¥", "元", "CN元"], "subunit": "Fen", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "¥", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "", "smallest_denomination": 1 } } money-6.16.0/config/currency_iso.json0000644000004100000410000020120214054035243017624 0ustar www-datawww-data{ "aed": { "priority": 100, "iso_code": "AED", "name": "United Arab Emirates Dirham", "symbol": "د.إ", "alternate_symbols": ["DH", "Dhs"], "subunit": "Fils", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "784", "smallest_denomination": 25 }, "afn": { "priority": 100, "iso_code": "AFN", "name": "Afghan Afghani", "symbol": "؋", "alternate_symbols": ["Af", "Afs"], "subunit": "Pul", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "971", "smallest_denomination": 100 }, "all": { "priority": 100, "iso_code": "ALL", "name": "Albanian Lek", "symbol": "L", "disambiguate_symbol": "Lek", "alternate_symbols": ["Lek"], "subunit": "Qintar", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "008", "smallest_denomination": 100 }, "amd": { "priority": 100, "iso_code": "AMD", "name": "Armenian Dram", "symbol": "դր.", "alternate_symbols": ["dram"], "subunit": "Luma", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "051", "smallest_denomination": 10 }, "ang": { "priority": 100, "iso_code": "ANG", "name": "Netherlands Antillean Gulden", "symbol": "ƒ", "alternate_symbols": ["NAƒ", "NAf", "f"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "ƒ", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "532", "smallest_denomination": 1 }, "aoa": { "priority": 100, "iso_code": "AOA", "name": "Angolan Kwanza", "symbol": "Kz", "alternate_symbols": [], "subunit": "Cêntimo", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "973", "smallest_denomination": 10 }, "ars": { "priority": 100, "iso_code": "ARS", "name": "Argentine Peso", "symbol": "$", "disambiguate_symbol": "$m/n", "alternate_symbols": ["$m/n", "m$n"], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "032", "smallest_denomination": 1 }, "aud": { "priority": 4, "iso_code": "AUD", "name": "Australian Dollar", "symbol": "$", "disambiguate_symbol": "A$", "alternate_symbols": ["A$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "036", "smallest_denomination": 5 }, "awg": { "priority": 100, "iso_code": "AWG", "name": "Aruban Florin", "symbol": "ƒ", "alternate_symbols": ["Afl"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "ƒ", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "533", "smallest_denomination": 5 }, "azn": { "priority": 100, "iso_code": "AZN", "name": "Azerbaijani Manat", "symbol": "₼", "alternate_symbols": ["m", "man"], "subunit": "Qəpik", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "944", "smallest_denomination": 1 }, "bam": { "priority": 100, "iso_code": "BAM", "name": "Bosnia and Herzegovina Convertible Mark", "symbol": "КМ", "alternate_symbols": ["KM"], "subunit": "Fening", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "977", "smallest_denomination": 5 }, "bbd": { "priority": 100, "iso_code": "BBD", "name": "Barbadian Dollar", "symbol": "$", "disambiguate_symbol": "Bds$", "alternate_symbols": ["Bds$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "052", "smallest_denomination": 1 }, "bdt": { "priority": 100, "iso_code": "BDT", "name": "Bangladeshi Taka", "symbol": "৳", "alternate_symbols": ["Tk"], "subunit": "Paisa", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "050", "smallest_denomination": 1 }, "bgn": { "priority": 100, "iso_code": "BGN", "name": "Bulgarian Lev", "symbol": "лв.", "alternate_symbols": ["lev", "leva", "лев", "лева"], "subunit": "Stotinka", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "975", "smallest_denomination": 1 }, "bhd": { "priority": 100, "iso_code": "BHD", "name": "Bahraini Dinar", "symbol": "د.ب", "alternate_symbols": ["BD"], "subunit": "Fils", "subunit_to_unit": 1000, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "048", "smallest_denomination": 5 }, "bif": { "priority": 100, "iso_code": "BIF", "name": "Burundian Franc", "symbol": "Fr", "disambiguate_symbol": "FBu", "alternate_symbols": ["FBu"], "subunit": "Centime", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "108", "smallest_denomination": 100 }, "bmd": { "priority": 100, "iso_code": "BMD", "name": "Bermudian Dollar", "symbol": "$", "disambiguate_symbol": "BD$", "alternate_symbols": ["BD$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "060", "smallest_denomination": 1 }, "bnd": { "priority": 100, "iso_code": "BND", "name": "Brunei Dollar", "symbol": "$", "disambiguate_symbol": "BND", "alternate_symbols": ["B$"], "subunit": "Sen", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "096", "smallest_denomination": 1 }, "bob": { "priority": 100, "iso_code": "BOB", "name": "Bolivian Boliviano", "symbol": "Bs.", "alternate_symbols": ["Bs"], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "068", "smallest_denomination": 10 }, "brl": { "priority": 100, "iso_code": "BRL", "name": "Brazilian Real", "symbol": "R$", "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "R$", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "986", "smallest_denomination": 5 }, "bsd": { "priority": 100, "iso_code": "BSD", "name": "Bahamian Dollar", "symbol": "$", "disambiguate_symbol": "BSD", "alternate_symbols": ["B$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "044", "smallest_denomination": 1 }, "btn": { "priority": 100, "iso_code": "BTN", "name": "Bhutanese Ngultrum", "symbol": "Nu.", "alternate_symbols": ["Nu"], "subunit": "Chertrum", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "064", "smallest_denomination": 5 }, "bwp": { "priority": 100, "iso_code": "BWP", "name": "Botswana Pula", "symbol": "P", "alternate_symbols": [], "subunit": "Thebe", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "072", "smallest_denomination": 5 }, "byn": { "priority": 100, "iso_code": "BYN", "name": "Belarusian Ruble", "symbol": "Br", "disambiguate_symbol": "BYN", "alternate_symbols": ["бел. руб.", "б.р.", "руб.", "р."], "subunit": "Kapeyka", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ",", "thousands_separator": " ", "iso_numeric": "933", "smallest_denomination": 1 }, "byr": { "priority": 50, "iso_code": "BYR", "name": "Belarusian Ruble", "symbol": "Br", "disambiguate_symbol": "BYR", "alternate_symbols": ["бел. руб.", "б.р.", "руб.", "р."], "subunit": null, "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ",", "thousands_separator": " ", "iso_numeric": "974", "smallest_denomination": 100 }, "bzd": { "priority": 100, "iso_code": "BZD", "name": "Belize Dollar", "symbol": "$", "disambiguate_symbol": "BZ$", "alternate_symbols": ["BZ$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "084", "smallest_denomination": 1 }, "cad": { "priority": 5, "iso_code": "CAD", "name": "Canadian Dollar", "symbol": "$", "disambiguate_symbol": "C$", "alternate_symbols": ["C$", "CAD$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "124", "smallest_denomination": 5 }, "cdf": { "priority": 100, "iso_code": "CDF", "name": "Congolese Franc", "symbol": "Fr", "disambiguate_symbol": "FC", "alternate_symbols": ["FC"], "subunit": "Centime", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "976", "smallest_denomination": 1 }, "chf": { "priority": 100, "iso_code": "CHF", "name": "Swiss Franc", "symbol": "CHF", "alternate_symbols": ["SFr", "Fr"], "subunit": "Rappen", "subunit_to_unit": 100, "symbol_first": true, "format": "%u%n", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "756", "smallest_denomination": 5 }, "clf": { "priority": 100, "iso_code": "CLF", "name": "Unidad de Fomento", "symbol": "UF", "alternate_symbols": [], "subunit": "Peso", "subunit_to_unit": 10000, "symbol_first": true, "html_entity": "₱", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "990" }, "clp": { "priority": 100, "iso_code": "CLP", "name": "Chilean Peso", "symbol": "$", "disambiguate_symbol": "CLP", "alternate_symbols": [], "subunit": "Peso", "subunit_to_unit": 1, "symbol_first": true, "html_entity": "$", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "152", "smallest_denomination": 1 }, "cny": { "priority": 100, "iso_code": "CNY", "name": "Chinese Renminbi Yuan", "symbol": "¥", "alternate_symbols": ["CN¥", "元", "CN元"], "subunit": "Fen", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "¥", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "156", "smallest_denomination": 1 }, "cop": { "priority": 100, "iso_code": "COP", "name": "Colombian Peso", "symbol": "$", "disambiguate_symbol": "COL$", "alternate_symbols": ["COL$"], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "170", "smallest_denomination": 20 }, "crc": { "priority": 100, "iso_code": "CRC", "name": "Costa Rican Colón", "symbol": "₡", "alternate_symbols": ["¢"], "subunit": "Céntimo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₡", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "188", "smallest_denomination": 500 }, "cuc": { "priority": 100, "iso_code": "CUC", "name": "Cuban Convertible Peso", "symbol": "$", "disambiguate_symbol": "CUC$", "alternate_symbols": ["CUC$"], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "931", "smallest_denomination": 1 }, "cup": { "priority": 100, "iso_code": "CUP", "name": "Cuban Peso", "symbol": "$", "disambiguate_symbol": "$MN", "alternate_symbols": ["$MN"], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₱", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "192", "smallest_denomination": 1 }, "cve": { "priority": 100, "iso_code": "CVE", "name": "Cape Verdean Escudo", "symbol": "$", "disambiguate_symbol": "Esc", "alternate_symbols": ["Esc"], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "132", "smallest_denomination": 100 }, "czk": { "priority": 100, "iso_code": "CZK", "name": "Czech Koruna", "symbol": "Kč", "alternate_symbols": [], "subunit": "Haléř", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ",", "thousands_separator": " ", "iso_numeric": "203", "smallest_denomination": 100 }, "djf": { "priority": 100, "iso_code": "DJF", "name": "Djiboutian Franc", "symbol": "Fdj", "alternate_symbols": [], "subunit": "Centime", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "262", "smallest_denomination": 100 }, "dkk": { "priority": 100, "iso_code": "DKK", "name": "Danish Krone", "symbol": "kr.", "disambiguate_symbol": "DKK", "alternate_symbols": [",-"], "subunit": "Øre", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "208", "smallest_denomination": 50 }, "dop": { "priority": 100, "iso_code": "DOP", "name": "Dominican Peso", "symbol": "$", "disambiguate_symbol": "RD$", "alternate_symbols": ["RD$"], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₱", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "214", "smallest_denomination": 100 }, "dzd": { "priority": 100, "iso_code": "DZD", "name": "Algerian Dinar", "symbol": "د.ج", "alternate_symbols": ["DA"], "subunit": "Centime", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "012", "smallest_denomination": 100 }, "egp": { "priority": 100, "iso_code": "EGP", "name": "Egyptian Pound", "symbol": "ج.م", "alternate_symbols": ["LE", "E£", "L.E."], "subunit": "Piastre", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "818", "smallest_denomination": 25 }, "ern": { "priority": 100, "iso_code": "ERN", "name": "Eritrean Nakfa", "symbol": "Nfk", "alternate_symbols": [], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "232", "smallest_denomination": 1 }, "etb": { "priority": 100, "iso_code": "ETB", "name": "Ethiopian Birr", "symbol": "Br", "disambiguate_symbol": "ETB", "alternate_symbols": [], "subunit": "Santim", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "230", "smallest_denomination": 1 }, "eur": { "priority": 2, "iso_code": "EUR", "name": "Euro", "symbol": "€", "alternate_symbols": [], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "€", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "978", "smallest_denomination": 1 }, "fjd": { "priority": 100, "iso_code": "FJD", "name": "Fijian Dollar", "symbol": "$", "disambiguate_symbol": "FJ$", "alternate_symbols": ["FJ$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "242", "smallest_denomination": 5 }, "fkp": { "priority": 100, "iso_code": "FKP", "name": "Falkland Pound", "symbol": "£", "disambiguate_symbol": "FK£", "alternate_symbols": ["FK£"], "subunit": "Penny", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "238", "smallest_denomination": 1 }, "gbp": { "priority": 3, "iso_code": "GBP", "name": "British Pound", "symbol": "£", "alternate_symbols": [], "subunit": "Penny", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "826", "smallest_denomination": 1 }, "gel": { "priority": 100, "iso_code": "GEL", "name": "Georgian Lari", "symbol": "ლ", "alternate_symbols": ["lari"], "subunit": "Tetri", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "981", "smallest_denomination": 1 }, "ghs": { "priority": 100, "iso_code": "GHS", "name": "Ghanaian Cedi", "symbol": "₵", "alternate_symbols": ["GH¢", "GH₵"], "subunit": "Pesewa", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₵", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "936", "smallest_denomination": 1 }, "gip": { "priority": 100, "iso_code": "GIP", "name": "Gibraltar Pound", "symbol": "£", "disambiguate_symbol": "GIP", "alternate_symbols": [], "subunit": "Penny", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "292", "smallest_denomination": 1 }, "gmd": { "priority": 100, "iso_code": "GMD", "name": "Gambian Dalasi", "symbol": "D", "alternate_symbols": [], "subunit": "Butut", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "270", "smallest_denomination": 1 }, "gnf": { "priority": 100, "iso_code": "GNF", "name": "Guinean Franc", "symbol": "Fr", "disambiguate_symbol": "FG", "alternate_symbols": ["FG", "GFr"], "subunit": "Centime", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "324", "smallest_denomination": 100 }, "gtq": { "priority": 100, "iso_code": "GTQ", "name": "Guatemalan Quetzal", "symbol": "Q", "alternate_symbols": [], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "320", "smallest_denomination": 1 }, "gyd": { "priority": 100, "iso_code": "GYD", "name": "Guyanese Dollar", "symbol": "$", "disambiguate_symbol": "G$", "alternate_symbols": ["G$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "328", "smallest_denomination": 100 }, "hkd": { "priority": 100, "iso_code": "HKD", "name": "Hong Kong Dollar", "symbol": "$", "disambiguate_symbol": "HK$", "alternate_symbols": ["HK$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "344", "smallest_denomination": 10 }, "hnl": { "priority": 100, "iso_code": "HNL", "name": "Honduran Lempira", "symbol": "L", "disambiguate_symbol": "HNL", "alternate_symbols": [], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "340", "smallest_denomination": 5 }, "hrk": { "priority": 100, "iso_code": "HRK", "name": "Croatian Kuna", "symbol": "kn", "alternate_symbols": [], "subunit": "Lipa", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "191", "smallest_denomination": 1 }, "htg": { "priority": 100, "iso_code": "HTG", "name": "Haitian Gourde", "symbol": "G", "alternate_symbols": [], "subunit": "Centime", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "332", "smallest_denomination": 5 }, "huf": { "priority": 100, "iso_code": "HUF", "name": "Hungarian Forint", "symbol": "Ft", "alternate_symbols": [], "subunit": "", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ",", "thousands_separator": " ", "iso_numeric": "348", "smallest_denomination": 5 }, "idr": { "priority": 100, "iso_code": "IDR", "name": "Indonesian Rupiah", "symbol": "Rp", "alternate_symbols": [], "subunit": "Sen", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "360", "smallest_denomination": 5000 }, "ils": { "priority": 100, "iso_code": "ILS", "name": "Israeli New Sheqel", "symbol": "₪", "alternate_symbols": ["ש״ח", "NIS"], "subunit": "Agora", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₪", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "376", "smallest_denomination": 10 }, "inr": { "priority": 100, "iso_code": "INR", "name": "Indian Rupee", "symbol": "₹", "alternate_symbols": ["Rs", "৳", "૱", "௹", "रु", "₨"], "subunit": "Paisa", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₹", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "356", "smallest_denomination": 50 }, "iqd": { "priority": 100, "iso_code": "IQD", "name": "Iraqi Dinar", "symbol": "ع.د", "alternate_symbols": [], "subunit": "Fils", "subunit_to_unit": 1000, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "368", "smallest_denomination": 50000 }, "irr": { "priority": 100, "iso_code": "IRR", "name": "Iranian Rial", "symbol": "﷼", "alternate_symbols": [], "subunit": null, "subunit_to_unit": 100, "symbol_first": true, "html_entity": "﷼", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "364", "smallest_denomination": 5000 }, "isk": { "priority": 100, "iso_code": "ISK", "name": "Icelandic Króna", "symbol": "kr.", "alternate_symbols": ["Íkr"], "subunit": null, "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "352", "smallest_denomination": 1 }, "jmd": { "priority": 100, "iso_code": "JMD", "name": "Jamaican Dollar", "symbol": "$", "disambiguate_symbol": "J$", "alternate_symbols": ["J$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "388", "smallest_denomination": 1 }, "jod": { "priority": 100, "iso_code": "JOD", "name": "Jordanian Dinar", "symbol": "د.ا", "alternate_symbols": ["JD"], "subunit": "Fils", "subunit_to_unit": 1000, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "400", "smallest_denomination": 5 }, "jpy": { "priority": 6, "iso_code": "JPY", "name": "Japanese Yen", "symbol": "¥", "alternate_symbols": ["円", "圓"], "subunit": null, "subunit_to_unit": 1, "symbol_first": true, "html_entity": "¥", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "392", "smallest_denomination": 1 }, "kes": { "priority": 100, "iso_code": "KES", "name": "Kenyan Shilling", "symbol": "KSh", "alternate_symbols": ["Sh"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "404", "smallest_denomination": 50 }, "kgs": { "priority": 100, "iso_code": "KGS", "name": "Kyrgyzstani Som", "symbol": "som", "alternate_symbols": ["сом"], "subunit": "Tyiyn", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "417", "smallest_denomination": 1 }, "khr": { "priority": 100, "iso_code": "KHR", "name": "Cambodian Riel", "symbol": "៛", "alternate_symbols": [], "subunit": "Sen", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "៛", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "116", "smallest_denomination": 5000 }, "kmf": { "priority": 100, "iso_code": "KMF", "name": "Comorian Franc", "symbol": "Fr", "disambiguate_symbol": "CF", "alternate_symbols": ["CF"], "subunit": "Centime", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "174", "smallest_denomination": 100 }, "kpw": { "priority": 100, "iso_code": "KPW", "name": "North Korean Won", "symbol": "₩", "alternate_symbols": [], "subunit": "Chŏn", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "₩", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "408", "smallest_denomination": 1 }, "krw": { "priority": 100, "iso_code": "KRW", "name": "South Korean Won", "symbol": "₩", "subunit": null, "subunit_to_unit": 1, "alternate_symbols": [], "symbol_first": true, "html_entity": "₩", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "410", "smallest_denomination": 1 }, "kwd": { "priority": 100, "iso_code": "KWD", "name": "Kuwaiti Dinar", "symbol": "د.ك", "alternate_symbols": ["K.D."], "subunit": "Fils", "subunit_to_unit": 1000, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "414", "smallest_denomination": 5 }, "kyd": { "priority": 100, "iso_code": "KYD", "name": "Cayman Islands Dollar", "symbol": "$", "disambiguate_symbol": "CI$", "alternate_symbols": ["CI$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "136", "smallest_denomination": 1 }, "kzt": { "priority": 100, "iso_code": "KZT", "name": "Kazakhstani Tenge", "symbol": "₸", "alternate_symbols": [], "subunit": "Tiyn", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "398", "smallest_denomination": 100 }, "lak": { "priority": 100, "iso_code": "LAK", "name": "Lao Kip", "symbol": "₭", "alternate_symbols": ["₭N"], "subunit": "Att", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "₭", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "418", "smallest_denomination": 10 }, "lbp": { "priority": 100, "iso_code": "LBP", "name": "Lebanese Pound", "symbol": "ل.ل", "alternate_symbols": ["£", "L£"], "subunit": "Piastre", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "422", "smallest_denomination": 25000 }, "lkr": { "priority": 100, "iso_code": "LKR", "name": "Sri Lankan Rupee", "symbol": "₨", "disambiguate_symbol": "SLRs", "alternate_symbols": ["රු", "ரூ", "SLRs", "/-"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "₨", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "144", "smallest_denomination": 100 }, "lrd": { "priority": 100, "iso_code": "LRD", "name": "Liberian Dollar", "symbol": "$", "disambiguate_symbol": "L$", "alternate_symbols": ["L$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "430", "smallest_denomination": 5 }, "lsl": { "priority": 100, "iso_code": "LSL", "name": "Lesotho Loti", "symbol": "L", "disambiguate_symbol": "M", "alternate_symbols": ["M"], "subunit": "Sente", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "426", "smallest_denomination": 1 }, "lyd": { "priority": 100, "iso_code": "LYD", "name": "Libyan Dinar", "symbol": "ل.د", "alternate_symbols": ["LD"], "subunit": "Dirham", "subunit_to_unit": 1000, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "434", "smallest_denomination": 50 }, "mad": { "priority": 100, "iso_code": "MAD", "name": "Moroccan Dirham", "symbol": "د.م.", "alternate_symbols": [], "subunit": "Centime", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "504", "smallest_denomination": 1 }, "mdl": { "priority": 100, "iso_code": "MDL", "name": "Moldovan Leu", "symbol": "L", "alternate_symbols": ["lei"], "subunit": "Ban", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "498", "smallest_denomination": 1 }, "mga": { "priority": 100, "iso_code": "MGA", "name": "Malagasy Ariary", "symbol": "Ar", "alternate_symbols": [], "subunit": "Iraimbilanja", "subunit_to_unit": 5, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "969", "smallest_denomination": 1 }, "mkd": { "priority": 100, "iso_code": "MKD", "name": "Macedonian Denar", "symbol": "ден", "alternate_symbols": [], "subunit": "Deni", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "807", "smallest_denomination": 100 }, "mmk": { "priority": 100, "iso_code": "MMK", "name": "Myanmar Kyat", "symbol": "K", "disambiguate_symbol": "MMK", "alternate_symbols": [], "subunit": "Pya", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "104", "smallest_denomination": 50 }, "mnt": { "priority": 100, "iso_code": "MNT", "name": "Mongolian Tögrög", "symbol": "₮", "alternate_symbols": [], "subunit": "Möngö", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "₮", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "496", "smallest_denomination": 2000 }, "mop": { "priority": 100, "iso_code": "MOP", "name": "Macanese Pataca", "symbol": "P", "alternate_symbols": ["MOP$"], "subunit": "Avo", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "446", "smallest_denomination": 10 }, "mru": { "priority": 100, "iso_code": "MRU", "name": "Mauritanian Ouguiya", "symbol": "UM", "alternate_symbols": [], "subunit": "Khoums", "subunit_to_unit": 5, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "929", "smallest_denomination": 1 }, "mur": { "priority": 100, "iso_code": "MUR", "name": "Mauritian Rupee", "symbol": "₨", "alternate_symbols": [], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₨", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "480", "smallest_denomination": 100 }, "mvr": { "priority": 100, "iso_code": "MVR", "name": "Maldivian Rufiyaa", "symbol": "MVR", "alternate_symbols": ["MRF", "Rf", "/-", "ރ"], "subunit": "Laari", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "462", "smallest_denomination": 1 }, "mwk": { "priority": 100, "iso_code": "MWK", "name": "Malawian Kwacha", "symbol": "MK", "alternate_symbols": [], "subunit": "Tambala", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "454", "smallest_denomination": 1 }, "mxn": { "priority": 100, "iso_code": "MXN", "name": "Mexican Peso", "symbol": "$", "disambiguate_symbol": "MEX$", "alternate_symbols": ["MEX$"], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "484", "smallest_denomination": 5 }, "myr": { "priority": 100, "iso_code": "MYR", "name": "Malaysian Ringgit", "symbol": "RM", "alternate_symbols": [], "subunit": "Sen", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "458", "smallest_denomination": 5 }, "mzn": { "priority": 100, "iso_code": "MZN", "name": "Mozambican Metical", "symbol": "MTn", "alternate_symbols": ["MZN"], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "943", "smallest_denomination": 1 }, "nad": { "priority": 100, "iso_code": "NAD", "name": "Namibian Dollar", "symbol": "$", "disambiguate_symbol": "N$", "alternate_symbols": ["N$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "516", "smallest_denomination": 5 }, "ngn": { "priority": 100, "iso_code": "NGN", "name": "Nigerian Naira", "symbol": "₦", "alternate_symbols": [], "subunit": "Kobo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₦", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "566", "smallest_denomination": 50 }, "nio": { "priority": 100, "iso_code": "NIO", "name": "Nicaraguan Córdoba", "symbol": "C$", "disambiguate_symbol": "NIO$", "alternate_symbols": [], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "558", "smallest_denomination": 5 }, "nok": { "priority": 100, "iso_code": "NOK", "name": "Norwegian Krone", "symbol": "kr", "disambiguate_symbol": "NOK", "alternate_symbols": [",-"], "subunit": "Øre", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "kr", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "578", "smallest_denomination": 100 }, "npr": { "priority": 100, "iso_code": "NPR", "name": "Nepalese Rupee", "symbol": "Rs.", "disambiguate_symbol": "NPR", "alternate_symbols": ["Rs", "रू", "₨"], "subunit": "Paisa", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₨", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "524", "smallest_denomination": 1 }, "nzd": { "priority": 100, "iso_code": "NZD", "name": "New Zealand Dollar", "symbol": "$", "disambiguate_symbol": "NZ$", "alternate_symbols": ["NZ$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "554", "smallest_denomination": 10 }, "omr": { "priority": 100, "iso_code": "OMR", "name": "Omani Rial", "symbol": "ر.ع.", "alternate_symbols": [], "subunit": "Baisa", "subunit_to_unit": 1000, "symbol_first": true, "html_entity": "﷼", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "512", "smallest_denomination": 5 }, "pab": { "priority": 100, "iso_code": "PAB", "name": "Panamanian Balboa", "symbol": "B/.", "alternate_symbols": [], "subunit": "Centésimo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "590", "smallest_denomination": 1 }, "pen": { "priority": 100, "iso_code": "PEN", "name": "Peruvian Sol", "symbol": "S/", "alternate_symbols": [], "subunit": "Céntimo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "S/", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "604", "smallest_denomination": 1 }, "pgk": { "priority": 100, "iso_code": "PGK", "name": "Papua New Guinean Kina", "symbol": "K", "disambiguate_symbol": "PGK", "alternate_symbols": [], "subunit": "Toea", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "598", "smallest_denomination": 5 }, "php": { "priority": 100, "iso_code": "PHP", "name": "Philippine Peso", "symbol": "₱", "alternate_symbols": ["PHP", "PhP", "P"], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₱", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "608", "smallest_denomination": 1 }, "pkr": { "priority": 100, "iso_code": "PKR", "name": "Pakistani Rupee", "symbol": "₨", "disambiguate_symbol": "PKR", "alternate_symbols": ["Rs"], "subunit": "Paisa", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₨", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "586", "smallest_denomination": 100 }, "pln": { "priority": 100, "iso_code": "PLN", "name": "Polish Złoty", "symbol": "zł", "alternate_symbols": [], "subunit": "Grosz", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "zł", "decimal_mark": ",", "thousands_separator": " ", "iso_numeric": "985", "smallest_denomination": 1 }, "pyg": { "priority": 100, "iso_code": "PYG", "name": "Paraguayan Guaraní", "symbol": "₲", "alternate_symbols": [], "subunit": "Céntimo", "subunit_to_unit": 1, "symbol_first": true, "html_entity": "₲", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "600", "smallest_denomination": 5000 }, "qar": { "priority": 100, "iso_code": "QAR", "name": "Qatari Riyal", "symbol": "ر.ق", "alternate_symbols": ["QR"], "subunit": "Dirham", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "﷼", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "634", "smallest_denomination": 1 }, "ron": { "priority": 100, "iso_code": "RON", "name": "Romanian Leu", "symbol": "Lei", "alternate_symbols": [], "subunit": "Bani", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "946", "smallest_denomination": 1 }, "rsd": { "priority": 100, "iso_code": "RSD", "name": "Serbian Dinar", "symbol": "РСД", "alternate_symbols": ["RSD", "din", "дин"], "subunit": "Para", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "941", "smallest_denomination": 100 }, "rub": { "priority": 100, "iso_code": "RUB", "name": "Russian Ruble", "symbol": "₽", "alternate_symbols": ["руб.", "р."], "subunit": "Kopeck", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "₽", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "643", "smallest_denomination": 1 }, "rwf": { "priority": 100, "iso_code": "RWF", "name": "Rwandan Franc", "symbol": "FRw", "alternate_symbols": ["RF", "R₣"], "subunit": "Centime", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "646", "smallest_denomination": 100 }, "sar": { "priority": 100, "iso_code": "SAR", "name": "Saudi Riyal", "symbol": "ر.س", "alternate_symbols": ["SR", "﷼"], "subunit": "Hallallah", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "﷼", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "682", "smallest_denomination": 5 }, "sbd": { "priority": 100, "iso_code": "SBD", "name": "Solomon Islands Dollar", "symbol": "$", "disambiguate_symbol": "SI$", "alternate_symbols": ["SI$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "090", "smallest_denomination": 10 }, "scr": { "priority": 100, "iso_code": "SCR", "name": "Seychellois Rupee", "symbol": "₨", "disambiguate_symbol": "SRe", "alternate_symbols": ["SRe", "SR"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "₨", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "690", "smallest_denomination": 1 }, "sdg": { "priority": 100, "iso_code": "SDG", "name": "Sudanese Pound", "symbol": "£", "disambiguate_symbol": "SDG", "alternate_symbols": [], "subunit": "Piastre", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "938", "smallest_denomination": 1 }, "sek": { "priority": 100, "iso_code": "SEK", "name": "Swedish Krona", "symbol": "kr", "disambiguate_symbol": "SEK", "alternate_symbols": [":-"], "subunit": "Öre", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ",", "thousands_separator": " ", "iso_numeric": "752", "smallest_denomination": 100 }, "sgd": { "priority": 100, "iso_code": "SGD", "name": "Singapore Dollar", "symbol": "$", "disambiguate_symbol": "S$", "alternate_symbols": ["S$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "702", "smallest_denomination": 1 }, "shp": { "priority": 100, "iso_code": "SHP", "name": "Saint Helenian Pound", "symbol": "£", "disambiguate_symbol": "SHP", "alternate_symbols": [], "subunit": "Penny", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "654", "smallest_denomination": 1 }, "skk": { "priority": 100, "iso_code": "SKK", "name": "Slovak Koruna", "symbol": "Sk", "alternate_symbols": [], "subunit": "Halier", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "703", "smallest_denomination": 50 }, "sll": { "priority": 100, "iso_code": "SLL", "name": "Sierra Leonean Leone", "symbol": "Le", "alternate_symbols": [], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "694", "smallest_denomination": 1000 }, "sos": { "priority": 100, "iso_code": "SOS", "name": "Somali Shilling", "symbol": "Sh", "alternate_symbols": ["Sh.So"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "706", "smallest_denomination": 1 }, "srd": { "priority": 100, "iso_code": "SRD", "name": "Surinamese Dollar", "symbol": "$", "disambiguate_symbol": "SRD", "alternate_symbols": [], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "968", "smallest_denomination": 1 }, "ssp": { "priority": 100, "iso_code": "SSP", "name": "South Sudanese Pound", "symbol": "£", "disambiguate_symbol": "SSP", "alternate_symbols": [], "subunit": "piaster", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "728", "smallest_denomination": 5 }, "std": { "priority": 100, "iso_code": "STD", "name": "São Tomé and Príncipe Dobra", "symbol": "Db", "alternate_symbols": [], "subunit": "Cêntimo", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "678", "smallest_denomination": 10000 }, "svc": { "priority": 100, "iso_code": "SVC", "name": "Salvadoran Colón", "symbol": "₡", "alternate_symbols": ["¢"], "subunit": "Centavo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₡", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "222", "smallest_denomination": 1 }, "syp": { "priority": 100, "iso_code": "SYP", "name": "Syrian Pound", "symbol": "£S", "alternate_symbols": ["£", "ل.س", "LS", "الليرة السورية"], "subunit": "Piastre", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "760", "smallest_denomination": 100 }, "szl": { "priority": 100, "iso_code": "SZL", "name": "Swazi Lilangeni", "symbol": "E", "disambiguate_symbol": "SZL", "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "748", "smallest_denomination": 1 }, "thb": { "priority": 100, "iso_code": "THB", "name": "Thai Baht", "symbol": "฿", "alternate_symbols": [], "subunit": "Satang", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "฿", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "764", "smallest_denomination": 1 }, "tjs": { "priority": 100, "iso_code": "TJS", "name": "Tajikistani Somoni", "symbol": "ЅМ", "alternate_symbols": [], "subunit": "Diram", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "972", "smallest_denomination": 1 }, "tmt": { "priority": 100, "iso_code": "TMT", "name": "Turkmenistani Manat", "symbol": "T", "alternate_symbols": [], "subunit": "Tenge", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "934", "smallest_denomination": 1 }, "tnd": { "priority": 100, "iso_code": "TND", "name": "Tunisian Dinar", "symbol": "د.ت", "alternate_symbols": ["TD", "DT"], "subunit": "Millime", "subunit_to_unit": 1000, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "788", "smallest_denomination": 10 }, "top": { "priority": 100, "iso_code": "TOP", "name": "Tongan Paʻanga", "symbol": "T$", "alternate_symbols": ["PT"], "subunit": "Seniti", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "776", "smallest_denomination": 1 }, "try": { "priority": 100, "iso_code": "TRY", "name": "Turkish Lira", "symbol": "₺", "alternate_symbols": ["TL"], "subunit": "kuruş", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₺", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "949", "smallest_denomination": 1 }, "ttd": { "priority": 100, "iso_code": "TTD", "name": "Trinidad and Tobago Dollar", "symbol": "$", "disambiguate_symbol": "TT$", "alternate_symbols": ["TT$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "780", "smallest_denomination": 1 }, "twd": { "priority": 100, "iso_code": "TWD", "name": "New Taiwan Dollar", "symbol": "$", "disambiguate_symbol": "NT$", "alternate_symbols": ["NT$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "901", "smallest_denomination": 50 }, "tzs": { "priority": 100, "iso_code": "TZS", "name": "Tanzanian Shilling", "symbol": "Sh", "alternate_symbols": [], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "834", "smallest_denomination": 5000 }, "uah": { "priority": 100, "iso_code": "UAH", "name": "Ukrainian Hryvnia", "symbol": "₴", "alternate_symbols": [], "subunit": "Kopiyka", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "₴", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "980", "smallest_denomination": 1 }, "ugx": { "priority": 100, "iso_code": "UGX", "name": "Ugandan Shilling", "symbol": "USh", "alternate_symbols": [], "subunit": "Cent", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "800", "smallest_denomination": 1000 }, "usd": { "priority": 1, "iso_code": "USD", "name": "United States Dollar", "symbol": "$", "disambiguate_symbol": "US$", "alternate_symbols": ["US$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "840", "smallest_denomination": 1 }, "uyu": { "priority": 100, "iso_code": "UYU", "name": "Uruguayan Peso", "symbol": "$U", "alternate_symbols": ["$U"], "subunit": "Centésimo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$U", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "858", "smallest_denomination": 100 }, "uzs": { "priority": 100, "iso_code": "UZS", "name": "Uzbekistan Som", "symbol": "so'm", "alternate_symbols": ["so‘m", "сўм", "сум", "s", "с"], "subunit": "Tiyin", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "860", "smallest_denomination": 100 }, "ves": { "priority": 100, "iso_code": "VES", "name": "Venezuelan Bolívar Soberano", "symbol": "Bs", "alternate_symbols": ["Bs.S"], "subunit": "Céntimo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "928", "smallest_denomination": 1 }, "vnd": { "priority": 100, "iso_code": "VND", "name": "Vietnamese Đồng", "symbol": "₫", "alternate_symbols": [], "subunit": "Hào", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "₫", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "704", "smallest_denomination": 100 }, "vuv": { "priority": 100, "iso_code": "VUV", "name": "Vanuatu Vatu", "symbol": "Vt", "alternate_symbols": [], "subunit": null, "subunit_to_unit": 1, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "548", "smallest_denomination": 1 }, "wst": { "priority": 100, "iso_code": "WST", "name": "Samoan Tala", "symbol": "T", "disambiguate_symbol": "WS$", "alternate_symbols": ["WS$", "SAT", "ST"], "subunit": "Sene", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "882", "smallest_denomination": 10 }, "xaf": { "priority": 100, "iso_code": "XAF", "name": "Central African Cfa Franc", "symbol": "CFA", "disambiguate_symbol": "FCFA", "alternate_symbols": ["FCFA"], "subunit": "Centime", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "950", "smallest_denomination": 100 }, "xag": { "priority": 100, "iso_code": "XAG", "name": "Silver (Troy Ounce)", "symbol": "oz t", "disambiguate_symbol": "XAG", "alternate_symbols": [], "subunit": "oz", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "961" }, "xau": { "priority": 100, "iso_code": "XAU", "name": "Gold (Troy Ounce)", "symbol": "oz t", "disambiguate_symbol": "XAU", "alternate_symbols": [], "subunit": "oz", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "959" }, "xba": { "priority": 100, "iso_code": "XBA", "name": "European Composite Unit", "symbol": "", "disambiguate_symbol": "XBA", "alternate_symbols": [], "subunit": "", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "955" }, "xbb": { "priority": 100, "iso_code": "XBB", "name": "European Monetary Unit", "symbol": "", "disambiguate_symbol": "XBB", "alternate_symbols": [], "subunit": "", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "956" }, "xbc": { "priority": 100, "iso_code": "XBC", "name": "European Unit of Account 9", "symbol": "", "disambiguate_symbol": "XBC", "alternate_symbols": [], "subunit": "", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "957" }, "xbd": { "priority": 100, "iso_code": "XBD", "name": "European Unit of Account 17", "symbol": "", "disambiguate_symbol": "XBD", "alternate_symbols": [], "subunit": "", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "958" }, "xcd": { "priority": 100, "iso_code": "XCD", "name": "East Caribbean Dollar", "symbol": "$", "disambiguate_symbol": "EX$", "alternate_symbols": ["EC$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "951", "smallest_denomination": 1 }, "xdr": { "priority": 100, "iso_code": "XDR", "name": "Special Drawing Rights", "symbol": "SDR", "alternate_symbols": ["XDR"], "subunit": "", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "960" }, "xof": { "priority": 100, "iso_code": "XOF", "name": "West African Cfa Franc", "symbol": "Fr", "disambiguate_symbol": "CFA", "alternate_symbols": ["CFA"], "subunit": "Centime", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "952", "smallest_denomination": 100 }, "xpd": { "priority": 100, "iso_code": "XPD", "name": "Palladium", "symbol": "oz t", "disambiguate_symbol": "XPD", "alternate_symbols": [], "subunit": "oz", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "964" }, "xpf": { "priority": 100, "iso_code": "XPF", "name": "Cfp Franc", "symbol": "Fr", "alternate_symbols": ["F"], "subunit": "Centime", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "953", "smallest_denomination": 100 }, "xpt": { "priority": 100, "iso_code": "XPT", "name": "Platinum", "symbol": "oz t", "alternate_symbols": [], "subunit": "", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "962", "smallest_denomination": "" }, "xts": { "priority": 100, "iso_code": "XTS", "name": "Codes specifically reserved for testing purposes", "symbol": "", "alternate_symbols": [], "subunit": "", "subunit_to_unit": 1, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "963", "smallest_denomination": "" }, "yer": { "priority": 100, "iso_code": "YER", "name": "Yemeni Rial", "symbol": "﷼", "alternate_symbols": [], "subunit": "Fils", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "﷼", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "886", "smallest_denomination": 100 }, "zar": { "priority": 100, "iso_code": "ZAR", "name": "South African Rand", "symbol": "R", "alternate_symbols": [], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "R", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "710", "smallest_denomination": 10 }, "zmk": { "priority": 100, "iso_code": "ZMK", "name": "Zambian Kwacha", "symbol": "ZK", "disambiguate_symbol": "ZMK", "alternate_symbols": [], "subunit": "Ngwee", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "894", "smallest_denomination": 5 }, "zmw": { "priority": 100, "iso_code": "ZMW", "name": "Zambian Kwacha", "symbol": "K", "disambiguate_symbol": "ZMW", "alternate_symbols": [], "subunit": "Ngwee", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "967", "smallest_denomination": 5 } } money-6.16.0/config/currency_backwards_compatible.json0000644000004100000410000001166214054035243023203 0ustar www-datawww-data{ "eek": { "priority": 100, "iso_code": "EEK", "name": "Estonian Kroon", "symbol": "KR", "alternate_symbols": [], "subunit": "Sent", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "233", "smallest_denomination": 5 }, "ghc": { "priority": 100, "iso_code": "GHS", "name": "Ghanaian Cedi", "symbol": "₵", "disambiguate_symbol": "GH₵", "alternate_symbols": ["GH₵"], "subunit": "Pesewa", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "₵", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "288", "smallest_denomination": 1 }, "ltl": { "priority": 100, "iso_code": "LTL", "name": "Lithuanian Litas", "symbol": "Lt", "alternate_symbols": [], "subunit": "Centas", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "440", "smallest_denomination": 1 }, "lvl": { "priority": 100, "iso_code": "LVL", "name": "Latvian Lats", "symbol": "Ls", "alternate_symbols": [], "subunit": "Santīms", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "428", "smallest_denomination": 1 }, "mro": { "priority": 100, "iso_code": "MRO", "name": "Mauritanian Ouguiya", "symbol": "UM", "disambiguate_symbol": "A-UM", "alternate_symbols": [], "subunit": "Khoums", "subunit_to_unit": 5, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "478", "smallest_denomination": 1 }, "mtl": { "priority": 100, "iso_code": "MTL", "name": "Maltese Lira", "symbol": "₤", "alternate_symbols": ["Lm"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "£", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "470", "smallest_denomination": 1 }, "tmm": { "priority": 100, "iso_code": "TMM", "name": "Turkmenistani Manat", "symbol": "m", "alternate_symbols": [], "subunit": "Tennesi", "subunit_to_unit": 100, "symbol_first": false, "format": "%n %u", "html_entity": "", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "795", "smallest_denomination": 1 }, "yen": { "priority": 100, "iso_code": "JPY", "name": "Japanese Yen", "symbol": "¥", "disambiguate_symbol": "JPY", "alternate_symbols": ["円", "圓"], "subunit": "Sen", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "¥", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "", "smallest_denomination": 100 }, "zwd": { "priority": 100, "iso_code": "ZWD", "name": "Zimbabwean Dollar", "symbol": "$", "disambiguate_symbol": "ZWD", "alternate_symbols": ["Z$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "716", "smallest_denomination": 100 }, "zwl": { "priority": 100, "iso_code": "ZWL", "name": "Zimbabwean Dollar", "symbol": "$", "disambiguate_symbol": "ZWL", "alternate_symbols": ["Z$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "932", "smallest_denomination": 100 }, "zwn": { "priority": 100, "iso_code": "ZWN", "name": "Zimbabwean Dollar", "symbol": "$", "disambiguate_symbol": "ZWN", "alternate_symbols": ["Z$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "942", "smallest_denomination": 100 }, "zwr": { "priority": 100, "iso_code": "ZWR", "name": "Zimbabwean Dollar", "symbol": "$", "disambiguate_symbol": "ZWR", "alternate_symbols": ["Z$"], "subunit": "Cent", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "$", "decimal_mark": ".", "thousands_separator": ",", "iso_numeric": "935", "smallest_denomination": 100 }, "vef": { "priority": 100, "iso_code": "VEF", "name": "Venezuelan Bolívar", "symbol": "Bs.F", "alternate_symbols": ["Bs"], "subunit": "Céntimo", "subunit_to_unit": 100, "symbol_first": true, "html_entity": "", "decimal_mark": ",", "thousands_separator": ".", "iso_numeric": "937", "smallest_denomination": 1 } }