Search in sources :

Example 16 with Currency

use of android.icu.util.Currency in project j2objc by google.

the class NumberFormat method getEffectiveCurrency.

/**
 * Returns the currency in effect for this formatter.  Subclasses
 * should override this method as needed.  Unlike getCurrency(),
 * this method should never return null.
 * @return a non-null Currency
 * @deprecated This API is ICU internal only.
 * @hide original deprecated declaration
 * @hide draft / provisional / internal are hidden on Android
 */
@Deprecated
protected Currency getEffectiveCurrency() {
    Currency c = getCurrency();
    if (c == null) {
        ULocale uloc = getLocale(ULocale.VALID_LOCALE);
        if (uloc == null) {
            uloc = ULocale.getDefault(Category.FORMAT);
        }
        c = Currency.getInstance(uloc);
    }
    return c;
}
Also used : ULocale(android.icu.util.ULocale) Currency(android.icu.util.Currency)

Example 17 with Currency

use of android.icu.util.Currency in project j2objc by google.

the class NumberFormat method format.

/**
 * <strong>[icu]</strong> Formats a CurrencyAmount. Specialization of format.
 * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
 */
public StringBuffer format(CurrencyAmount currAmt, StringBuffer toAppendTo, FieldPosition pos) {
    // Default implementation -- subclasses may override
    synchronized (this) {
        Currency save = getCurrency(), curr = currAmt.getCurrency();
        boolean same = curr.equals(save);
        if (!same)
            setCurrency(curr);
        format(currAmt.getNumber(), toAppendTo, pos);
        if (!same)
            setCurrency(save);
    }
    return toAppendTo;
}
Also used : Currency(android.icu.util.Currency)

Example 18 with Currency

use of android.icu.util.Currency in project j2objc by google.

the class DecimalFormat method applyPatternWithoutExpandAffix.

private void applyPatternWithoutExpandAffix(String pattern, boolean localized) {
    // '0'
    char zeroDigit = PATTERN_ZERO_DIGIT;
    // '@'
    char sigDigit = PATTERN_SIGNIFICANT_DIGIT;
    char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
    char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
    char percent = PATTERN_PERCENT;
    char perMill = PATTERN_PER_MILLE;
    // '#'
    char digit = PATTERN_DIGIT;
    char separator = PATTERN_SEPARATOR;
    String exponent = String.valueOf(PATTERN_EXPONENT);
    char plus = PATTERN_PLUS_SIGN;
    char padEscape = PATTERN_PAD_ESCAPE;
    // Bug 4212072 [Richard/GCL]
    char minus = PATTERN_MINUS_SIGN;
    if (localized) {
        zeroDigit = symbols.getZeroDigit();
        sigDigit = symbols.getSignificantDigit();
        groupingSeparator = symbols.getGroupingSeparator();
        decimalSeparator = symbols.getDecimalSeparator();
        percent = symbols.getPercent();
        perMill = symbols.getPerMill();
        digit = symbols.getDigit();
        separator = symbols.getPatternSeparator();
        exponent = symbols.getExponentSeparator();
        plus = symbols.getPlusSign();
        padEscape = symbols.getPadEscape();
        // Bug 4212072 [Richard/GCL]
        minus = symbols.getMinusSign();
    }
    char nineDigit = (char) (zeroDigit + 9);
    boolean gotNegative = false;
    int pos = 0;
    // pattern.
    for (int part = 0; part < 2 && pos < pattern.length(); ++part) {
        // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, 2=suffix,
        // 3=prefix in quote, 4=suffix in quote. Subpart 0 is between the prefix and
        // suffix, and consists of pattern characters. In the prefix and suffix,
        // percent, permille, and currency symbols are recognized and translated.
        int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
        // It's important that we don't change any fields of this object
        // prematurely. We set the following variables for the multiplier, grouping,
        // etc., and then only change the actual object fields if everything parses
        // correctly. This also lets us register the data from part 0 and ignore the
        // part 1, except for the prefix and suffix.
        StringBuilder prefix = new StringBuilder();
        StringBuilder suffix = new StringBuilder();
        int decimalPos = -1;
        int multpl = 1;
        int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
        byte groupingCount = -1;
        byte groupingCount2 = -1;
        int padPos = -1;
        char padChar = 0;
        int incrementPos = -1;
        long incrementVal = 0;
        byte expDigits = -1;
        boolean expSignAlways = false;
        int currencySignCnt = 0;
        // The affix is either the prefix or the suffix.
        StringBuilder affix = prefix;
        int start = pos;
        PARTLOOP: for (; pos < pattern.length(); ++pos) {
            char ch = pattern.charAt(pos);
            switch(subpart) {
                case // Pattern proper subpart (between prefix & suffix)
                0:
                    // decimal point, then there should be no right digits.
                    if (ch == digit) {
                        if (zeroDigitCount > 0 || sigDigitCount > 0) {
                            ++digitRightCount;
                        } else {
                            ++digitLeftCount;
                        }
                        if (groupingCount >= 0 && decimalPos < 0) {
                            ++groupingCount;
                        }
                    } else if ((ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
                        if (digitRightCount > 0) {
                            patternError("Unexpected '" + ch + '\'', pattern);
                        }
                        if (ch == sigDigit) {
                            ++sigDigitCount;
                        } else {
                            ++zeroDigitCount;
                            if (ch != zeroDigit) {
                                int p = digitLeftCount + zeroDigitCount + digitRightCount;
                                if (incrementPos >= 0) {
                                    while (incrementPos < p) {
                                        incrementVal *= 10;
                                        ++incrementPos;
                                    }
                                } else {
                                    incrementPos = p;
                                }
                                incrementVal += ch - zeroDigit;
                            }
                        }
                        if (groupingCount >= 0 && decimalPos < 0) {
                            ++groupingCount;
                        }
                    } else if (ch == groupingSeparator) {
                        // == QUOTE) [Richard/GCL]
                        if (ch == QUOTE && (pos + 1) < pattern.length()) {
                            char after = pattern.charAt(pos + 1);
                            if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) {
                                // we have the first quote in 'do' or o''clock.
                                if (after == QUOTE) {
                                    ++pos;
                                // Fall through to append(ch)
                                } else {
                                    if (groupingCount < 0) {
                                        // quoted prefix subpart
                                        subpart = 3;
                                    } else {
                                        // Transition to suffix subpart
                                        // suffix subpart
                                        subpart = 2;
                                        affix = suffix;
                                        sub0Limit = pos--;
                                    }
                                    continue;
                                }
                            }
                        }
                        if (decimalPos >= 0) {
                            patternError("Grouping separator after decimal", pattern);
                        }
                        groupingCount2 = groupingCount;
                        groupingCount = 0;
                    } else if (ch == decimalSeparator) {
                        if (decimalPos >= 0) {
                            patternError("Multiple decimal separators", pattern);
                        }
                        // Intentionally incorporate the digitRightCount, even though it
                        // is illegal for this to be > 0 at this point. We check pattern
                        // syntax below.
                        decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
                    } else {
                        if (pattern.regionMatches(pos, exponent, 0, exponent.length())) {
                            if (expDigits >= 0) {
                                patternError("Multiple exponential symbols", pattern);
                            }
                            if (groupingCount >= 0) {
                                patternError("Grouping separator in exponential", pattern);
                            }
                            pos += exponent.length();
                            // Check for positive prefix
                            if (pos < pattern.length() && pattern.charAt(pos) == plus) {
                                expSignAlways = true;
                                ++pos;
                            }
                            // Use lookahead to parse out the exponential part of the
                            // pattern, then jump into suffix subpart.
                            expDigits = 0;
                            while (pos < pattern.length() && pattern.charAt(pos) == zeroDigit) {
                                ++expDigits;
                                ++pos;
                            }
                            // 3. Require at least one exponent pattern digit
                            if (((digitLeftCount + zeroDigitCount) < 1 && (sigDigitCount + digitRightCount) < 1) || (sigDigitCount > 0 && digitLeftCount > 0) || expDigits < 1) {
                                patternError("Malformed exponential", pattern);
                            }
                        }
                        // Transition to suffix subpart
                        // suffix subpart
                        subpart = 2;
                        affix = suffix;
                        // backup: for() will increment
                        sub0Limit = pos--;
                        continue;
                    }
                    break;
                // Prefix subpart
                case 1:
                case // Suffix subpart
                2:
                    // are in the prefix; otherwise they are illegal if unquoted.
                    if (ch == digit || ch == groupingSeparator || ch == decimalSeparator || (ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
                        // next subpart if we are in the prefix
                        if (subpart == 1) {
                            // prefix subpart
                            // pattern proper subpart
                            subpart = 0;
                            // Reprocess this character
                            sub0Start = pos--;
                            continue;
                        } else if (ch == QUOTE) {
                            // the first quote in 'do' or o''clock.
                            if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
                                ++pos;
                                affix.append(ch);
                            } else {
                                // open quote
                                subpart += 2;
                            }
                            continue;
                        }
                        patternError("Unquoted special character '" + ch + '\'', pattern);
                    } else if (ch == CURRENCY_SIGN) {
                        // Use lookahead to determine if the currency sign is
                        // doubled or not.
                        boolean doubled = (pos + 1) < pattern.length() && pattern.charAt(pos + 1) == CURRENCY_SIGN;
                        // StirngBuffer) [Richard/GCL]
                        if (doubled) {
                            // Skip over the doubled character
                            ++pos;
                            // append two: one here, one below
                            affix.append(ch);
                            if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == CURRENCY_SIGN) {
                                // Skip over the tripled character
                                ++pos;
                                // append again
                                affix.append(ch);
                                currencySignCnt = CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT;
                            } else {
                                currencySignCnt = CURRENCY_SIGN_COUNT_IN_ISO_FORMAT;
                            }
                        } else {
                            currencySignCnt = CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT;
                        }
                    // Fall through to append(ch)
                    } else if (ch == QUOTE) {
                        // first quote in 'do' or o''clock.
                        if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
                            ++pos;
                            // append two: one here, one below
                            affix.append(ch);
                        } else {
                            // open quote
                            subpart += 2;
                        }
                    // Fall through to append(ch)
                    } else if (ch == separator) {
                        // separators in the second pattern (part == 1).
                        if (subpart == 1 || part == 1) {
                            patternError("Unquoted special character '" + ch + '\'', pattern);
                        }
                        sub2Limit = pos++;
                        // Go to next part
                        break PARTLOOP;
                    } else if (ch == percent || ch == perMill) {
                        // Next handle characters which are appended directly.
                        if (multpl != 1) {
                            patternError("Too many percent/permille characters", pattern);
                        }
                        multpl = (ch == percent) ? 100 : 1000;
                        // Convert to non-localized pattern
                        ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE;
                    // Fall through to append(ch)
                    } else if (ch == minus) {
                        // Convert to non-localized pattern
                        ch = PATTERN_MINUS_SIGN;
                    // Fall through to append(ch)
                    } else if (ch == padEscape) {
                        if (padPos >= 0) {
                            patternError("Multiple pad specifiers", pattern);
                        }
                        if ((pos + 1) == pattern.length()) {
                            patternError("Invalid pad specifier", pattern);
                        }
                        // Advance past pad char
                        padPos = pos++;
                        padChar = pattern.charAt(pos);
                        continue;
                    }
                    affix.append(ch);
                    break;
                // Prefix subpart, in quote
                case 3:
                case // Suffix subpart, in quote
                4:
                    // in 'do' or 'don''t'.
                    if (ch == QUOTE) {
                        if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
                            ++pos;
                            affix.append(ch);
                        } else {
                            // close quote
                            subpart -= 2;
                        }
                    // Fall through to append(ch)
                    }
                    // NOTE: In ICU 2.2 there was code here to parse quoted percent and
                    // permille characters _within quotes_ and give them special
                    // meaning. This is incorrect, since quoted characters are literals
                    // without special meaning.
                    affix.append(ch);
                    break;
            }
        }
        if (subpart == 3 || subpart == 4) {
            patternError("Unterminated quote", pattern);
        }
        if (sub0Limit == 0) {
            sub0Limit = pattern.length();
        }
        if (sub2Limit == 0) {
            sub2Limit = pattern.length();
        }
        // though that's what it really is, semantically).
        if (zeroDigitCount == 0 && sigDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) {
            // Handle "###.###" and "###." and ".###"
            int n = decimalPos;
            if (n == 0)
                // Handle ".###"
                ++n;
            digitRightCount = digitLeftCount - n;
            digitLeftCount = n - 1;
            zeroDigitCount = 1;
        }
        // Do syntax checking on the digits, decimal points, and quotes.
        if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) || (decimalPos >= 0 && (sigDigitCount > 0 || decimalPos < digitLeftCount || decimalPos > (digitLeftCount + zeroDigitCount))) || groupingCount == 0 || groupingCount2 == 0 || (sigDigitCount > 0 && zeroDigitCount > 0) || subpart > 2) {
            // subpart > 2 == unmatched quote
            patternError("Malformed pattern", pattern);
        }
        // Make sure pad is at legal position before or after affix.
        if (padPos >= 0) {
            if (padPos == start) {
                padPos = PAD_BEFORE_PREFIX;
            } else if (padPos + 2 == sub0Start) {
                padPos = PAD_AFTER_PREFIX;
            } else if (padPos == sub0Limit) {
                padPos = PAD_BEFORE_SUFFIX;
            } else if (padPos + 2 == sub2Limit) {
                padPos = PAD_AFTER_SUFFIX;
            } else {
                patternError("Illegal pad position", pattern);
            }
        }
        if (part == 0) {
            // Set negative affixes temporarily to match the positive
            // affixes. Fix this up later after processing both parts.
            // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
            // [Richard/GCL]
            posPrefixPattern = negPrefixPattern = prefix.toString();
            posSuffixPattern = negSuffixPattern = suffix.toString();
            useExponentialNotation = (expDigits >= 0);
            if (useExponentialNotation) {
                minExponentDigits = expDigits;
                exponentSignAlwaysShown = expSignAlways;
            }
            int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
            // The effectiveDecimalPos is the position the decimal is at or would be
            // at if there is no decimal. Note that if decimalPos<0, then
            // digitTotalCount == digitLeftCount + zeroDigitCount.
            int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
            boolean useSigDig = (sigDigitCount > 0);
            setSignificantDigitsUsed(useSigDig);
            if (useSigDig) {
                setMinimumSignificantDigits(sigDigitCount);
                setMaximumSignificantDigits(sigDigitCount + digitRightCount);
            } else {
                int minInt = effectiveDecimalPos - digitLeftCount;
                setMinimumIntegerDigits(minInt);
                // Upper limit on integer and fraction digits for a Java double
                // [Richard/GCL]
                setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount + minInt : DOUBLE_INTEGER_DIGITS);
                _setMaximumFractionDigits(decimalPos >= 0 ? (digitTotalCount - decimalPos) : 0);
                setMinimumFractionDigits(decimalPos >= 0 ? (digitLeftCount + zeroDigitCount - decimalPos) : 0);
            }
            setGroupingUsed(groupingCount > 0);
            this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
            this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount) ? groupingCount2 : 0;
            this.multiplier = multpl;
            setDecimalSeparatorAlwaysShown(decimalPos == 0 || decimalPos == digitTotalCount);
            if (padPos >= 0) {
                padPosition = padPos;
                // to be fixed up below
                formatWidth = sub0Limit - sub0Start;
                pad = padChar;
            } else {
                formatWidth = 0;
            }
            if (incrementVal != 0) {
                // BigDecimal scale cannot be negative (even though this makes perfect
                // sense), so we need to handle this.
                int scale = incrementPos - effectiveDecimalPos;
                roundingIncrementICU = BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0);
                if (scale < 0) {
                    roundingIncrementICU = roundingIncrementICU.movePointRight(-scale);
                }
                roundingMode = BigDecimal.ROUND_HALF_EVEN;
            } else {
                setRoundingIncrement((BigDecimal) null);
            }
            // Update currency sign count for the new pattern
            currencySignCount = currencySignCnt;
        } else {
            // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
            // [Richard/GCL]
            negPrefixPattern = prefix.toString();
            negSuffixPattern = suffix.toString();
            gotNegative = true;
        }
    }
    // Bug 4140009 Process the empty pattern [Richard/GCL]
    if (pattern.length() == 0) {
        posPrefixPattern = posSuffixPattern = "";
        setMinimumIntegerDigits(0);
        setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
        setMinimumFractionDigits(0);
        _setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
    }
    if (!gotNegative || (negPrefixPattern.equals(posPrefixPattern) && negSuffixPattern.equals(posSuffixPattern))) {
        negSuffixPattern = posSuffixPattern;
        negPrefixPattern = PATTERN_MINUS_SIGN + posPrefixPattern;
    }
    setLocale(null, null);
    // save the pattern
    formatPattern = pattern;
    // special handlings for currency instance
    if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) {
        // reset rounding increment and max/min fractional digits
        // by the currency
        Currency theCurrency = getCurrency();
        if (theCurrency != null) {
            setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage));
            int d = theCurrency.getDefaultFractionDigits(currencyUsage);
            setMinimumFractionDigits(d);
            _setMaximumFractionDigits(d);
        }
        // initialize currencyPluralInfo if needed
        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT && currencyPluralInfo == null) {
            currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
        }
    }
    resetActualRounding();
}
Also used : Currency(android.icu.util.Currency) AttributedString(java.text.AttributedString)

Example 19 with Currency

use of android.icu.util.Currency in project j2objc by google.

the class CompactDecimalFormat method format.

/* INTERNALS */
private StringBuffer format(double number, Currency curr, StringBuffer toAppendTo, FieldPosition pos) {
    if (curr != null && style == CompactStyle.LONG) {
        throw new UnsupportedOperationException("CompactDecimalFormat does not support LONG style for currency.");
    }
    // Compute the scaled amount, prefix, and suffix appropriate for the number's magnitude.
    Output<Unit> currencyUnit = new Output<Unit>();
    Amount amount = toAmount(number, curr, currencyUnit);
    Unit unit = amount.getUnit();
    // Note that currencyUnit is a remnant.  In almost all cases, it will be null.
    StringBuffer prefix = new StringBuffer();
    StringBuffer suffix = new StringBuffer();
    if (currencyUnit.value != null) {
        currencyUnit.value.writePrefix(prefix);
    }
    unit.writePrefix(prefix);
    unit.writeSuffix(suffix);
    if (currencyUnit.value != null) {
        currencyUnit.value.writeSuffix(suffix);
    }
    if (curr == null) {
        // Prevent locking when not formatting a currency number.
        toAppendTo.append(escape(prefix.toString()));
        super.format(amount.getQty(), toAppendTo, pos);
        toAppendTo.append(escape(suffix.toString()));
    } else {
        // This has to be synchronized since this information is held in the state of the DecimalFormat object.
        synchronized (this) {
            String originalPattern = this.toPattern();
            Currency originalCurrency = this.getCurrency();
            StringBuffer newPattern = new StringBuffer();
            // Write prefixes and suffixes to the pattern.  Note that we have to apply it to both halves of a
            // positive/negative format (separated by ';')
            int semicolonPos = originalPattern.indexOf(';');
            newPattern.append(prefix);
            if (semicolonPos != -1) {
                newPattern.append(originalPattern, 0, semicolonPos);
                newPattern.append(suffix);
                newPattern.append(';');
                newPattern.append(prefix);
            }
            newPattern.append(originalPattern, semicolonPos + 1, originalPattern.length());
            newPattern.append(suffix);
            // Overwrite the pattern and currency.
            setCurrency(curr);
            applyPattern(newPattern.toString());
            // Actually perform the formatting.
            super.format(amount.getQty(), toAppendTo, pos);
            // Reset the pattern and currency.
            setCurrency(originalCurrency);
            applyPattern(originalPattern);
        }
    }
    return toAppendTo;
}
Also used : Output(android.icu.util.Output) CurrencyAmount(android.icu.util.CurrencyAmount) Currency(android.icu.util.Currency)

Example 20 with Currency

use of android.icu.util.Currency in project j2objc by google.

the class NumberFormatTest method Test6816.

@Test
public void Test6816() {
    Currency cur1 = Currency.getInstance(new Locale("und", "PH"));
    NumberFormat nfmt = NumberFormat.getCurrencyInstance(new Locale("und", "PH"));
    DecimalFormatSymbols decsym = ((DecimalFormat) nfmt).getDecimalFormatSymbols();
    Currency cur2 = decsym.getCurrency();
    if (!cur1.getCurrencyCode().equals("PHP") || !cur2.getCurrencyCode().equals("PHP")) {
        errln("FAIL: Currencies should match PHP: cur1 = " + cur1.getCurrencyCode() + "; cur2 = " + cur2.getCurrencyCode());
    }
}
Also used : Locale(java.util.Locale) ULocale(android.icu.util.ULocale) DecimalFormatSymbols(android.icu.text.DecimalFormatSymbols) Currency(android.icu.util.Currency) CompactDecimalFormat(android.icu.text.CompactDecimalFormat) DecimalFormat(android.icu.text.DecimalFormat) RuleBasedNumberFormat(android.icu.text.RuleBasedNumberFormat) NumberFormat(android.icu.text.NumberFormat) Test(org.junit.Test)

Aggregations

Currency (android.icu.util.Currency)28 Test (org.junit.Test)19 ULocale (android.icu.util.ULocale)13 Locale (java.util.Locale)7 DecimalFormatSymbols (android.icu.text.DecimalFormatSymbols)4 NumberFormat (android.icu.text.NumberFormat)4 RuleBasedNumberFormat (android.icu.text.RuleBasedNumberFormat)4 CurrencyAmount (android.icu.util.CurrencyAmount)4 CompactDecimalFormat (android.icu.text.CompactDecimalFormat)3 DecimalFormat (android.icu.text.DecimalFormat)3 AttributedString (java.text.AttributedString)3 StandardPlural (android.icu.impl.StandardPlural)2 MeasureUnit (android.icu.util.MeasureUnit)2 BigDecimal (android.icu.math.BigDecimal)1 MeasureFormat (android.icu.text.MeasureFormat)1 GlobalizationPreferences (android.icu.util.GlobalizationPreferences)1 Output (android.icu.util.Output)1 ParseException (java.text.ParseException)1 ParsePosition (java.text.ParsePosition)1