diff --git a/currency.currency.inc b/currency.currency.inc
index eb1c80a..026697b 100644
--- a/currency.currency.inc
+++ b/currency.currency.inc
@@ -247,6 +247,7 @@ function currency_currency_info() {
     )),
     new Currency(array(
       'code' => 'EUR',
+      'minor_unit' => 2,
       'sign' => '€',
       'title' => t('Euro'),
     )),
@@ -771,6 +772,7 @@ function currency_currency_info() {
     )),
     new Currency(array(
       'code' => 'UAH',
+      'minor_unit' => 2,
       'sign' => 'грн.',
       'title' => t('Ukraine Hryvnia'),
     )),
diff --git a/currency.info b/currency.info
index 9f6abf8..401ea5b 100755
--- a/currency.info
+++ b/currency.info
@@ -6,3 +6,4 @@ dependencies[] = ctools
 files[] = includes/Currency.inc
 files[] = includes/CurrencyBaseAbstract.inc
 files[] = tests/CurrencyCRUDWebTestCase.test
+files[] = tests/CurrencyWebTestCase.test
diff --git a/includes/Currency.inc b/includes/Currency.inc
index 83ef5b3..17cf261 100644
--- a/includes/Currency.inc
+++ b/includes/Currency.inc
@@ -38,7 +38,7 @@ class Currency extends CurrencyBaseAbstract {
    *
    * @var integer
    */
-  public $minor_unit = NULL;
+  public $minor_unit = 0;
 
   /**
    * ISO 4217 currency number.
@@ -60,4 +60,135 @@ class Currency extends CurrencyBaseAbstract {
    * @var string
    */
   public $title = '';
+
+  /**
+   * Gets an amounts major unit.
+   *
+   * @param integer|string $amount
+   *
+   * @return integer
+   */
+  function majorUnit($amount) {
+    return (int) substr($amount, 0, -$this->minor_unit);
+  }
+
+  /**
+   * Gets an amounts minor unit.
+   *
+   * @param integer|string $amount
+   *
+   * @return integer
+   */
+  function minorUnit($amount) {
+    return (int) substr($amount, -$this->minor_unit);
+  }
+
+  /**
+   * Splits a string in a unicode-safe way.
+   *
+   * @param string
+   *
+   * @return array
+   */
+  function str_split($string, $split_length = 1) {
+    preg_match_all('/.{' . $split_length . '}/u', $string, $matches);
+
+    return $matches[0];
+  }
+
+  /**
+   * Reverses a string in a unicode-safe way.
+   *
+   * @param string
+   *
+   * @return string
+   */
+  function strrev($string) {
+    return implode(array_reverse($this->str_split($string)));
+  }
+
+  /**
+   * Formats an amount.
+   *
+   * @throws Exception
+   *
+   * @param integer $amount
+   * @param string $format
+   *   The output equals $format, but the following replacements will be made:
+   *   - Zeroes (0) will be replaced by the amount, or kept if there are more
+   *     zeroes than the amount has digits.
+   *   - Hashes (#) will be replaced by the amount. If there are more hashes
+   *     than the amount has digits, they will be removed, along with any
+   *     non-digit characters between them.
+   *   - ¤ will be replaced by the currency sign.
+   *   - XXX will be replaced by the ISO 4217 currency code.
+   *   - 999 will be replaced by the ISO 4217 currency number.
+   *   - Minus signs (-) will be removed if the amount is not negative.
+   *   - SEPARATOR indicates the separation between the format's major (on its
+   *     left) and minor part (on its right).
+   *   Example: formatting the euro amount 123456 using '¤-##.##0,00' results
+   *   in €1.234,56.
+   *
+   * @return string
+   */
+  function format($amount, $format) {
+    // Split all required data in major and minor, and reverse all major data.
+    $format_fragments = explode('SEPARATOR', $format);
+    if (count($format_fragments) != 2) {
+      throw new Exception(t('Format contains more or less than one <code>SEPARATOR</code>.'));
+    }
+    $sections = array(
+      'major' => array(
+        // Reverse all major data, because we format the units from the
+        // separator outward.
+        'format' => $this->strrev($format_fragments[0]),
+        'digits' => $this->strrev($this->majorUnit($amount)),
+      ),
+      'minor' => array(
+        'format' => $format_fragments[1],
+        'digits' => $this->minorUnit($amount),
+      ),
+    );
+
+    // Render the major and minor units from the separator outward.
+    $output = array(
+      'major' => '',
+      'minor' => '',
+    );
+    foreach ($sections as $section => $data) {
+      // Split the format into its characters in a unicode-safe way.
+      $characters = preg_split('//u', $data['format']);
+      // We keep track of the first replaceable character in the format, so if
+      // the amount has more digits than there are replaceable characters, we
+      // replace the first character by all remaining digits.
+      $digits = str_split($data['digits']);
+      $section_output = '';
+      foreach ($characters as $position => $character) {
+        // Replace replaceable characters, but only if we still have digits left
+        // to replace them with.
+        if ($digits && ($character == '#' || $character ==='0')) {
+          $output[$section] .= array_shift($digits);
+        }
+        else {
+          $output[$section] .= $character;
+        }
+      }
+      // Remove remaining hashes and whatever is between them and the last
+      // digit.
+      $output[$section] = preg_replace('/(\D*)#/', '', $output[$section]);
+    }
+    // Put the major unit back in its original order and join the units.
+    $output = $this->strrev($output['major']) . $output['minor'];
+
+    // Insert the currency sign, code, and number.
+    $output = str_replace('¤', $this->sign, $output);
+    $output = str_replace('XXX', $this->code, $output);
+    $output = str_replace('999', $this->number, $output);
+    // Remove the minus sign if the amount is not negative.
+    if ($amount >= 0) {
+      $output = str_replace('-', '', $output);
+    }
+
+    return $output;
+  }
 }
diff --git a/tests/CurrencyWebTestCase.test b/tests/CurrencyWebTestCase.test
new file mode 100644
index 0000000..4932629
--- /dev/null
+++ b/tests/CurrencyWebTestCase.test
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Contains class CurrencyWebTestCase.
+ */
+
+/**
+ * Tests Currency's functionality.
+ */
+class CurrencyWebTestCase extends DrupalWebTestCase {
+
+  static function getInfo() {
+    return array(
+      'name' => 'Currency',
+      'group' => 'Currency',
+    );
+  }
+
+  function setUp(array $modules = array()) {
+    parent::setUp($modules + array('currency'));
+  }
+
+  /**
+   * Test amount formatting.
+   */
+  function testFormat() {
+    ctools_include('export');
+    $amount = -123456789;
+    // Use different currencies to test multibyte (some currency signs).
+    $currency_codes = array('EUR', 'UAH');
+    foreach ($currency_codes as $currency_code) {
+      $currency = ctools_export_crud_load('currency', $currency_code);
+      $formats = array(
+        '¤-###.###.###.##0,SEPARATOR##0' => $currency->sign . '-1.234.567,890',
+        'XXX ##0,SEPARATOR0000' => $currency_code . ' 567,8900',
+        // Test some unusual character combinations and positions.
+        '--¤####000/@##0SEPARATOR<span style="text-transform: uppercase;">#XXX</span>--' => '--' . $currency->sign . '1234/@567<span style="text-transform: uppercase;">8' . $currency_code . '</span>--',
+      );
+      foreach ($formats as $format => $formatted) {
+        $this->assertEqual($currency->format($amount, $format), $formatted, t('<code>Currency::format()</code> formats amount <code>!currency_code!amount</code> as %formatted using format <code>@format</code>.', array(
+          '!currency_code' => $currency_code,
+          '!amount' => $amount,
+          '%formatted' => $formatted,
+          '@format' => $format,
+        )));
+      }
+    }
+  }
+}
\ No newline at end of file
