# Overview

Money2 is a Dart package providing parsing, formatting and mathematical operations on monetary amounts.

Key features of Money2:

* simple and expressive formatting.
* simple parsing of monetary amounts.
* multi-currency support.
* intuitive maths operations.
* fixed precision storage to ensure calculation without loss of precision.
* detailed documentation and extensive examples to get you up and running.
* pure Dart implementation.
* Open Source MIT license.
* Using Money2 will make you taller.

## Sponsored by OnePub <a href="#sponsored-by-onepub" id="sponsored-by-onepub"></a>

Help support Money2 by supporting [OnePub](https://onepub.dev/drive/b37ef958-bdc9-49bc-af7b-d31f1dd7c65d), the private Dart repository.

OnePub allows you to privately share Dart packages across your Team and with your customers.

Try it for free and publish your first private package in seconds.

| ![](/files/rc2pt36Jck9po23ILnYz) | <p>Publish a private package in five commands:</p><p><mark style="color:green;"><code>dart pub global activate onepub</code></mark></p><p><mark style="color:green;"><code>onepub login</code></mark><br><mark style="color:green;">cd \<my package></mark><br><mark style="color:green;">onepub pub private</mark><br><mark style="color:green;">dart pub publish</mark></p> |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Full API Documentation can be found at:&#x20;

{% embed url="<https://pub.dev/documentation/money2/latest/>" %}

Essentially the Money class stores the monetary value as a BigInt with a fixed scale (number of decimal places)  using the [Fixed ](https://pub.dev/packages/fixed)package. This allows for precise calculations as required when handling money and eliminates common rounding issues.

Let's start with some examples:

```dart
import 'package:money2/money2.dart';
import 'package:test/test.dart';

void main() {
  test('Overview - example 1', () {
   final usdCurrency = Currency.create('USD', 2);

    /// Create money from an int.
    final costPrice = Money.fromIntWithCurrency(1000, usdCurrency);
    expect(costPrice.toString(), equals(r'$10.00'));

    final taxInclusive = costPrice * 1.1;
    expect(taxInclusive.toString(), equals(r'$11.00'));

    expect(taxInclusive.format('SCC #.00'), equals(r'$US 11.00'));

    /// Create money from an String using the `Currency` instance.
    final parsed = usdCurrency.parse(r'$10.00');
    expect(parsed.format('SCCC 0.00'), equals(r'$USD 10.00'));

    /// Create money from an int which contains the MajorUnit (e.g dollars)
    final buyPrice = Money.fromNum(10, isoCode: 'AUD');
    expect(buyPrice.toString(), equals(r'$10.00'));

    /// Create money from a double which contains Major and Minor units
    /// (e.g. dollars and cents)
    /// We don't recommend transporting money as a double as you will get
    /// rounding errors.
    final sellPrice = Money.fromNum(10.50, isoCode: 'AUD');
    expect(sellPrice.toString(), equals(r'$10.50'));
  });
}

```

The package uses the following terms:

* Minor Units - the smallest unit of a currency e.g. cents.
* Major Units - the integer component of a currency - e.g. dollars
* isoCode - the currency code. e.g. USD
* symbol - the currency symbol. e.g. '$'. It should be noted that not every currency has a symbol.
* pattern - a pattern used to control parsing and the display format.
* decimals - the number of minor Units (e.g. cents) which should be used when storing the currency.
* decimal separator - the character that separates the fraction part from the integer of a number e.g. '10.99'. This defaults to '.' but can be changed to any character.
* group separator - the character that is used to format thousands (e.g. 100,000). Defaults to ',' but can be changed to any character.

Note: Money2 is tested to a maximum of 100 integer digits and 100 decimal digits. Money2 is likely to work with larger numbers as under the hood we use a BigInt which in Dart is only limited by memory.

<https://github.com/onepub-dev/money.dart/issues/75>


# Common Currencies

Money2 ships with a list of Common Currencies with a default format, decimals, isoCode and symbol.

If your currency isn't on the list then please help by submitting a [PR](https://github.com/onepub-dev/money.dart/pulls).

The Common Currencies are pre-registered, allowing you to easily access them by their currency code or by a member field.

{% hint style="info" %}
The $ character is used by Dart for String interpolation. When using a $ in a string mark the String as a raw or escape the $.\
e.g. \`r'$1.00'\` or \`'\\$1.00'\`.
{% endhint %}

To create a Money instance from a common currency:

```dart
import 'package:money2/money2.dart';
import 'package:test/test.dart';

void main() {
  test('Common Currency - example 1', () {
    /// Create a Money instance from the AUD common currency.
    final amount = Money.parse(r'$1.25', isoCode: 'AUD');
    expect(amount.toString(), equals(r'$1.25'));
    expect(amount.format('SCCC 0.00'), equals(r'$AUD 1.25'));

    /// Create a Money instance using the aud field.
    final amount2 = Money.parseWithCurrency(r'$1.25', CommonCurrencies().aud);
    expect(amount2.format('SCC 0.00'), equals(r'$AU 1.25'));

    /// Create a money instance from a Fixed and the USD
    /// common currency.
    final amount3 = Money.fromFixed(Fixed.parse('1.24', scale: 2), isoCode: 'USD');

    expect(amount3.format('S0.00 CCC'), equals(r'$1.24 USD'));
  });
}
```

Here is the list of currencies available in `CommonCurrencies`but please check the `CommonCurrencies` class as the list is updated sporadically.

```dart
  /// Afghan Afghani
  final Currency afn = Currency.create(
    'AFN',
    2,
    symbol: '؋',
    country: 'Afghanistan',
    unit: 'Afghani',
    name: 'Afghan Afghani',
  );

  /// Albanian Lek
  final Currency all = Currency.create(
    'ALL',
    2,
    symbol: 'L',
    country: 'Albania',
    unit: 'Lek',
    name: 'Albanian Lek',
  );

  /// Algerian Dinar
  final Currency dzd = Currency.create(
    'DZD',
    2,
    symbol: 'د.ج',
    pattern: '0.00S',
    country: 'Algeria',
    unit: 'Dinar',
    name: 'Algerian Dinar',
  );

  /// Angolan Kwanza
  final Currency aoa = Currency.create(
    'AOA',
    2,
    symbol: 'Kz',
    pattern: 'S0,00',
    groupSeparator: '.',
    decimalSeparator: ',',
    country: 'Angola',
    unit: 'Kwanza',
    name: 'Angolan Kwanza',
  );

  /// Argentine Peso
  final Currency ars = Currency.create(
    'ARS',
    2,
    pattern: 'S0,00',
    groupSeparator: '.',
    decimalSeparator: ',',
    country: 'Argentina',
    unit: 'Peso',
    name: 'Argentine Peso',
  );

  /// Armenian Dram
  final Currency amd = Currency.create(
    'AMD',
    2,
    symbol: '֏',
    pattern: '0.00S',
    country: 'Armenia',
    unit: 'Dram',
    name: 'Armenian Dram',
  );

  /// Aruban Florin
  final Currency awg = Currency.create(
    'AWG',
    2,
    symbol: 'ƒ',
    pattern: 'S0,00',
    groupSeparator: '.',
    decimalSeparator: ',',
    country: 'Aruba',
    unit: 'Florin',
    name: 'Aruban Florin',
  );

  /// Australian Dollar
  final Currency aud = Currency.create('AUD', 2,
      country: 'Australian', unit: 'Dollar', name: 'Australian Dollar');

  /// Azerbaijani Manat
  final Currency azn = Currency.create(
    'AZN',
    2,
    symbol: '₼',
    country: 'Azerbaijan',
    unit: 'Manat',
    name: 'Azerbaijani Manat',
  );

  /// Bahamian Dollar
  final Currency bsd = Currency.create(
    'BSD',
    2,
    country: 'Bahamas',
    unit: 'Dollar',
    name: 'Bahamian Dollar',
  );

  /// Bahraini Dinar
  final Currency bhd = Currency.create(
    'BHD',
    3,
    symbol: '.د.ب',
    pattern: '0.000S',
    country: 'Bahrain',
    unit: 'Dinar',
    name: 'Bahraini Dinar',
  );

  /// Bangladeshi Taka
  final Currency bdt = Currency.create(
    'BDT',
    2,
    symbol: '৳',
    country: 'Bangladesh',
    unit: 'Taka',
    name: 'Bangladeshi Taka',
  );

  /// Barbadian Dollar
  final Currency bbd = Currency.create(
    'BBD',
    2,
    country: 'Barbados',
    unit: 'Dollar',
    name: 'Barbadian Dollar',
  );

  /// Belarusian Ruble
  final Currency byn = Currency.create(
    'BYN',
    2,
    symbol: 'Br',
    pattern: 'S0,00',
    groupSeparator: ' ',
    decimalSeparator: ',',
    country: 'Belarus',
    unit: 'Ruble',
    name: 'Belarusian Ruble',
  );

  /// Belize Dollar
  final Currency bzd = Currency.create(
    'BZD',
    2,
    symbol: r'BZ$',
    country: 'Belize',
    unit: 'Dollar',
    name: 'Belize Dollar',
  );

  /// Bermudian Dollar
  final Currency bmd = Currency.create(
    'BMD',
    2,
    country: 'Bermuda',
    unit: 'Dollar',
    name: 'Bermudian Dollar',
  );

  /// Bhutanese Ngultrum
  final Currency btn = Currency.create(
    'BTN',
    2,
    symbol: 'Nu.',
    country: 'Bhutan',
    unit: 'Ngultrum',
    name: 'Bhutanese Ngultrum',
  );

  /// Bitcoin
  final Currency btc = Currency.create('BTC', 8,
      symbol: '₿',
      pattern: 'S0.00000000',
      country: 'Digital',
      unit: 'Bitcoin',
      name: 'Bitcon');

  /// Bolivian Boliviano
  final Currency bob = Currency.create(
    'BOB',
    2,
    symbol: 'Bs.',
    country: 'Bolivia',
    unit: 'Boliviano',
    name: 'Bolivian Boliviano',
  );

  /// Bosnia and Herzegovina Convertible Mark
  final Currency bam = Currency.create(
    'BAM',
    2,
    symbol: 'KM',
    pattern: 'S0,00',
    groupSeparator: '.',
    decimalSeparator: ',',
    country: 'Bosnia and Herzegovina',
    unit: 'Mark',
    name: 'Bosnia and Herzegovina Convertible Mark',
  );

  /// Botswana Pula
  final Currency bwp = Currency.create(
    'BWP',
    2,
    symbol: 'P',
    country: 'Botswana',
    unit: 'Pula',
    name: 'Botswana Pula',
  );

  /// Brazilian Real
  final Currency brl = Currency.create('BRL', 2,
      symbol: r'R$',
      groupSeparator: '.',
      decimalSeparator: ',',
      country: 'Brazil',
      unit: 'Real',
      name: 'Brazilian Real');

  /// British Pound Sterling
  final Currency gbp = Currency.create('GBP', 2,
      symbol: '£',
      country: 'Britan',
      unit: 'Pound Sterling',
      name: 'British Pound Sterling');

  /// Brunei Dollar
  final Currency bnd = Currency.create(
    'BND',
    2,
    country: 'Brunei',
    unit: 'Dollar',
    name: 'Brunei Dollar',
  );

  /// Bulgarian Lev
  final Currency bgn = Currency.create(
    'BGN',
    2,
    symbol: 'лв',
    pattern: 'S0,00',
    groupSeparator: ' ',
    decimalSeparator: ',',
    country: 'Bulgaria',
    unit: 'Lev',
    name: 'Bulgarian Lev',
  );

  /// Burundian Franc
  final Currency bif = Currency.create(
    'BIF',
    0,
    symbol: 'FBu',
    pattern: 'S0',
    decimalSeparator: '',
    country: 'Burundi',
    unit: 'Franc',
    name: 'Burundian Franc',
  );

  /// Cambodian Riel
  final Currency khr = Currency.create(
    'KHR',
    2,
    symbol: '៛',
    country: 'Cambodia',
    unit: 'Riel',
    name: 'Cambodian Riel',
  );

  /// Canadian Dollar
  final Currency cad = Currency.create('CAD', 2,
      country: 'Canada', unit: 'Dollar', name: 'Canadian Dollar');

  /// Cape Verdean Escudo
  final Currency cve = Currency.create(
    'CVE',
    2,
    country: 'Cape Verde',
    unit: 'Escudo',
    name: 'Cape Verdean Escudo',
  );

  /// Cayman Islands Dollar
  final Currency kyd = Currency.create(
    'KYD',
    2,
    country: 'Cayman Islands',
    unit: 'Dollar',
    name: 'Cayman Islands Dollar',
  );

  /// Central African CFA Franc
  final Currency xaf = Currency.create(
    'XAF',
    0,
    symbol: 'FCFA',
    pattern: 'S0',
    groupSeparator: ' ',
    decimalSeparator: '',
    country: 'Central African States',
    unit: 'Franc',
    name: 'Central African CFA Franc',
  );

  /// CFP Franc
  final Currency xpf = Currency.create(
    'XPF',
    0,
    symbol: '₣',
    pattern: 'S0',
    decimalSeparator: '',
    country: 'French Polynesia, New Caledonia, Wallis and Futuna',
    unit: 'Franc',
    name: 'CFP Franc',
  );

  /// Chilean Peso
  final Currency clp = Currency.create(
    'CLP',
    0,
    pattern: 'S0',
    decimalSeparator: '',
    country: 'Chile',
    unit: 'Peso',
    name: 'Chilean Peso',
  );

  /// Chinese Renminbi
  final Currency cny = Currency.create('CNY', 2,
      symbol: '¥',
      country: 'China',
      unit: 'Renminbi',
      name: 'Chinese Renminbi');

  /// Colombian Peso
  final Currency cop = Currency.create(
    'COP',
    2,
    pattern: '0,00S',
    groupSeparator: '.',
    decimalSeparator: ',',
    country: 'Colombia',
    unit: 'Peso',
    name: 'Colombian Peso',
  );

  /// Comorian Franc
  final Currency kmf = Currency.create(
    'KMF',
    0,
    symbol: 'CF',
    pattern: 'S0',
    decimalSeparator: '',
    country: 'Comoros',
    unit: 'Franc',
    name: 'Comorian Franc',
  );

  /// Congolese Franc
  final Currency cdf = Currency.create(
    'CDF',
    2,
    symbol: 'FC',
    country: 'Congo (DRC)',
    unit: 'Franc',
    name: 'Congolese Franc',
  );

  /// Costa Rican Colón
  final Currency crc = Currency.create(
    'CRC',
    2,
    symbol: '₡',
    pattern: 'S0,00',
    groupSeparator: '.',
    decimalSeparator: ',',
    country: 'Costa Rica',
    unit: 'Colón',
    name: 'Costa Rican Colón',
  );

  /// Cuban Peso
  final Currency cup = Currency.create(
    'CUP',
    2,
    country: 'Cuba',
    unit: 'Peso',
    name: 'Cuban Peso',
  );

  /// Czech Koruna
  final Currency czk = Currency.create('CZK', 2,
      symbol: 'Kč',
      groupSeparator: '.',
      decimalSeparator: ',',
      pattern: '0.00S',
      country: 'Czech',
      unit: 'Koruna',
      name: 'Czech Koruna');

  /// Danish Krone
  final Currency dkk = Currency.create(
    'DKK',
    2,
    symbol: 'kr',
    pattern: 'S0,00',
    groupSeparator: '.',
    decimalSeparator: ',',
    country: 'Denmark',
    unit: 'Krone',
    name: 'Danish Krone',
  );

  /// Djiboutian Franc
  final Currency djf = Currency.create(
    'DJF',
    0,
    symbol: 'Fdj',
    pattern: 'S0',
    decimalSeparator: '',
    country: 'Djibouti',
    unit: 'Franc',
    name: 'Djiboutian Franc',
  );

  /// Dominican Peso
  final Currency dop = Currency.create(
    'DOP',
    2,
    country: 'Dominican Republic',
    unit: 'Peso',
    name: 'Dominican Peso',
  );

  /// East Caribbean Dollar
  final Currency xcd = Currency.create(
    'XCD',
    2,
    country: 'East Caribbean',
    unit: 'Dollar',
    name: 'East Caribbean Dollar',
  );

  /// Egyptian Pound
  final Currency egp = Currency.create(
    'EGP',
    2,
    symbol: '£',
    country: 'Egypt',
    unit: 'Pound',
    name: 'Egyptian Pound',
  );

  /// Eritrean Nakfa
  final Currency ern = Currency.create(
    'ERN',
    2,
    symbol: 'Nfk',
    country: 'Eritrea',
    unit: 'Nakfa',
    name: 'Eritrean Nakfa',
  );

  /// Ethiopian Birr
  final Currency etb = Currency.create(
    'ETB',
    2,
    symbol: 'Br',
    country: 'Ethiopia',
    unit: 'Birr',
    name: 'Ethiopian Birr',
  );

  /// European Union Euro
  final Currency euro = Currency.create('EUR', 2,
      symbol: '€',
      groupSeparator: '.',
      decimalSeparator: ',',
      pattern: '0.00S',
      country: 'European Union',
      unit: 'Euro',
      name: 'European Union Euro');

  /// Falkland Islands Pound
  final Currency fkp = Currency.create(
    'FKP',
    2,
    symbol: '£',
    country: 'Falkland Islands',
    unit: 'Pound',
    name: 'Falkland Islands Pound',
  );

  /// Fijian Dollar
  final Currency fjd = Currency.create(
    'FJD',
    2,
    country: 'Fiji',
    unit: 'Dollar',
    name: 'Fijian Dollar',
  );

  /// Gambian Dalasi
  final Currency gmd = Currency.create(
    'GMD',
    2,
    symbol: 'D',
    country: 'Gambia',
    unit: 'Dalasi',
    name: 'Gambian Dalasi',
  );

  /// Georgian Lari
  final Currency gel = Currency.create(
    'GEL',
    2,
    symbol: '₾',
    pattern: 'S0,00',
    groupSeparator: ' ',
    decimalSeparator: ',',
    country: 'Georgia',
    unit: 'Lari',
    name: 'Georgian Lari',
  );

  /// Ghana Cedi
  final Currency ghs = Currency.create('GHS', 2,
      symbol: '₵', country: 'Ghana', unit: 'Cedi', name: 'Ghana Cedi');

  /// Gibraltar Pound
  final Currency gip = Currency.create(
    'GIP',
    2,
    symbol: '£',
    country: 'Gibraltar',
    unit: 'Pound',
    name: 'Gibraltar Pound',
  );

  /// Guatemalan Quetzal
  final Currency gtq = Currency.create(
    'GTQ',
    2,
    symbol: 'Q',
    country: 'Guatemala',
    unit: 'Quetzal',
    name: 'Guatemalan Quetzal',
  );

  /// Guinean Franc
  final Currency gnf = Currency.create(
    'GNF',
    0,
    symbol: 'FG',
    pattern: 'S0',
    decimalSeparator: '',
    country: 'Guinea',
    unit: 'Franc',
    name: 'Guinean Franc',
  );

  /// Guyanese Dollar
  final Currency gyd = Currency.create(
    'GYD',
    2,
    country: 'Guyana',
    unit: 'Dollar',
    name: 'Guyanese Dollar',
  );

  /// Haitian Gourde
  final Currency htg = Currency.create(
    'HTG',
    2,
    symbol: 'G',
    country: 'Haiti',
    unit: 'Gourde',
    name: 'Haitian Gourde',
  );

  /// Honduran Lempira
  final Currency hnl = Currency.create(
    'HNL',
    2,
    symbol: 'L',
    country: 'Honduras',
    unit: 'Lempira',
    name: 'Honduran Lempira',
  );

  /// Hong Kong Dollar
  final Currency hkd = Currency.create(
    'HKD',
    2,
    country: 'Hong Kong',
    unit: 'Dollar',
    name: 'Hong Kong Dollar',
  );

  /// Hungarian Forint
  final Currency huf = Currency.create(
    'HUF',
    0,
    symbol: 'Ft',
    pattern: 'S0',
    decimalSeparator: '',
    country: 'Hungary',
    unit: 'Forint',
    name: 'Hungarian Forint',
  );

  /// Icelandic Krona
  final Currency isk = Currency.create(
    'ISK',
    0,
    symbol: 'kr',
    pattern: 'S0',
    decimalSeparator: '',
    country: 'Iceland',
    unit: 'Krona',
    name: 'Icelandic Krona',
  );

  /// Indian Rupee
  final Currency inr = Currency.create('INR', 2,
      symbol: '₹',
      country: 'Indian',
      unit: 'Rupee',
      name: 'Indian Rupee',
      pattern: 'S##,###.00');

  /// Indonesian Rupiah
  final Currency idr = Currency.create(
    'IDR',
    2,
    symbol: 'Rp',
    country: 'Indonesia',
    unit: 'Rupiah',
    name: 'Indonesian Rupiah',
  );

  /// Iranian Rial
  final Currency irr = Currency.create(
    'IRR',
    2,
    symbol: '﷼',
    pattern: 'S0,00',
    country: 'Iran',
    unit: 'Rial',
    name: 'Iranian Rial',
  );

  /// Iraqi Dinar
  final Currency iqd = Currency.create(
    'IQD',
    3,
    symbol: 'ع.د',
    pattern: '0.000S',
    country: 'Iraq',
    unit: 'Dinar',
    name: 'Iraqi Dinar',
  );

  /// Israeli New Shekel
  final Currency ils = Currency.create(
    'ILS',
    2,
    symbol: '₪',
    country: 'Israel',
    unit: 'Shekel',
    name: 'Israeli New Shekel',
  );

  /// Jamaican Dollar
  final Currency jmd = Currency.create(
    'JMD',
    2,
    country: 'Jamaica',
    unit: 'Dollar',
    name: 'Jamaican Dollar',
  );

  /// Japanese Yen
  final Currency jpy = Currency.create('JPY', 0,
      symbol: '¥',
      pattern: 'S0',
      country: 'Japanese',
      unit: 'Yen',
      name: 'Japanese Yen');

  /// Jordanian Dinar
  final Currency jod = Currency.create(
    'JOD',
    3,
    symbol: 'د.ا',
    pattern: '0.000S',
    country: 'Jordan',
    unit: 'Dinar',
    name: 'Jordanian Dinar',
  );

  /// Kazakhstani Tenge
  final Currency kzt = Currency.create(
    'KZT',
    2,
    symbol: '₸',
    country: 'Kazakhstan',
    unit: 'Tenge',
    name: 'Kazakhstani Tenge',
  );

  /// Kenyan Shilling
  final Currency kes = Currency.create(
    'KES',
    2,
    symbol: 'KSh',
    country: 'Kenya',
    unit: 'Shilling',
    name: 'Kenyan Shilling',
  );

  /// Kuwaiti Dinar
  final Currency kwd = Currency.create(
    'KWD',
    3,
    symbol: 'د.ك',
    pattern: '0.000S',
    country: 'Kuwait',
    unit: 'Dinar',
    name: 'Kuwaiti Dinar',
  );

  /// Kyrgyzstani Som
  final Currency kgs = Currency.create(
    'KGS',
    2,
    symbol: 'с',
    country: 'Kyrgyzstan',
    unit: 'Som',
    name: 'Kyrgyzstani Som',
  );

  /// Lao Kip
  final Currency lak = Currency.create(
    'LAK',
    2,
    symbol: '₭',
    country: 'Laos',
    unit: 'Kip',
    name: 'Lao Kip',
  );

  /// Lebanese Pound
  final Currency lbp = Currency.create(
    'LBP',
    2,
    symbol: 'ل.ل',
    country: 'Lebanon',
    unit: 'Pound',
    name: 'Lebanese Pound',
  );

  /// Lesotho Loti
  final Currency lsl = Currency.create(
    'LSL',
    2,
    symbol: 'L',
    country: 'Lesotho',
    unit: 'Loti',
    name: 'Lesotho Loti',
  );

  /// Liberian Dollar
  final Currency lrd = Currency.create(
    'LRD',
    2,
    country: 'Liberia',
    unit: 'Dollar',
    name: 'Liberian Dollar',
  );

  /// Libyan Dinar
  final Currency lyd = Currency.create(
    'LYD',
    3,
    symbol: 'ل.د',
    pattern: '0.000S',
    country: 'Libya',
    unit: 'Dinar',
    name: 'Libyan Dinar',
  );

  /// Macanese Pataca
  final Currency mop = Currency.create(
    'MOP',
    2,
    symbol: r'MOP$',
    country: 'Macao',
    unit: 'Pataca',
    name: 'Macanese Pataca',
  );

  /// Macedonian Denar
  final Currency mkd = Currency.create(
    'MKD',
    2,
    symbol: 'ден',
    pattern: 'S0,00',
    groupSeparator: '.',
    decimalSeparator: ',',
    country: 'North Macedonia',
    unit: 'Denar',
    name: 'Macedonian Denar',
  );

  /// Malagasy Ariary
  final Currency mga = Currency.create(
    'MGA',
    2,
    symbol: 'Ar',
    country: 'Madagascar',
    unit: 'Ariary',
    name: 'Malagasy Ariary',
  );

  /// Malawian Kwacha
  final Currency mwk = Currency.create(
    'MWK',
    2,
    symbol: 'MK',
    country: 'Malawi',
    unit: 'Kwacha',
    name: 'Malawian Kwacha',
  );

  /// Malaysian Ringgit
  final Currency myr = Currency.create(
    'MYR',
    2,
    symbol: 'RM',
    country: 'Malaysia',
    unit: 'Ringgit',
    name: 'Malaysian Ringgit',
  );

  /// Maldivian Rufiyaa
  final Currency mvr = Currency.create(
    'MVR',
    2,
    symbol: 'ރ.',
    country: 'Maldives',
    unit: 'Rufiyaa',
    name: 'Maldivian Rufiyaa',
  );

  /// Mauritanian Ouguiya
  final Currency mru = Currency.create(
    'MRU',
    2,
    symbol: 'UM',
    country: 'Mauritania',
    unit: 'Ouguiya',
    name: 'Mauritanian Ouguiya',
  );

  /// Mauritian Rupee
  final Currency mur = Currency.create(
    'MUR',
    2,
    symbol: '₨',
    country: 'Mauritius',
    unit: 'Rupee',
    name: 'Mauritian Rupee',
  );

  /// Mexican Peso
  final Currency mxn = Currency.create('MXN', 2,
      country: 'Mexican', unit: 'Peso', name: 'Mexican Peso');

  /// Moldovan Leu
  final Currency mdl = Currency.create(
    'MDL',
    2,
    symbol: 'L',
    country: 'Moldova',
    unit: 'Leu',
    name: 'Moldovan Leu',
  );

  /// Mongolian Tugrik
  final Currency mnt = Currency.create(
    'MNT',
    2,
    symbol: '₮',
    country: 'Mongolia',
    unit: 'Tugrik',
    name: 'Mongolian Tugrik',
  );

  /// Moroccan Dirham
  final Currency mad = Currency.create(
    'MAD',
    2,
    symbol: 'د.م.',
    pattern: 'S0,00',
    groupSeparator: ' ',
    decimalSeparator: ',',
    country: 'Morocco',
    unit: 'Dirham',
    name: 'Moroccan Dirham',
  );

  /// Mozambican Metical
  final Currency mzn = Currency.create(
    'MZN',
    2,
    symbol: 'MT',
    country: 'Mozambique',
    unit: 'Metical',
    name: 'Mozambican Metical',
  );

  /// Myanmar Kyat
  final Currency mmk = Currency.create(
    'MMK',
    2,
    symbol: 'K',
    country: 'Myanmar (Burma)',
    unit: 'Kyat',
    name: 'Myanmar Kyat',
  );

  /// Namibian Dollar
  final Currency nad = Currency.create(
    'NAD',
    2,
    country: 'Namibia',
    unit: 'Dollar',
    name: 'Namibian Dollar',
  );

  /// Nepalese Rupee
  final Currency npr = Currency.create(
    'NPR',
    2,
    symbol: 'रू',
    country: 'Nepal',
    unit: 'Rupee',
    name: 'Nepalese Rupee',
  );

  /// Netherlands Antillean Guilder
  final Currency ang = Currency.create(
    'ANG',
    2,
    symbol: 'ƒ',
    country: 'Curaçao and Sint Maarten',
    unit: 'Guilder',
    name: 'Netherlands Antillean Guilder',
  );

  /// New Taiwan Dollar
  final Currency twd = Currency.create('TWD', 0,
      symbol: r'NT$',
      pattern: 'S0',
      country: 'New Taiwan',
      unit: 'Dollar',
      name: 'New Taiwan Dollar');

  /// New Zealand Dollar
  final Currency nzd = Currency.create('NZD', 2,
      country: 'New Zealand', unit: 'Dollar', name: 'New Zealand Dollar');

  /// Nicaraguan Córdoba
  final Currency nio = Currency.create(
    'NIO',
    2,
    symbol: r'C$',
    country: 'Nicaragua',
    unit: 'Córdoba',
    name: 'Nicaraguan Córdoba',
  );

  /// Nigerian Naira
  final Currency ngn = Currency.create('NGN', 2,
      symbol: '₦', country: 'Nigerian', unit: 'Naira', name: 'Nigerian Naira');

  /// North Korean Won
  final Currency kpw = Currency.create(
    'KPW',
    2,
    symbol: '₩',
    country: 'North Korea',
    unit: 'Won',
    name: 'North Korean Won',
  );

  /// Norwegian Krone
  final Currency nok = Currency.create('NOK', 2,
      symbol: 'kr',
      country: 'Norwegian',
      unit: 'Krone',
      name: 'Norwegian Krone');

  /// Omani Rial
  final Currency omr = Currency.create(
    'OMR',
    3,
    symbol: 'ر.ع.',
    pattern: '0.000S',
    country: 'Oman',
    unit: 'Rial',
    name: 'Omani Rial',
  );

  /// Pakistani Rupee
  final Currency pkr = Currency.create(
    'PKR',
    2,
    symbol: '₨',
    country: 'Pakistan',
    unit: 'Rupee',
    name: 'Pakistani Rupee',
  );

  /// Panamanian Balboa
  final Currency pab = Currency.create(
    'PAB',
    2,
    symbol: 'B/.',
    country: 'Panama',
    unit: 'Balboa',
    name: 'Panamanian Balboa',
  );

  /// Papua New Guinean Kina
  final Currency pgk = Currency.create(
    'PGK',
    2,
    symbol: 'K',
    country: 'Papua New Guinea',
    unit: 'Kina',
    name: 'Papua New Guinean Kina',
  );

  /// Paraguayan Guarani
  final Currency pyg = Currency.create(
    'PYG',
    0,
    symbol: '₲',
    pattern: 'S0',
    groupSeparator: '.',
    decimalSeparator: '',
    country: 'Paraguay',
    unit: 'Guarani',
    name: 'Paraguayan Guarani',
  );

  /// Peruvian Sol
  final Currency pen = Currency.create(
    'PEN',
    2,
    symbol: 'S/.',
    country: 'Peru',
    unit: 'Sol',
    name: 'Peruvian Sol',
  );

  /// Philippine Peso
  final Currency php = Currency.create(
    'PHP',
    2,
    symbol: '₱',
    country: 'Philippines',
    unit: 'Peso',
    name: 'Philippine Peso',
  );

  /// Polish Zloty
  final Currency pln = Currency.create('PLN', 2,
      symbol: 'zł',
      groupSeparator: '.',
      decimalSeparator: ',',
      pattern: '0.00S',
      country: 'Polish',
      unit: 'Zloty',
      name: 'Polish Zloty');

  /// Qatari Riyal
  final Currency qar = Currency.create(
    'QAR',
    2,
    symbol: 'ر.ق',
    country: 'Qatar',
    unit: 'Riyal',
    name: 'Qatari Riyal',
  );

  /// Romanian Leu
  final Currency ron = Currency.create(
    'RON',
    2,
    symbol: 'lei',
    pattern: 'S0,00',
    groupSeparator: '.',
    decimalSeparator: ',',
    country: 'Romania',
    unit: 'Leu',
    name: 'Romanian Leu',
  );

  /// Russian Ruble
  final Currency rub = Currency.create('RUB', 2,
      symbol: '₽', country: 'Russia', unit: 'Ruble', name: 'Russian Ruble');

  /// Rwandan Franc
  final Currency rwf = Currency.create(
    'RWF',
    0,
    symbol: 'RF',
    pattern: 'S0',
    decimalSeparator: '',
    country: 'Rwanda',
    unit: 'Franc',
    name: 'Rwandan Franc',
  );

  /// Saint Helena Pound
  final Currency shp = Currency.create(
    'SHP',
    2,
    symbol: '£',
    country: 'Saint Helena',
    unit: 'Pound',
    name: 'Saint Helena Pound',
  );

  /// Samoan Tala
  final Currency wst = Currency.create(
    'WST',
    2,
    symbol: r'WS$',
    country: 'Samoa',
    unit: 'Tala',
    name: 'Samoan Tala',
  );

  /// São Tomé and Príncipe Dobra
  final Currency stn = Currency.create(
    'STN',
    2,
    symbol: 'Db',
    country: 'São Tomé and Príncipe',
    unit: 'Dobra',
    name: 'São Tomé and Príncipe Dobra',
  );

  /// Saudi Riyal
  final Currency sar = Currency.create(
    'SAR',
    2,
    symbol: 'ر.س',
    country: 'Saudi Arabia',
    unit: 'Riyal',
    name: 'Saudi Riyal',
  );

  /// Serbian Dinar
  final Currency rsd = Currency.create(
    'RSD',
    2,
    symbol: 'дин',
    pattern: 'S0,00',
    groupSeparator: '.',
    decimalSeparator: ',',
    country: 'Serbia',
    unit: 'Dinar',
    name: 'Serbian Dinar',
  );

  /// Seychellois Rupee
  final Currency scr = Currency.create(
    'SCR',
    2,
    symbol: '₨',
    country: 'Seychelles',
    unit: 'Rupee',
    name: 'Seychellois Rupee',
  );

  /// Sierra Leonean Leone
  final Currency sle = Currency.create(
    'SLE',
    2,
    symbol: 'Le',
    country: 'Sierra Leone',
    unit: 'Leone',
    name: 'Sierra Leonean Leone',
  );

  /// Singapore Dollar
  final Currency sgd = Currency.create(
    'SGD',
    2,
    country: 'Singapore',
    unit: 'Dollar',
    name: 'Singapore Dollar',
  );

  /// Solomon Islands Dollar
  final Currency sbd = Currency.create(
    'SBD',
    2,
    country: 'Solomon Islands',
    unit: 'Dollar',
    name: 'Solomon Islands Dollar',
  );

  /// Somali Shilling
  final Currency sos = Currency.create(
    'SOS',
    2,
    symbol: 'Sh',
    country: 'Somalia',
    unit: 'Shilling',
    name: 'Somali Shilling',
  );

  /// South African Rand
  final Currency zar = Currency.create('ZAR', 2,
      symbol: 'R',
      country: 'South African',
      unit: 'Rand',
      name: 'South African Rand');

  /// South Korean Won
  final Currency krw = Currency.create('KRW', 0,
      symbol: '₩',
      pattern: 'S0',
      country: 'South Korean',
      unit: 'Won',
      name: 'South Korean Won');

  /// South Sudanese Pound
  final Currency ssp = Currency.create(
    'SSP',
    2,
    symbol: '£',
    country: 'South Sudan',
    unit: 'Pound',
    name: 'South Sudanese Pound',
  );

  /// Sri Lankan Rupee
  final Currency lkr = Currency.create(
    'LKR',
    2,
    symbol: 'Rs',
    country: 'Sri Lanka',
    unit: 'Rupee',
    name: 'Sri Lankan Rupee',
  );

  /// Sudanese Pound
  final Currency sdg = Currency.create(
    'SDG',
    2,
    symbol: '£',
    country: 'Sudan',
    unit: 'Pound',
    name: 'Sudanese Pound',
  );

  /// Surinamese Dollar
  final Currency srd = Currency.create(
    'SRD',
    2,
    country: 'Suriname',
    unit: 'Dollar',
    name: 'Surinamese Dollar',
  );

  /// Swazi Lilangeni
  final Currency szl = Currency.create(
    'SZL',
    2,
    symbol: 'E',
    country: 'Eswatini',
    unit: 'Lilangeni',
    name: 'Swazi Lilangeni',
  );

  /// Swedish Krona
  final Currency sek = Currency.create(
    'SEK',
    2,
    symbol: 'kr',
    pattern: 'S0,00',
    groupSeparator: ' ',
    decimalSeparator: ',',
    country: 'Sweden',
    unit: 'Krona',
    name: 'Swedish Krona',
  );

  /// Swiss Franc
  final Currency chf = Currency.create('CHF', 2,
      symbol: 'fr', country: 'Switzerland', unit: 'Franc', name: 'Swiss Franc');

  /// Syrian Pound
  final Currency syp = Currency.create(
    'SYP',
    2,
    symbol: '£',
    country: 'Syria',
    unit: 'Pound',
    name: 'Syrian Pound',
  );

  /// Tajikistani Somoni
  final Currency tjs = Currency.create(
    'TJS',
    2,
    symbol: 'ЅМ',
    country: 'Tajikistan',
    unit: 'Somoni',
    name: 'Tajikistani Somoni',
  );

  /// Tanzanian Shilling
  final Currency tzs = Currency.create(
    'TZS',
    2,
    symbol: 'Sh',
    country: 'Tanzania',
    unit: 'Shilling',
    name: 'Tanzanian Shilling',
  );

  /// Thai Baht
  final Currency thb = Currency.create(
    'THB',
    2,
    symbol: '฿',
    country: 'Thailand',
    unit: 'Baht',
    name: 'Thai Baht',
  );

  /// Tongan Paʻanga
  final Currency top = Currency.create(
    'TOP',
    2,
    symbol: r'T$',
    country: 'Tonga',
    unit: 'Paʻanga',
    name: 'Tongan Paʻanga',
  );

  /// Trinidad and Tobago Dollar
  final Currency ttd = Currency.create(
    'TTD',
    2,
    symbol: r'TT$',
    country: 'Trinidad and Tobago',
    unit: 'Dollar',
    name: 'Trinidad and Tobago Dollar',
  );

  /// Tunisian Dinar
  final Currency tnd = Currency.create(
    'TND',
    3,
    symbol: 'د.ت',
    pattern: '0.000S',
    country: 'Tunisia',
    unit: 'Dinar',
    name: 'Tunisian Dinar',
  );

  /// Turkish Lira
  final Currency ltry = Currency.create('TRY', 2,
      symbol: '₺', country: 'Turkish', unit: 'Lira', name: 'Turkish Lira');

  /// Turkmenistani Manat
  final Currency tmt = Currency.create(
    'TMT',
    2,
    symbol: 'm',
    country: 'Turkmenistan',
    unit: 'Manat',
    name: 'Turkmenistani Manat',
  );

  /// Ugandan Shilling
  final Currency ugx = Currency.create(
    'UGX',
    0,
    symbol: 'USh',
    pattern: 'S0',
    decimalSeparator: '',
    country: 'Uganda',
    unit: 'Shilling',
    name: 'Ugandan Shilling',
  );

  /// Ukrainian Hryvnia
  final Currency uah = Currency.create(
    'UAH',
    2,
    symbol: '₴',
    country: 'Ukraine',
    unit: 'Hryvnia',
    name: 'Ukrainian Hryvnia',
  );

  /// United Arab Emirates Dirham
  final Currency aed = Currency.create(
    'AED',
    2,
    symbol: 'د.إ',
    country: 'United Arab Emirates',
    unit: 'Dirham',
    name: 'United Arab Emirates Dirham',
  );

  /// United States Dollar
  final Currency usd = Currency.create('USD', 2,
      country: 'United States of America',
      unit: 'Dollar',
      name: 'United States Dollar');

  /// Uruguayan Peso
  final Currency uyu = Currency.create(
    'UYU',
    2,
    symbol: r'$U',
    country: 'Uruguay',
    unit: 'Peso',
    name: 'Uruguayan Peso',
  );

  /// Uzbekistani Som
  final Currency uzs = Currency.create(
    'UZS',
    2,
    symbol: 'soʻm',
    country: 'Uzbekistan',
    unit: 'Som',
    name: 'Uzbekistani Som',
  );

  /// Vanuatu Vatu
  final Currency vuv = Currency.create(
    'VUV',
    0,
    symbol: 'Vt',
    pattern: 'S0',
    decimalSeparator: '',
    country: 'Vanuatu',
    unit: 'Vatu',
    name: 'Vanuatu Vatu',
  );

  /// Venezuelan Bolívar
  final Currency ves = Currency.create(
    'VES',
    2,
    symbol: 'Bs',
    groupSeparator: '.',
    decimalSeparator: ',',
    country: 'Venezuela',
    unit: 'Bolívar',
    name: 'Venezuelan Bolívar',
  );

  /// Vietnamese Dong
  final Currency vnd = Currency.create(
    'VND',
    0,
    symbol: '₫',
    pattern: 'S0',
    groupSeparator: '.',
    decimalSeparator: '',
    country: 'Vietnam',
    unit: 'Dong',
    name: 'Vietnamese Dong',
  );

  /// West African CFA Franc
  final Currency xof = Currency.create(
    'XOF',
    0,
    symbol: 'CFA',
    pattern: 'S0',
    groupSeparator: ' ',
    decimalSeparator: '',
    country: 'West African States',
    unit: 'Franc',
    name: 'West African CFA Franc',
  );

  /// Yemeni Rial
  final Currency yer = Currency.create(
    'YER',
    2,
    symbol: '﷼',
    country: 'Yemen',
    unit: 'Rial',
    name: 'Yemeni Rial',
  );

  /// Zambian Kwacha
  final Currency zmw = Currency.create(
    'ZMW',
    2,
    symbol: 'ZK',
    country: 'Zambia',
    unit: 'Kwacha',
    name: 'Zambian Kwacha',
  );


      
```


# Creating a Currency

The Money2 package includes a list of most of the [Common Currencies](/common-currencies) with the appropriate default format and scale.

In some cases you may need to create your own currency.

Creating a Currency is simple:

```dart
import 'package:money2/money2.dart';
import 'package:test/test.dart';

void main() {
 test('Create Currency - example 1', () {
    // US dollars which have 2 digits after the decimal place
    // using the default patttern: 'S0.00'
    final usd = Currency.create('USD', 2);
    expect(usd.isoCode, equals('USD'));

    // Create currency using a custom pattern
    final usd2 = Currency.create('USD', 2, pattern: 'SCCC 0.00');

    /// we can now use the currency to create a Money instance.
    final amount = Money.parseWithCurrency(r'$1.25', usd2);

    expect(amount.toString(), equals(r'$USD 1.25'));

    // configure everything
    final euro = Currency.create('EUR', 2,
        symbol: '€',
        decimalSeparator: ',',
        groupSeparator: '.',
        pattern: '0,00S',
        country: 'European Union',
        unit: 'Euro',
        name: 'European Union Euro');
    expect(euro.country, equals('European Union'));
  });
}
```

The Currency also allows you to optionally provide a country, unit and name.  The common currencies have currency-specific values for each of these.

You would normally create a single instance of a Currency and re-use that throughout your code base. The easiest way to do this is to [register](/registering-a-currency) your currency.


# Registering a Currency

Money2 ships with a list of [Common Currencies](/common-currencies) however there are times when you may want to add additional currencies (e.g. digital currencies) or change the defaults for an existing Common Currency.

### Common Currencies

Common Currencies are pre-loaded into the currency Registry in Money2.  You can not modify a Common Currency but you can replace it's entry in the Money2 registry.

This means that when parsing a string containing an isoCode or using Currencies().find the modified Currency will be returned.

### Register a Currency

When creating custom Currencies you have two choices, register the currency , with the benefit that you can access it like any other currency, or create and manage the currency in your own code.

Both methods are useful at different times so use the one that best suits your use case.

```dart
import 'package:money2/money2.dart';
import 'package:test/test.dart';

void main() {
 test('register currency', () {
      /// Create currency and replace the CommonCurrency with our
      /// own one.
      final usd = Currency.create('USD', 2);
      Currencies().register(usd);

      /// Change the registered euro currency to have 4 decimal places
      /// Note: CommonCurrencies can't be changed but the registry can.
      final euro = CommonCurrencies().euro.copyWith(decimalDigits: 4);
      Currencies().register(euro);
      final euro4 = Currencies().parse('EUR1500.0');
      expect(euro4.decimalDigits, equals(4));

      /// register a new currency with 8 decimals.
      final doge =
          Currency.create('DODG', 8, symbol: 'Ð', pattern: 'S0.00000000');
      Currencies().register(doge);

      // find a registered currency.
      final nowUseIt = Currencies().find('DODG');
      expect(nowUseIt, isNotNull);
      if (nowUseIt != null) {
        final cost = Money.fromIntWithCurrency(1000000000, nowUseIt);
        expect(cost.toString(), equals('Ð10.00000000'));
      }
    });
}
```


# Parsing

The Money package provides a number of methods to parse a monetary amount:

* Money.parse
* Currency.parse
* Currencies.parse

You may also find Fixed.parse is useful for parsing decimal values which can then be used to create a Money instance.

### Money.parse

Allows you to parse a string containing a monetary amount.

When using Money.parse you must know the currency of the monetary amount.

```dart
import 'package:money2/money2.dart';
import 'package:test/test.dart';

void main() {
  test('Parse money', () {
      /// Parse the amount using default pattern for AUD.
      final t1 = Money.parse('10.00', isoCode: 'AUD');
      expect(t1.toString(), equals(r'$10.00'));

      final t2 = Money.parse(r'$10.00', isoCode: 'AUD');
      expect(t2.amount, equals(Fixed.fromNum(10.00)));

      /// Parse using an alternate pattern
      final t3 =
          Money.parse(r'$10.00 AUD', isoCode: 'AUD', pattern: 'S0.00 CCC');
      expect(t3.amount, equals(Fixed.parse('10.00', scale: 2)));
    });
}

```

### Currency.parse

Parse a monetary amount for a known currency.

```dart
import 'package:money2/money2.dart';
import 'package:test/test.dart';

void main() {

  test('parse with Currency', () {
   /// Parse using a currency.
   final t1 = CommonCurrencies().aud.parse(r'$10.00');
   expect(t1.toString(), equals(r'$10.00'));
   expect(t1.currency.isoCode, equals('AUD'));
  });
}
```

### Currencies.parse

Allows you to parse a monetary amount using an embedded currency code to derive the currency.

```dart
import 'package:money2/money2.dart';
import 'package:test/test.dart';

void main() {

      test('parse with unknown currency', () {
            final t1 = Currencies().parse(r'$AUD10.00');
            expect(t1.toString(), equals(r'$10.00'));
            expect(t1.currency.isoCode, equals('AUD'));
      });
}
```

## If you got this far you deserve a prize.

If you have enough money it's good to tout.

But a word to the unwise.

Spending it gladly can lead to a drought.

##


# Find a currency

To find a Currency that either belongs to one of the [Common Currencies](/common-currencies) or one that you have [registered](/registering-a-currency) you can use the `Currencies().find` method.

```dart
    test('Find a currency', () {
      // Find a registered currency via its code.
      final audCurrency = Currencies().find('AUD');
      final audCostPrice = Money.fromIntWithCurrency(899, audCurrency!);
      expect(audCostPrice.currency.isoCode, equals('AUD'));
    });
```

The Money parser is also able to automatically find a currency if the currency code is a Common Currency or one you have registered.


# Default format

The Currency class also allows you to specify a default format which is used when parsing or formatting a `Money` instance.

If you are using a Common Currency (recommended) then each has a default format pattern appropriate for that currency.

Note: If no other patterns are specified the default pattern is 'S#,##0.00'

```dart
import 'package:money2/money2.dart';
import 'package:test/test.dart';

void main() {
  test('Default Formatting', () {
    final aud = Currency.create('AUD', 2);
      final costPrice = Money.fromIntWithCurrency(1099, aud);
      expect(costPrice.toString(), equals(r'$10.99'));

      final jpy = Currency.create('JPY', 0, symbol: '¥', pattern: 'S#,##0');
      final yenCostPrice = Money.fromIntWithCurrency(1099, jpy);
      expect(yenCostPrice.toString(), equals('¥1099'));

      final euro = Currency.create('EUR', 2,
          symbol: '€',
          decimalSeparator: ',',
          groupSeparator: '.',
          // The pattern MUST use the default group and decimal separators.
          // This allows us to share patterns across currencies.
          pattern: 'S#,##0.00');
      final euroCostPrice = Money.fromIntWithCurrency(899, euro);
      expect(euroCostPrice.toString(), equals('€8,99'));

      final euroValue = euro.parse('€2,99');
      expect(euroValue.toString(), equals('€2,99'));
  });
}

```

You can also use the `Money.format` method to define a specific format where required. See details below


# Symbols

A number of currency have different symbols, you can specify the symbol when creating the currency.

The Common Currencies have the appropriate symbol configured for each currency.

```dart
void main() {
   test('Symbols', () {
      // Create a currency for Japan's yen with the correct symbol
      final jpy = Currency.create('JPY', 0, symbol: '¥');
      expect(jpy.symbol, equals('¥'));
      final euro = Currency.create('EUR', 2, symbol: '€');
      expect(euro.symbol, equals('€'));
    });
}
```


# Separators

Monetary amounts often use separators to format numbers in order to make them easier to read.

The two standard separators are the decimal separator and the group separator.

The Money2 package allows you to control what decimal and group separator are used for each currency.

NOTE:

regardless of the separators you choose for you Currency format patterns MUST always use the default group (,) and decimal (.) separators.

This ensures that we can share patterns across currencies.

e.g.&#x20;

```dart
'S#,##0.00'
```


# Decimal Separator

Numbers use a decimal separator to separate the integer and factional (decimal) component of a number.

In the English speaking world the period (.) is used as the decimal separator, however in large parts of the world the comma (,) is used as the decimal separator.

e.g.

* $USD1,000.99 (one thousand dollars and 99 cents)
* €EUR1.000,99 (one thousand euro and 99 cents)

Money2 use the English convention by default unless you use a CommonCurrency in which case the appropriate separators will have been set for each currency.

To switch to the Euro style convention set the decimalSeparator and groupSeparator arguments when creating a currency.

You will also need to provide an appropriate pattern.

```dart
import 'package:money2/money2.dart';
    test('Decimal Separator', () {
      final euro = Currency.create('EUR', 2,
          symbol: '€',
          decimalSeparator: ',',
          groupSeparator: '.',
          pattern: 'S0,000.00');

      expect(euro.decimalSeparator, equals(','));
    });
```

Note: even if you have switched to alternate separators, Money2 patterns always use the '.' for a decimal separator and the ',' as the thousand group separator. This allows patterns to be shared amongst currencies.


# Group Separator

Numbers also use a group separator to help format large numbers by placing a separator every few digits. e.g. $100,000.00

In the English speaking world the comma (,) is used as the group separator however in large parts of the world the period (.) is used as the group separator.

Money2 use the English convention as default. To switch to the Euro style convention set the decimalSeparator and groupSeparator arguments when creating a currency.

You will also need to provide an appropriate pattern.

```dart
import 'package:money2/money2.dart';

   test('Group Separator', () {
      final euro = Currency.create('EUR', 2,
          symbol: '€',
          decimalSeparator: ',',
          groupSeparator: '.',
          pattern: 'S0,000.00');

      expect(euro.groupSeparator, equals('.'));
    });
```

Note: even if you have switched to alternate separators, Money2 patterns always use the '.' for a decimal separator and the ',' as the thousand group separator. This allows patterns to be shared amongst currencies.


# Creating Money

The Money2 package provide a number of methods to create a `Money` instance.

* Money.fromFixed - from a [Fixed](https://pub.dev/packages/fixed) instance.
* Money.fromInt - from a minorUnit (e.g. cents) stored as an int.
* Money.fromBigInt - from a minorUnit stored as a BigInt.
* Money.parse - parse a string containing an amount.
* Money.fromNum - from a num (int or double) - not recommended
* Money.fromDecimal - from a [Decimal](https://pub.dev/packages/decimal)
* Currency.parse - parse a string containing a monetary amount and assumes the currency
* Currencies.parse - parse a monetary string and determine the currency from the&#x20;

  &#x20;  embedded ISO currency code.

The `Money` variants all require you to pass in the `Currency or a currency code (isoCode)`. The `Currency` variant requires only the monetary value. The `Currencies` variant is able to determine  `Currency` if the passed string amount contains a currency code.

The two most common methods are:

* Money.fromFixed
* Currency.parse


# Money.parse

Money.parse parses a string containing a monetary value.

`Money.fromInt` is faster if you already have the value represented as an integer in minor units.

The simplest variant of `Money.parse` relies on the default `pattern` of the passed currency.

```dart
import 'package:money2/money2.dart';   
test('Money.parse', () {
      final usd = Currency.create('USD', 2);
      final amount = Money.parseWithCurrency(r'$10.25', usd);
      expect(amount.currency.isoCode, equals('USD'));
    });
```

You can also pass an explicit pattern.

```dart
import 'money2.dart';
   test('Money.parse with Pattern', () {
      final usd = Currency.create('USD', 2);
      final amount = Money.parseWithCurrency(r'$10.25', usd, pattern: 'S0.00');
      expect(amount.currency.isoCode, equals('USD'));
    });
```


# Currency.parse

The simplest variant of `Currency.parse` relies on the default pattern of the currency.

```dart
  test('parse with Currency', () {
    /// Parse using a currency.
    var t1 = CommonCurrencies().aud.parse(r'$10.00');
    expect(t1.toString(), equals(r'$10.00'));
    expect(t1.currency.isoCode, equals('AUD'));
  });
```

You can also pass an explict pattern.

```dart
      test('Parse with pattern', () {
        final t2 = CommonCurrencies().aud.parse(r'10.00$', pattern: '0.00S');
        expect(t2.toString(), equals(r'$10.00'));
        expect(t2.currency.isoCode, equals('AUD'));
      });
```


# Money.from

`The Money class allows you to create a Money instance from a variety of other types:`

* Money.fromFixed
* Money.fromInt
* Money.fromBigInt
* Money.fromNum
* Money.fromDecimal

Each of the variants have a `withCurrency` alternate form:

* Money.fromFixedWithCurrency
* Money.fromIntWithCurrency
* Money.fromBigIntWithCurrency
* Money.fromNumWithCurrency
* Money.fromDecimalWithCurrency

The recommended method is  to used ``Money.fromFixed or the `withCurrency` alternative. Using `fromFixed` then allows you to store and transmit your Money amounts without loss of precision.``

`Money` can be instantiated by providing the amount in the minor units of the currency (e.g. cents):

```dart
 test('parse with Currency', () {
        // create one (1) australian dollar
        Money.fromFixed(Fixed.fromInt(100), isoCode: 'AUD');

        Money.parse(r'$1.00', isoCode: 'AUD');

        Money.fromFixedWithCurrency(Fixed.fromInt(100), CommonCurrencies().aud);

        Money.parseWithCurrency(r'$1.00', CommonCurrencies().aud);

        /// Create a money value of $5.10 usd from an int
        Money.fromInt(510, isoCode: 'USD');

        /// Create a money value of ¥25010 from a big int.
        Money.fromBigInt(BigInt.from(25010), isoCode: 'JPY');
      });
```


# Currencies.parse

This method is extremely useful if you have a database/list of monetary amounts that contain their currency ISO code. 'Currencies.parse' will create a `Money` instance of the correct currency based on the currency code embedded in the monetary amount.

An exception will be thrown if the monetary amount does not include a known currency code.

Before you can use `Currencies.parse` you need to ensure that all of the imported currencies are included in [Common Currencies](/common-currencies) or you have [registered ](/registering-a-currency)any additional currencies

If you try to create a `Money` instance for an unregistered `Currency` an `UknownCurrencyException` will be thrown.

```dart
import 'package:money2/money2.dart';

test('parse with Currency', () {
        Currencies().parse(r'$USD10.25', pattern: 'SCCC0.0');
        Currencies().parse('JPY100', pattern: 'CCC0');
});
```


# decimalDigits

When defining a Currency you must define the number of digits after the decimal place that will be stored. This is referred to as the decimalDigits (or more technically scale) of the currency.

```dart
 test('parse with Currency', () {
        final aud = Currency.create('AUD', 2);
        expect(aud.decimalDigits, equals(2));
});
```

In the above example we create a Currency for the Australian Dollar with 2 decimal digits.

The defined number of decimal digits will affect all calculations performed on Money objects created for the Currency in that all calculations will be rounded to the defined number of decimal digits.

### Parsing

When we parse a monetary amount the Currencies number of decimal digits affects how the amount is parsed.

If we parse an AUD amount it will always be stored with 2 decimals regardless of the value we passed:

```
   test('parsing', () {
        final aud = Currency.create('AUD', 2);
        final one = aud.parse(r'$1.12345');
        expect(one.minorUnits.toInt(), equals(112));
      });
```

As you can see, even though we parsed 5 decimal places we only stored 2 decimal places as the currency is defined as storing 2 decimal digits.

### Formatting

The number of decimal digits also affects formatting.   As the monetary amount is always rounded to the number of decimal digits you can't print more decimal places than the amount retrains.

```dart
final aud = Currency.create('AUD', 2);
final one = aud.parse(r'$1.12345');
expect(one.format('#.###'), equals('1.12'));
```

You can however force trailing zeros to be appended by using '0' in your format pattern.

```dart
final aud = Currency.create('AUD', 2);
final one = aud.parse(r'$1.12345');
expect(one.format('0.000'), equals('1.120'));
```

In practice it is recommended that you only use the '0' pattern character for decimal places so you always output a consistent no. of decimals.

## Customising the number of Decimal Digits

Note: Money2 is tested with up to 100 decimal digits but should work with a higher precisions as we store the amount as a BigInt which is only limited by memory.

Money ships with a collection of CommonCurrencies.  Each of the common currencies has a precision that conforms to the currencies standard number of decimal digits. e.g.  The USD has 2 decimal digits.

If you need to use a non-standard number of decimals for a Currency then you will need to create your own currency object rather than relying on one of the CommonCurrencies or copy one of the common currencies.

```dart
CommonCurrencies().aud.copyWith(decimalDigits: 4);
Currency.create('AUD', 4, pattern: '0.0000');

```

If you entire application needs to use the high precision version of the AUD you can overwrite the standard CommonCurrency:

```dart
  test('formatting - trailing zeros', () {
        Currencies()
            .register(CommonCurrencies().aud.copyWith(decimalDigits: 5));
        expect(Currencies().find('AUD')!.decimalDigits, equals(5));
      });
```

Once you have registered the updated currency any code that references  the 'AUD' currency by its code will return your custom currency.


# Formatting

The money class provides a simple way of formatting currency using a pattern.

When you create a Currency instance you can provide a default format pattern which is used to format a Money instance when you call `Money.toString()`.

The CommonCurrencies have default formatters for each Currency which is consistent with that currencies standards.

In some cases you may however want to format a Money instances in a specific manner. In this case you can use:

`Money.format(String pattern)`

```dart
import 'package:money2/money2.dart';
     test('formatting', () {
        final usd = Currency.create('USD', 2);
        final one = Money.fromIntWithCurrency(100, usd);
        expect(one.format('S0'), equals(r'$1'));
      });
```


# Formatting Patterns

Note: the same patterns are used for both formatting and parsing monetary amounts.

The supported pattern characters are:

* S outputs the currencies symbol e.g. $.
* C outputs part of the currency code e.g. USD. You can specify 1,2 or 3 C's. Specifying CCC will output the full code regardless of its length.
  * C - U
  * CC - US
  * CCC - USD - outputs the full currency code regardless of length.
* **denotes a digit.**
* '0' (zero) denotes a digit and and forces padding with leading and trailing zeros.
* '#' denotes a digit is output if required.
* , (comma) a placeholder for the grouping separator
* . (period) a place holder for the decimal separator&#x20;
* '-' a place holder for a '-' character if the amount is -ve.
* '+' a place holder for a '-' or a '+' character dependant on whether the amount is -ve or +ve respectively.

The following rules apply:

* Currency placeholders (S or C) may appear only as a contiguous prefix\
  &#x20;or suffix (not both)  and only one occurrence is allowed.
* A negative symbol '-' or '+' may appear at most once in the numeric portion\
  &#x20;and must be either the first or last character there.

Examples:

```dart
import 'money2.dart';
test('formatting', () {
        var usd = Currency.create('USD', 2);
        final lowPrice = Money.fromIntWithCurrency(1099, usd);
        expect(lowPrice.format('S000.000'), equals(r'$010.990'));

        var costPrice =
            Money.fromIntWithCurrency(10034530, usd); // 100,345.30 usd

        expect(costPrice.format('###,###.00'), equals('100,345.30'));

        expect(costPrice.format('S###,###.##'), equals(r'$100,345.3'));

        expect(costPrice.format('CC###,###.00'), equals('US100,345.30'));

        expect(costPrice.format('CCC###,###.##'), equals('USD100,345.3'));

        expect(costPrice.format('SCC###,###.00'), equals(r'$US100,345.30'));

        usd = Currency.create('USD', 2);
        costPrice = Money.fromIntWithCurrency(10034530, usd); // 100,345.30 usd
        expect(costPrice.format('SCC###,###.##'), equals(r'$US100,345.3'));

        final jpy = Currency.create('JPY', 0, symbol: '¥');
        costPrice = Money.fromIntWithCurrency(345, jpy); // 345 yen
        expect(costPrice.format('SCCC#'), equals('¥JPY345'));

// Bahraini dinar
        final bhd = Currency.create('BHD', 3,
            symbol: 'BD', decimalSeparator: ',', groupSeparator: '.');
        costPrice = Money.fromIntWithCurrency(100345, bhd); // 100.345 bhd
        expect(costPrice.format('SCCC0000.000'), equals('BDBHD0100,345'));
      });
```

## Group Separators

Group Separators have a number of rules on how repeating patterns are treated.\
\
For most currencies the thousand separator repeats every three characters:

&#x20;10,000,000

For india, the pattern is:

1,00,00,000\
\
To support this in a generic manor the group separator has the following rules.\
\
Parsing of the group separator pattern is done 'right to left'.\
Digits are output according to the pattern until all of the pattern has been consumed.

Additional digits then look at the last two groups of the pattern:

\#,##,####

In the above case # and ## are the last two groups, with # as the last group.\
\
If the last group contains more than 1 character we use that group as the pattern to repeat.

If the last group contains only a single character then we use the 2nd last group as the pattern to repeat.

So:

&#x20;\#,### == ###,###,###

\##,### == ##,##,###

\###,### - ###,###,###

\#,#,### - #,#,#,###

Where in each pattern the last group (read right to left) is repeated indefinitely.

<br>


# Storing and Send

When storing and sending monetary amounts you need to ensure that you retain the precision and decimal digits of the amount.

The best way to do this is to store the amount is three components.

* Minor units
* Decimal Digits
* The currencies ISO Code

A value of $AUD1.99 would be stored as:

Minor Units: 199

Decimal Digits: 2

ISO Code: AUD

Using this technique guarantees you will always get back the amount you stored or transmitted.

If you are only using a single currency the Fixed package provides tools to store the minor units and decimal digits.

The Money package allows you to convert a Money amount to from a json format.

```dart

     test('formatting', () {
      final money = Money.fromInt(1025, isoCode: 'USD');
      final moneyJson = money.toJson();

      final expectedJson = <String, dynamic>{
        'minorUnits': '1025',
        'decimals': 2,
        'isoCode': 'USD',
      };

      expect(moneyJson, equals(expectedJson));

      final retrievedAmount = Money.fromJson(moneyJson);
      expect(retrievedAmount.minorUnits.toInt(), equals(1025));
      expect(retrievedAmount.decimalDigits, equals(2));
      expect(retrievedAmount.currency.isoCode, equals('USD'));
    });
```


# Exchange Rates

When manipulating monetary amounts you often need to convert between currencies.

Money2 provide a simple method to convert a `Money` instance to another currency using an exchange rate.

To converts a `Money` instance into a target `Currency` use the `Money.exchangeTo` method and an ExchangeRate.

To do this you need to define an exchange rate which consists of a rate, a from currency and a to currency.&#x20;

### Example

Lets say you have an invoice in Australian Dollars (AUD) which you need to convert to US Dollars (USD).

Start by googling the exchange rate for AUD to USD. You are likely to find something similar to:

1 AUD = 0.68c USD

Which means that for each Australian Dollar you will receive 0.68 US cents. (AKA I'm not traveling to the USA this year).

To do the above conversion:

```dart
import 'package:money2/money2.dart';
import 'package:test/test.dart';

void main() {
  test('exchange rate', () {
      /// Create the AUD invoice amount ($10.00)
      final invoiceAmount = Money.fromInt(1000, isoCode: 'AUD');
      expect(invoiceAmount.format('SCCC 0.00'), equals(r'$AUD 10.00'));

      /// Define the exchange rate in USD (0.68c)
      final auToUsExchangeRate = ExchangeRate.fromFixed(
          Fixed.parse('0.75432', scale: 5),
          fromIsoCode: 'AUD',
          toIsoCode: 'USD',
          toDecimalDigits: 5);
      expect(auToUsExchangeRate.format('0.00000'), equals('0.75432'));

      /// Now do the conversion.
      final usdAmount = invoiceAmount.exchangeTo(auToUsExchangeRate);
      expect(usdAmount.format('SCCC 0.00'), equals(r'$USD 7.54'));
    });
}
```


# Comparison

Equality operator (`==`) returns `true` when both operands are in the same currency and have an equal amount.

```dart
import 'package:money2/money2.dart';
fiveDollars == fiveDollars;  // => true
fiveDollars == sevenDollars; // => false
fiveDollars == fiveEuros;    // => false (different currencies)
```

Money values can be compared with the `<`, `<=`, `>`, `>=` operators, or the method `compareTo()` from the interface `Comparable<Money>`.

**These operators and method `compareTo()` can be used only between money values in the same currency. Runtime error will be thrown on any attempt to compare values in different currencies.**

```dart
import 'package:money2/money2.dart';
fiveDollars < sevenDollars; // => true
fiveDollars > sevenDollars; // => false
fiveEuros < fiveDollars;    // throws ArgumentError!
```


# Currency Predicates

To check that money value has an expected currency use the methods `isInCurrency(Currency)` and `isInSameCurrencyAs(Money)`:

```dart
import 'package:money2/money2.dart';
test('isInCurrency', () {
      final fiveDollars = Money.parse('5.00', isoCode: 'USD');
      final sevenDollars = Money.parse('7.00', isoCode: 'USD');
      final fiveEuros = Money.parse('5.00', isoCode: 'EUR');
      expect(fiveDollars.isInCurrency(CommonCurrencies().usd.isoCode),
          isTrue); // => true
      expect(fiveDollars.isInCurrency(CommonCurrencies().euro.isoCode),
          isFalse); // => false
      expect(fiveDollars.isInSameCurrencyAs(sevenDollars), isTrue); // => true
      expect(fiveDollars.isInSameCurrencyAs(fiveEuros), isFalse); // => false
    });
```


# Value Sign Predicates

To check if a money amount is a credit, a debit or zero, use predicates:

* `Money.isNegative` — returns `true` only if amount is less than `0`.
* `Money.isPositive` — returns `true` only if amount is greater than `0`.
* `Money.isZero` — returns `true` only if amount is `0`.


# Arithmetic Operations

The Money class is immutable, so each operation returns a new Money instance.

Whilst money does support a number of arithmetic operations that take a double as the operator this is STRONGLY DISCOURAGE.  Doubles are imprecise and will introduce rounding errors.

Where ever possible used the methods that take a Fixed, Int or BigInt.

### MultiplyByFixed

Multiply a Money instance by a Fixed instance.

```dart
final kr = Currency.create('KR', 0);
final amount = Money.parseWithCurrency('100', kr, pattern: 'S0');
final halfish = amount.multiplyByFixed(Fixed.parse('0.4', ));
expect(halfish, equals(Money.fromIntWithCurrency(40, kr)));
expect(halfish.decimalDigits, equals(0));
```

### Multiply by num (double or int)

The '\*' operator takes a num and converts it to a Fixed value with 16 decimal places. However the scale of the result is dictated by the Money instance passed to the '\*' operator.

```dart
/// Create the KR currency with 0 decimal digits.
final kr = Currency.create('KR', 0);
/// parse '100' to get a Money storing KR100.
final amount = Money.parseWithCurrency('100', kr, pattern: 'S0');
/// Multiply by 0.4 to get KR40
final halfish = amount * 0.4;
expect(halfish, equals(Money.fromIntWithCurrency(40, kr)));
/// scale of the results is 0 as dictated by the Currency.
expect(halfish.decimalDigits, equals(0));
```

`Money` provides the following arithmetic operators:

* unary `-()`
* `+(Money)`
* `-(Money)`
* `*(num)`
* `/(num)`

**Operators `+` and `-` must be used with operands in same currency, otherwise `ArgumentError` will be thrown.**

```dart
import 'package:money2/money2.dart';
final tenDollars = fiveDollars + fiveDollars;
final zeroDollars = fiveDollars - fiveDollars;
```

Operators `*`, `/` receive a `num` as the second operand. Both operators use *schoolbook rounding* to round result up to a minorUnits of a currency.

```dart
import 'package:money2/money2.dart';
    test('Operators', () {
      final fiveDollars = Money.parse('5.00', isoCode: 'USD');
      final tenDollars = fiveDollars + fiveDollars;
      expect(tenDollars.minorUnits.toInt(), equals(1000));
      final zeroDollars = fiveDollars - fiveDollars;
      expect(zeroDollars.minorUnits.toInt(), equals(0));

      final fifteenCents = Money.fromBigInt(BigInt.from(15), isoCode: 'USD');

      final thirtyCents = fifteenCents * 2; // $0.30
      expect(thirtyCents.minorUnits.toInt(), equals(30));
      final eightCents = fifteenCents * 0.5; // $0.08 (rounded from 0.075)
      expect(eightCents.minorUnits.toInt(), equals(8));
    });
```


# Allocation

#### Allocation According to Ratios

Let's say our company has made a profit of 5 cents, which has to be divided amongst two investors that hold 70% and 30%. Cents can't be divided, so we can't give 3.5 and 1.5 cents. If we round up, the first investor gets 4 cents, the investor gets 2, which means we need to conjure up an additional cent.

The best solution to avoid this pitfall is to use allocation according to ratios.

The sum of an allocation is always guarenteed to be equal to the money instance it is called against.

```dart
import 'money2.dart';
    test('Ratio', () {
      final usd = CommonCurrencies().usd;
      final profit = Money.fromBigIntWithCurrency(BigInt.from(5), usd); // 5¢

      var allocation = profit.allocationAccordingTo([70, 30]);
      expect(allocation[0],
          equals(Money.fromBigIntWithCurrency(BigInt.from(4), usd))); // 4¢
      expect(allocation[1],
          equals(Money.fromBigIntWithCurrency(BigInt.from(1), usd))); // 1¢

      /// The order of ratios is important:
      allocation = profit.allocationAccordingTo([30, 70]);
      expect(allocation[0],
          equals(Money.fromBigIntWithCurrency(BigInt.from(2), usd))); // 2¢
      expect(allocation[1],
          equals(Money.fromBigIntWithCurrency(BigInt.from(3), usd))); // 3¢
    });
```

#### Allocation to N Targets

An amount of money can be allocated to N targets using `allocateTo()`.

```dart
import 'money2.dart';
    test('N Targest', () {
      final usd = CommonCurrencies().usd;

      final value =
          Money.fromBigIntWithCurrency(BigInt.from(800), usd); // $8.00

      final allocation = value.allocationTo(3);
      expect(allocation[0],
          equals(Money.fromBigIntWithCurrency(BigInt.from(267), usd))); // $2.67
      expect(allocation[1],
          equals(Money.fromBigIntWithCurrency(BigInt.from(267), usd))); // $2.67
      expect(allocation[2],
          equals(Money.fromBigIntWithCurrency(BigInt.from(266), usd))); // $2.66
    });
```


# Money encoding/decoding

API for encoding/decoding a money value enables an application to store values in a database or send over a network.

A money value can be encoded to any type. For example it can be coded as a string in the format like 'USD 5.00'.

Note: this is a trivial example and you would simply use the parse/format methods to encode/decode from/to a string.

#### Encoding

```dart
import 'package:money2/money2.dart';

class MoneyToStringEncoder implements MoneyEncoder<String> {
  @override
  String encode(MoneyData data) {
    // Receives MoneyData DTO and produce
    // a string representation of money value...
    final major = data.integerPart.toString();
    final minor = data.decimalPart.toString();

    return '${data.currency.isoCode} $major.${Strings.padRight(minor, 2, '0')}';
  }


    test('Encoding', () {
      final fiveDollars = Money.parse('5.00', isoCode: 'USD');
      final encoded = fiveDollars.encodedBy(MoneyToStringEncoder());
      // Now we can save `encoded` to database...
      expect(encoded, equals('USD 5.00'));
    });

```

#### Decoding

```dart
import 'package:money2/money2.dart';
class StringToMoneyDecoder implements MoneyDecoder<String> {

  Currencies _currencies;

  StringToMoneyDecoder(this._currencies) {
    if (_currencies == null) {
      throw ArgumentError.notNull('currencies');
    }
  }

  /// Returns decoded `MoneyData` or throws a `FormatException`.
  MoneyData decode(String encoded) {
    // If `encoded` has an invalid format throws FormatException;

    // Extracts currency code from `encoded`:
    final currencyCode = ...;

    // Tries to find information about a currency:
    final currency = _currencies.find(currencyCode);
    if (currency == null) {
      throw FormatException('Unknown currency: $currencyCode.');
    }

    // Using `currency.precision`, extracts minorUnits from `encoded`:
    final minorUnits = ...;

    return MoneyData.from(minorUnits, currency);
  }
}
```

```dart
import 'money2.dart';
try {
  final value = Money.decoding('USD 5.00', MyMoneyDecoder(myCurrencies));

  // ...
} on FormatException {
  // ...
}
```


