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.Bytejava.lang.Shortjava.lang.Integerjava.util.concurrent.atomic.AtomicIntegerjava.lang.Longjava.util.concurrent.atomic.AtomicLongjava.lang.Floatjava.lang.Doublejava.math.BigDecimaljava.math.BigIntegernull
+ * @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