diff --git a/CHANGELOG.md b/CHANGELOG.md
index b6dfb104c..67d9a174b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
-# 5.5.5 (2020-12-23)
+# 5.5.5 (2020-12-24)
### 新特性
* 【core 】 URLUtil.normalize新增重载(pr#233@Gitee)
@@ -11,11 +11,14 @@
* 【db 】 RedisDS实现序列化接口(pr#1323@Github)
* 【poi 】 StyleUtil增加getFormat方法(pr#235@Gitee)
* 【poi 】 增加ExcelDateUtil更多日期格式支持(issue#1316@Github)
+* 【core 】 NumberUtil.toBigDecimal支持各类数字格式,如1,234.56等(issue#1334@Github)
+* 【core 】 NumberUtil增加parseXXX方法(issue#1334@Github)
### Bug修复
* 【core 】 FileUtil.isSub相对路径判断问题(pr#1315@Github)
* 【core 】 TreeUtil增加空判定(issue#I2ACCW@Gitee)
* 【db 】 解决Hive获取表名失败问题(issue#I2AGLU@Gitee)
+* 【core 】 修复DateUtil.parse未使用严格模式导致结果不正常的问题(issue#1332@Github)
-------------------------------------------------------------------------------------------------------------
# 5.5.4 (2020-12-16)
diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java
index 7d41bbb4c..e1b2f0c03 100644
--- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java
+++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java
@@ -21,16 +21,16 @@ import java.util.function.Function;
* 数字转换器
* 支持类型为:
*
java.lang.Byte
java.lang.Short
java.lang.Integer
java.util.concurrent.atomic.AtomicInteger
java.lang.Long
java.util.concurrent.atomic.AtomicLong
java.lang.Float
java.lang.Double
java.math.BigDecimal
java.math.BigInteger
null
+ * @throws IllegalArgumentException pattern 无效或{@code null}
*/
public F getInstance(final String pattern, TimeZone timeZone, Locale locale) {
Assert.notBlank(pattern, "pattern must not be blank") ;
@@ -74,7 +74,7 @@ abstract class FormatCachenull
+ * @throws IllegalArgumentException pattern 无效或{@code null}
*/
abstract protected F createInstance(String pattern, TimeZone timeZone, Locale locale);
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
index aa8896bf1..11f6e94e9 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
@@ -2044,6 +2044,11 @@ public class NumberUtil {
* @since 4.0.9
*/
public static BigDecimal toBigDecimal(String number) {
+ try{
+ number = parseNumber(number).toString();
+ } catch (Exception ignore){
+ // 忽略解析错误
+ }
return StrUtil.isBlank(number) ? BigDecimal.ZERO : new BigDecimal(number);
}
@@ -2287,7 +2292,7 @@ public class NumberUtil {
*
* * 1、0x开头的视为16进制数字 - * 2、0开头的视为8进制数字 + * 2、0开头的忽略开头的0 * 3、其它情况按照10进制转换 * 4、空串返回0 * 5、.123形式返回0(按照小于0的小数对待) @@ -2304,18 +2309,16 @@ public class NumberUtil { return 0; } - // 对于带小数转换为整数采取去掉小数的策略 - number = StrUtil.subBefore(number, CharUtil.DOT, false); - if (StrUtil.isEmpty(number)) { - return 0; - } - if (StrUtil.startWithIgnoreCase(number, "0x")) { // 0x04表示16进制数 return Integer.parseInt(number.substring(2), 16); } - return Integer.parseInt(removeNumberFlag(number)); + try{ + return Integer.parseInt(number); + } catch (NumberFormatException e){ + return parseNumber(number).intValue(); + } } /** @@ -2323,9 +2326,11 @@ public class NumberUtil { * ** 1、0x开头的视为16进制数字 - * 2、0开头的视为8进制数字 + * 2、0开头的忽略开头的0 * 3、空串返回0 * 4、其它情况按照10进制转换 + * 5、.123形式返回0(按照小于0的小数对待) + * 6、123.56截取小数点之前的数字,忽略小数部分 ** * @param number 数字,支持0x开头、0开头和普通十进制 @@ -2334,13 +2339,7 @@ public class NumberUtil { */ public static long parseLong(String number) { if (StrUtil.isBlank(number)) { - return 0; - } - - // 对于带小数转换为整数采取去掉小数的策略 - number = StrUtil.subBefore(number, CharUtil.DOT, false); - if (StrUtil.isEmpty(number)) { - return 0; + return 0L; } if (number.startsWith("0x")) { @@ -2348,7 +2347,63 @@ public class NumberUtil { return Long.parseLong(number.substring(2), 16); } - return Long.parseLong(removeNumberFlag(number)); + try{ + return Long.parseLong(number); + } catch (NumberFormatException e){ + return parseNumber(number).longValue(); + } + } + + /** + * 解析转换数字字符串为long型数字,规则如下: + * + *+ * 1、0开头的忽略开头的0 + * 2、空串返回0 + * 3、其它情况按照10进制转换 + * 4、.123形式返回0.123(按照小于0的小数对待) + *+ * + * @param number 数字,支持0x开头、0开头和普通十进制 + * @return long + * @since 5.5.5 + */ + public static float parseFloat(String number) { + if (StrUtil.isBlank(number)) { + return 0f; + } + + try{ + return Float.parseFloat(number); + } catch (NumberFormatException e){ + return parseNumber(number).floatValue(); + } + } + + /** + * 解析转换数字字符串为long型数字,规则如下: + * + *+ * 1、0开头的忽略开头的0 + * 2、空串返回0 + * 3、其它情况按照10进制转换 + * 4、.123形式返回0.123(按照小于0的小数对待) + *+ * + * @param number 数字,支持0x开头、0开头和普通十进制 + * @return long + * @since 5.5.5 + */ + public static double parseDouble(String number) { + if (StrUtil.isBlank(number)) { + return 0D; + } + + try{ + return Double.parseDouble(number); + } catch (NumberFormatException e){ + return parseNumber(number).doubleValue(); + } } /** @@ -2357,13 +2412,15 @@ public class NumberUtil { * @param numberStr Number字符串 * @return Number对象 * @since 4.1.15 + * @throws NumberFormatException 包装了{@link ParseException},当给定的数字字符串无法解析时抛出 */ - public static Number parseNumber(String numberStr) { - numberStr = removeNumberFlag(numberStr); + public static Number parseNumber(String numberStr) throws NumberFormatException{ try { return NumberFormat.getInstance().parse(numberStr); } catch (ParseException e) { - throw new UtilException(e); + final NumberFormatException nfe = new NumberFormatException(e.getMessage()); + nfe.initCause(e); + throw nfe; } } @@ -2509,25 +2566,5 @@ public class NumberUtil { return selectNum * mathNode(selectNum - 1); } } - - /** - * 去掉数字尾部的数字标识,例如12D,44.0F,22L中的最后一个字母 - * - * @param number 数字字符串 - * @return 去掉标识的字符串 - */ - private static String removeNumberFlag(String number) { - // 去掉千位分隔符 - if (StrUtil.contains(number, CharUtil.COMMA)) { - number = StrUtil.removeAll(number, CharUtil.COMMA); - } - // 去掉类型标识的结尾 - final int lastPos = number.length() - 1; - final char lastCharUpper = Character.toUpperCase(number.charAt(lastPos)); - if ('D' == lastCharUpper || 'L' == lastCharUpper || 'F' == lastCharUpper) { - number = StrUtil.subPre(number, lastPos); - } - return number; - } // ------------------------------------------------------------------------------------------- Private method end } diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/NumberConverterTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/NumberConverterTest.java new file mode 100644 index 000000000..28632f2de --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/convert/NumberConverterTest.java @@ -0,0 +1,22 @@ +package cn.hutool.core.convert; + +import cn.hutool.core.convert.impl.NumberConverter; +import org.junit.Assert; +import org.junit.Test; + +public class NumberConverterTest { + + @Test + public void toDoubleTest(){ + final NumberConverter numberConverter = new NumberConverter(Double.class); + final Number convert = numberConverter.convert("1,234.55", null); + Assert.assertEquals(1234.55D, convert); + } + + @Test + public void toIntegerTest(){ + final NumberConverter numberConverter = new NumberConverter(Integer.class); + final Number convert = numberConverter.convert("1,234.55", null); + Assert.assertEquals(1234, convert); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java index 0500d3827..f709f644d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -831,4 +831,11 @@ public class DateUtilTest { final DateTime parse = DateUtil.parse(dt); Assert.assertEquals("2020-06-03 12:32:12", parse.toString()); } + + @Test(expected = DateException.class) + public void parseNotFitTest(){ + //https://github.com/looly/hutool/issues/1332 + // 在日期格式不匹配的时候,测试是否正常报错 + final DateTime parse = DateUtil.parse("2020-12-23", DatePattern.PURE_DATE_PATTERN); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java index cbd632a0f..a6546efcd 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java @@ -189,6 +189,12 @@ public class NumberUtilTest { BigDecimal bigDecimal = NumberUtil.toBigDecimal(a); Assert.assertEquals("3.14", bigDecimal.toString()); + + bigDecimal = NumberUtil.toBigDecimal("1,234.55"); + Assert.assertEquals("1234.55", bigDecimal.toString()); + + bigDecimal = NumberUtil.toBigDecimal("1,234.56D"); + Assert.assertEquals("1234.56", bigDecimal.toString()); } @Test @@ -205,21 +211,33 @@ public class NumberUtilTest { @Test public void parseIntTest() { - int v1 = NumberUtil.parseInt("0xFF"); - Assert.assertEquals(255, v1); - int v2 = NumberUtil.parseInt("010"); - Assert.assertEquals(10, v2); - int v3 = NumberUtil.parseInt("10"); - Assert.assertEquals(10, v3); - int v4 = NumberUtil.parseInt(" "); - Assert.assertEquals(0, v4); - int v5 = NumberUtil.parseInt("10F"); - Assert.assertEquals(10, v5); - int v6 = NumberUtil.parseInt("22.4D"); - Assert.assertEquals(22, v6); + int number = NumberUtil.parseInt("0xFF"); + Assert.assertEquals(255, number); - int v7 = NumberUtil.parseInt("0"); - Assert.assertEquals(0, v7); + // 0开头 + number = NumberUtil.parseInt("010"); + Assert.assertEquals(10, number); + + number = NumberUtil.parseInt("10"); + Assert.assertEquals(10, number); + + number = NumberUtil.parseInt(" "); + Assert.assertEquals(0, number); + + number = NumberUtil.parseInt("10F"); + Assert.assertEquals(10, number); + + number = NumberUtil.parseInt("22.4D"); + Assert.assertEquals(22, number); + + number = NumberUtil.parseInt("22.6D"); + Assert.assertEquals(22, number); + + number = NumberUtil.parseInt("0"); + Assert.assertEquals(0, number); + + number = NumberUtil.parseInt(".123"); + Assert.assertEquals(0, number); } @Test @@ -236,22 +254,40 @@ public class NumberUtilTest { // 千位分隔符去掉 int v1 = NumberUtil.parseNumber("1,482.00").intValue(); Assert.assertEquals(1482, v1); + + Number v2 = NumberUtil.parseNumber("1,482.00D"); + Assert.assertEquals(1482L, v2); } @Test public void parseLongTest() { - long v1 = NumberUtil.parseLong("0xFF"); - Assert.assertEquals(255L, v1); - long v2 = NumberUtil.parseLong("010"); - Assert.assertEquals(10L, v2); - long v3 = NumberUtil.parseLong("10"); - Assert.assertEquals(10L, v3); - long v4 = NumberUtil.parseLong(" "); - Assert.assertEquals(0L, v4); - long v5 = NumberUtil.parseLong("10F"); - Assert.assertEquals(10L, v5); - long v6 = NumberUtil.parseLong("22.4D"); - Assert.assertEquals(22L, v6); + long number = NumberUtil.parseLong("0xFF"); + Assert.assertEquals(255, number); + + // 0开头 + number = NumberUtil.parseLong("010"); + Assert.assertEquals(10, number); + + number = NumberUtil.parseLong("10"); + Assert.assertEquals(10, number); + + number = NumberUtil.parseLong(" "); + Assert.assertEquals(0, number); + + number = NumberUtil.parseLong("10F"); + Assert.assertEquals(10, number); + + number = NumberUtil.parseLong("22.4D"); + Assert.assertEquals(22, number); + + number = NumberUtil.parseLong("22.6D"); + Assert.assertEquals(22, number); + + number = NumberUtil.parseLong("0"); + Assert.assertEquals(0, number); + + number = NumberUtil.parseLong(".123"); + Assert.assertEquals(0, number); } @Test