在 Java 中的外国语言环境中格式化货币

Posted

技术标签:

【中文标题】在 Java 中的外国语言环境中格式化货币【英文标题】:Formatting Currencies in Foreign Locales in Java 【发布时间】:2011-10-19 21:25:29 【问题描述】:

我正在尽我最大的努力寻找一种方法,使用 Java 来在各种语言环境中格式化外币,这些语言不是该货币的默认设置。我找到了 java.util.Currency,它可以代表用于各种语言环境的正确符号。也就是说,对于美元,它在美国为我提供符号 $,在其他国家提供美元或美元。此外,我还找到了 java.text.NumberFormat,它将为特定语言环境格式化货币。我的问题 - util.Currency 将提供适当的符号和代码来表示其非默认语言环境中的货币,但不会以任何特定于语言环境的方式格式化货币。 NumberFormat 假定我传递给它的数字(带有语言环境)是该语言环境的货币,而不是外币。

例如,如果我使用 getCurrencyInstance(Locale.GERMANY) 然后格式化 (1000) 它假定我正在格式化 1000 欧元。实际上,对于美元、日元或任何其他货币,我可能需要正确的德语本地化表示(正确的小数和千位分隔符,无论是在金额之前还是之后放置符号)。到目前为止,我能够得出的最好的结果是使用 NumberFormat 格式化数字,然后在输出中搜索非数字字符并将它们替换为从 util.Currency 派生的符号。但是,这非常脆弱,对于我的目的来说可能不够可靠。想法?任何帮助深表感谢。

【问题讨论】:

1) 你是否要在 GUI 的某个地方显示这些数据,2) 我从未尝试过(ISO Ccy 代码相关)然后我的问题是你尝试了美元、澳元、新加坡元的 print_out 符号可能是有符号 $,3) 我建议寻找 ISO 代码,而不是混合并设置不同的区域设置,例如因为 out_dated oanda.com/help/currency-iso-code-country 但首先来自谷歌, 与此相关的原因是您不应该将钱存储在原始的“自己的”中:它们应该是还包含它们所代表的货币的类的一部分(500 美元是 不 500日元)。 你看到我下面给出的答案了吗?这能解决问题吗? 【参考方案1】:

尝试在 getCurrencyInstance(Locale.GERMANY) 返回的实例上使用setCurrency

坏了

java.text.NumberFormat format = java.text.NumberFormat.getCurrencyInstance(java.util.Locale.GERMANY);
System.out.println(format.format(23));

产出:23,00 欧元

固定

java.util.Currency usd = java.util.Currency.getInstance("USD");
java.text.NumberFormat format = java.text.NumberFormat.getCurrencyInstance(java.util.Locale.GERMANY);
format.setCurrency(usd);
System.out.println(format.format(23));

产出:23,00 美元

【讨论】:

像魅力一样工作!谢谢! 在下面更好地查看 Testo Testini 的答案。 坦率地说,这仍然是从 Java 中破坏的。最佳输出应该是 Output: 23,00 $ @Diolor 不,这不是最佳输出。那是错误的。要获得该输出,您必须使用 US-Locale。货币符号与货币代码不匹配 1:1。因此,相同的货币符号在不同的语言环境中可能具有不同的含义。这就是为什么只有在语言环境和货币匹配时才允许使用货币符号的原因。【参考方案2】:

我想补充一下 les2 https://***.com/a/7828512/1536382 的回答,我相信小数位数不是取自货币,必须手动设置,否则如果客户端 (NumberFormat) 具有 JAPAN 语言环境并且货币是 EURO 或 en_US,然后金额显示为'a la' Yen',没有小数位,但这与预期不同,因为欧元小数是相关的,也适用于日语;-)。

因此 les2 示例可以通过添加 format.setMaximumFractionDigits(usd.getDefaultFractionDigits()); 进行改进,在该示例的特定情况下不相关,但使用带小数的数字和 Locale.JAPAN 作为 NumberFormat 的区域设置变得相关。

    java.util.Currency usd = java.util.Currency.getInstance("USD");
    java.text.NumberFormat format = java.text.NumberFormat.getCurrencyInstance(
          java.util.Locale.JAPAN);
    format.setCurrency(usd);
    System.out.println(format.format(23.23));
    format.setMaximumFractionDigits(usd.getDefaultFractionDigits());
    System.out.println(format.format(23.23));

将输出:

USD23
USD23.23

在NumberFormat code 中,对格式的初始/默认货币执行了类似的操作,调用方法DecimalFormat#adjustForCurrencyDefaultFractionDigits。之后用NumberFormat.setCurrency换币时不做此操作

【讨论】:

好收获。这真的很乏味,以至于要求成为一个实用程序库,例如,commons-currency。一个存在吗? CurrencyUtils.getFormatter(Locale, Currency).format(BigDecimal) 把这个留给任何可能被这种行为所困扰的人:在 android 上(特别是三星 Galaxy Note 2 和 4.3),使用语言环境 de_CH(德意志(瑞士)),如果我得到默认的货币格式化程序,并调用 setCurrency("CAD"),我将得到“瑞典”四舍五入。也就是说,26.98 的值被格式化为 27.00!但是使用 setCurrency("USD"),我看不到这种行为。像上面那样调用 setMaximumFractionDigits() 似乎可以解决问题,但这对我来说没有意义,因为默认情况下 CAD 和 USD 都使用 2 个小数位。 这仅解决了显示的最大小数位数的问题。其他所有内容,例如四舍五入行为和货币符号的位置,都将保留指定区域设置的本地货币设置。 @gnuf 我试过你的例子,但我看不到 CAD 的四舍五入,如果使用 JPY,也没有小数位。小数位值 (2) 来自区域设置“de_CH”的“Schweizer Franken”初始/默认货币。另请参阅更新的答案。 @mpontes 货币符号的放置我认为是正确的特定于语言环境的(例如:法国人将符号放在任何货币的金额之后)。您能否扩展舍入行为?可以举个例子。谢谢。【参考方案3】:
import java.util.*;
import java.text.*;

public class Solution 

    public static void main(String[] args) 
        Scanner scanner = new Scanner(System.in);
        double payment = scanner.nextDouble();
        scanner.close();

        NumberFormat lp;  //Local Payment

        lp = NumberFormat.getCurrencyInstance(Locale.US);
        System.out.println("US: " + lp.format(payment));

        lp = NumberFormat.getCurrencyInstance(new Locale("en", "in"));
        System.out.println("India: " + lp.format(payment));

        lp = NumberFormat.getCurrencyInstance(Locale.CHINA);
        System.out.println("China: " + lp.format(payment));

        lp = NumberFormat.getCurrencyInstance(Locale.FRANCE);
        System.out.println("France: " + lp.format(payment));
    

【讨论】:

这是部分国家/地区货币格式化程序的完整代码。【参考方案4】:

代码如下,参考Java Locale:

Scanner scanner = new Scanner(System.in);
double payment = scanner.nextDouble();
scanner.close();

// Write your code here.
String china = NumberFormat.getCurrencyInstance(new Locale("zh", "CN")).format(payment);
String india = NumberFormat.getCurrencyInstance(new Locale("en", "IN")).format(payment);
String us = NumberFormat.getCurrencyInstance(Locale.US).format(payment);
String france = NumberFormat.getCurrencyInstance(Locale.FRANCE).format(payment);

System.out.println("US: " + us);
System.out.println("India: " + india);
System.out.println("China: " + china);
System.out.println("France: " + france);

【讨论】:

【参考方案5】:
Scanner scanner = new Scanner(System.in);
double payment = scanner.nextDouble();
scanner.close();
java.text.NumberFormat formatUS = java.text.NumberFormat.getCurrencyInstance(java.util.Locale.US);
String us=formatUS.format(payment);
java.text.NumberFormat formatIn = java.text.NumberFormat.getCurrencyInstance(new java.util.Locale("en","in"));
String india=formatIn.format(payment);
java.text.NumberFormat formatChina = java.text.NumberFormat.getCurrencyInstance(java.util.Locale.CHINA);
String china=formatChina.format(payment);
java.text.NumberFormat formatFrance = java.text.NumberFormat.getCurrencyInstance(java.util.Locale.FRANCE);
String france=formatFrance.format(payment);

System.out.println("US: " + us);
System.out.println("India: " + india);
System.out.println("China: " + china);
System.out.println("France: " + france);

【讨论】:

【参考方案6】:

更好的方法是导入 java.util.Locale

然后使用这样的方法:

NumberFormat.getCurrencyInstance(Locale.theCountryYouWant);

例如NumberFormat.getCurrencyInstance(Locale.US);

【讨论】:

【参考方案7】:

    import java.util.*;
    import java.text.*;
    public class CurrencyConvertor    
        public static void main(String[] args) 
            Scanner scanner = new Scanner(System.in);
            double curr= scanner.nextDouble();
            scanner.close();
            if(curr>=0 && curr<=1000000000)
     NumberFormat france = NumberFormat.getCurrencyInstance(Locale.FRANCE);
    NumberFormat us = NumberFormat.getCurrencyInstance(Locale.US);
    NumberFormat china = NumberFormat.getCurrencyInstance(Locale.CHINA);
            NumberFormat india = NumberFormat.getCurrencyInstance(Locale.ENGLISH);
             
          System.out.println("India: "+NumberFormat.getCurrencyInstance(new Locale("en","IN")).format(curr)); 
           System.out.println("US: " + us.format(curr));
          System.out.println("China: "+ china.format(curr));
            System.out.println("France: " + france.format(curr));
            
        
    

【讨论】:

以上是关于在 Java 中的外国语言环境中格式化货币的主要内容,如果未能解决你的问题,请参考以下文章

JVM 从哪里获得 ubuntu 10.10 中的语言环境设置?

如何从字符串构造货币语言环境?

语言环境在 iOS 模拟器中返回错误的货币符号

如何强制Excel使用Apache POI以西班牙语语言环境显示值

如何在不使用语言环境模块的情况下获取国际货币符号?

用户当前语言环境的货币符号