【问题标题】:NumberFormat incorrect parse for non default locale in javaJava 中非默认语言环境的 NumberFormat 解析不正确
【发布时间】:2017-10-05 05:21:12
【问题描述】:

NumberFormat 错误地解析了默认 en_US 以外的区域设置的数字。例如,对 fr_CA 的解析给出了不正确的结果。

NumberFormat nf = NumberFormat.getNumberInstance(new Locale("fr_CA"));
Number num = nf.parse("2.302,52");

输出为:2.302

预期输出:2302,522302.52

基本上是把这个数字的值从 2000 变成了 2,这是不正确的。

详情请看以下截图:

我无法识别出了什么问题,请帮忙!

【问题讨论】:

  • @Jens:一定要注意这个值不对,必须是2302.52,内部表示不能改变值!
  • @Jens:既然你已经删除了你的评论,你能不能也修改一下你的反对票。

标签: java locale number-formatting


【解决方案1】:

编辑 1:

通过将小数点和分组分隔符设置为,我能够使用 DecimalFormat 正确解析非默认语言环境值:

        /**
         * Testing DF parse
         */
        DecimalFormat df = new DecimalFormat();
        DecimalFormatSymbols symbols = new DecimalFormatSymbols();
        symbols.setDecimalSeparator(',');
        symbols.setGroupingSeparator('.');
        df.setDecimalFormatSymbols(symbols);
        Number num = df.parse("2.302,52"); // OUTPUT is: 2302.52 -> correctly parsed

        /**
         * Round off and format
         */
        double d = num.doubleValue();
        double roundedVal = Math.round(d); // OUTPUT is: 2303.0 -> correctly rounded off
        String localeAwareVlue = df.format(roundedVal); // OUTPUT is: 2.303 -> using correct grouping separator
        valueString = localeAwareVlue;

但我真的希望能够在运行时动态地执行此操作,而不必为我可能收到的每种语言/国家/地区组合设置分隔符。请提供任何建议。

编辑 2:

我最终得到了以下最终代码,以便能够动态解析和格式化本地化值。这适用于 ###,###.## 和 ###.###,## 等模式 - 假设是 -

  1. 收到的数据总是只有 2 位小数
  2. 小数分隔符可以是逗号或句点
  3. 分组分隔符可以是句点或逗号

    String localValue = args.get(0).toString();
    // String locale = args.get(1).toString();
    
    char decChar = localValue.charAt(localValue.length()-3);
    char grpChar = ',';
    if(decChar == ',') {
        grpChar = '.';
    }
    DecimalFormat df = new DecimalFormat();
    DecimalFormatSymbols symbols = new DecimalFormatSymbols();
    symbols.setDecimalSeparator(decChar);
    symbols.setGroupingSeparator(grpChar);
    df.setDecimalFormatSymbols(symbols);
    
    Number parsedValue = 0;
    try {
        parsedValue = df.parse(localValue);
    }
    catch (ParseException pe) {
        pe.printStackTrace();
    }
    
    /**
     * Round off and format to localize
     */
    double roundedValue = Math.round(parsedValue.doubleValue());
    String localeAwareValue = df.format(roundedValue);
    
    
    // TODO - use Locale with nf instead of above method
    // currently facing issue with incorrect parse for non default locale
    /*
       NumberFormat nf = NumberFormat.getInstance(new Locale(locale));
       Number num = nf.parse(localValue);
    */
    

不用说我对解决方案不满意,这更像是一种解决方法,直到我得到主要问题的解决方案 - NumberFormat 对非默认语言环境的错误解析。因此,仍然欢迎任何提示、建议和解决方案。

【讨论】:

    【解决方案2】:

    这里有两个问题,

    1) 您创建的语言环境不正确。使用Locale.CANADA_FRENCH

    2) 给定数字在默认和加拿大语言环境中均无效。根据ICU,在fr_CA中,分组分隔符为空,小数分隔符为,

    因此,在您的示例中,它使用默认语言环境,它将. 视为小数分隔符并在, 处保释,而在正确的语言环境中,它将在. 处保释并简单地返回@987654328 @。

    fr_CA 中写入这个数字的正确方式是2302,52

    所以,真的,Java 是正确的,但你对这个数字格式的假设是不正确的。

    【讨论】:

      猜你喜欢
      • 2019-12-07
      • 2011-10-29
      • 1970-01-01
      • 1970-01-01
      • 2020-04-05
      • 2014-03-31
      • 2013-03-26
      • 1970-01-01
      相关资源
      最近更新 更多