From fc6a0567b447a8c4f24c779bad32f670d70bb579 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 5 Jul 2022 21:47:47 +0800 Subject: [PATCH] add method --- CHANGELOG.md | 1 + .../java/cn/hutool/core/convert/Convert.java | 76 +------- .../core/convert/NumberChineseFormatter.java | 83 +++++++++ .../cn/hutool/core/text/CharSequenceUtil.java | 3 +- .../cn/hutool/core/convert/ConvertTest.java | 171 +++++++++--------- 5 files changed, 169 insertions(+), 165 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d597b6df..6decf0615 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * 【core 】 修复注解工具类getAnnotations的NPE问题,注解扫描器添新功能(pr#671@Gitee) * 【core 】 合成注解SyntheticAnnotation提取为接口,并为实现类添加注解选择器和属性处理器(pr#678@Gitee) * 【core 】 增加BeanValueProvider(issue#I5FBHV@Gitee) +* 【core 】 Convert工具类中,新增中文大写数字金额转换为数字工具方法(pr#674@Gitee) * ### 🐞Bug修复 diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java b/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java index 869104f97..a67682904 100755 --- a/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java @@ -1033,80 +1033,10 @@ public class Convert { * * @param chineseMoneyAmount 中文大写数字金额 * @return 返回结果以元为单位的BigDecimal类型数字 + * @since 5.8.5 */ - public static BigDecimal chineseMoneyAmount2Number(String chineseMoneyAmount){ - if(StrUtil.isBlank(chineseMoneyAmount)){ - return null; - } - - int yi = chineseMoneyAmount.indexOf("元"); - if(yi == -1){ - yi = chineseMoneyAmount.indexOf("圆"); - } - int ji = chineseMoneyAmount.indexOf("角"); - int fi = chineseMoneyAmount.indexOf("分"); - - /* - * 先找到单位为元的数字 - */ - String yStr = null; - if(yi > 0) { - yStr = chineseMoneyAmount.substring(0, yi); - } - - /* - * 再找到单位为角的数字 - */ - String jStr = null; - if(ji > 0){ - if(yi >= 0){ - //前面有元,角肯定要在元后面 - if(ji > yi){ - jStr = chineseMoneyAmount.substring(yi+1, ji); - } - }else{ - //没有元,只有角 - jStr = chineseMoneyAmount.substring(0, ji); - } - } - - /* - * 再找到单位为分的数字 - */ - String fStr = null; - if(fi > 0){ - if(ji >= 0){ - //有角,分肯定在角后面 - if(fi > ji){ - fStr = chineseMoneyAmount.substring(ji+1, fi); - } - }else if(yi > 0){ - //没有角,有元,那就坐元后面找 - if(fi > yi){ - fStr = chineseMoneyAmount.substring(yi+1, fi); - } - }else { - //没有元、角,只有分 - fStr = chineseMoneyAmount.substring(0, fi); - } - } - - //元、角、分 - int y = 0, j = 0, f = 0; - if(StrUtil.isNotBlank(yStr)) { - y = NumberChineseFormatter.chineseToNumber(yStr); - } - if(StrUtil.isNotBlank(jStr)){ - j = NumberChineseFormatter.chineseToNumber(jStr); - } - if(StrUtil.isNotBlank(fStr)){ - f = NumberChineseFormatter.chineseToNumber(fStr); - } - - BigDecimal amount = new BigDecimal(y); - amount = amount.add(BigDecimal.valueOf(j).divide(BigDecimal.TEN)); - amount = amount.add(BigDecimal.valueOf(f).divide(BigDecimal.valueOf(100))); - return amount; + public static BigDecimal chineseMoneyToNumber(String chineseMoneyAmount){ + return NumberChineseFormatter.chineseMoneyToNumber(chineseMoneyAmount); } // -------------------------------------------------------------------------- 数字转换 diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java b/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java index 6ec3f0e16..ebf0be822 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java @@ -5,6 +5,9 @@ import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; +import java.math.BigDecimal; +import java.math.RoundingMode; + /** * 数字转中文类
* 包括: @@ -232,6 +235,86 @@ public class NumberChineseFormatter { return String.valueOf(numberToChinese(c - '0', isUseTraditional)); } + /** + * 中文大写数字金额转换为数字,返回结果以元为单位的BigDecimal类型数字 + * + * 如: + * “陆万柒仟伍佰伍拾陆元叁角贰分”返回“67556.32” + * “叁角贰分”返回“0.32” + * + * @param chineseMoneyAmount 中文大写数字金额 + * @return 返回结果以元为单位的BigDecimal类型数字 + */ + @SuppressWarnings("ConstantConditions") + public static BigDecimal chineseMoneyToNumber(String chineseMoneyAmount){ + if(StrUtil.isBlank(chineseMoneyAmount)){ + return null; + } + + int yi = chineseMoneyAmount.indexOf("元"); + if(yi == -1){ + yi = chineseMoneyAmount.indexOf("圆"); + } + final int ji = chineseMoneyAmount.indexOf("角"); + final int fi = chineseMoneyAmount.indexOf("分"); + + // 先找到单位为元的数字 + String yStr = null; + if(yi > 0) { + yStr = chineseMoneyAmount.substring(0, yi); + } + + // 再找到单位为角的数字 + String jStr = null; + if(ji > 0){ + if(yi >= 0){ + //前面有元,角肯定要在元后面 + if(ji > yi){ + jStr = chineseMoneyAmount.substring(yi+1, ji); + } + }else{ + //没有元,只有角 + jStr = chineseMoneyAmount.substring(0, ji); + } + } + + // 再找到单位为分的数字 + String fStr = null; + if(fi > 0){ + if(ji >= 0){ + //有角,分肯定在角后面 + if(fi > ji){ + fStr = chineseMoneyAmount.substring(ji+1, fi); + } + }else if(yi > 0){ + //没有角,有元,那就坐元后面找 + if(fi > yi){ + fStr = chineseMoneyAmount.substring(yi+1, fi); + } + }else { + //没有元、角,只有分 + fStr = chineseMoneyAmount.substring(0, fi); + } + } + + //元、角、分 + int y = 0, j = 0, f = 0; + if(StrUtil.isNotBlank(yStr)) { + y = NumberChineseFormatter.chineseToNumber(yStr); + } + if(StrUtil.isNotBlank(jStr)){ + j = NumberChineseFormatter.chineseToNumber(jStr); + } + if(StrUtil.isNotBlank(fStr)){ + f = NumberChineseFormatter.chineseToNumber(fStr); + } + + BigDecimal amount = new BigDecimal(y); + amount = amount.add(BigDecimal.valueOf(j).divide(BigDecimal.TEN, RoundingMode.HALF_UP)); + amount = amount.add(BigDecimal.valueOf(f).divide(BigDecimal.valueOf(100), RoundingMode.HALF_UP)); + return amount; + } + /** * 阿拉伯数字整数部分转换成中文,只支持正数 * diff --git a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java index d38e31ee0..50c6b59c4 100755 --- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java @@ -86,8 +86,7 @@ public class CharSequenceUtil { * @see #isEmpty(CharSequence) */ public static boolean isBlank(CharSequence str) { - int length; - + final int length; if ((str == null) || ((length = str.length()) == 0)) { return true; } diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java index ce245edb7..43c7ea09b 100755 --- a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java @@ -5,10 +5,8 @@ import cn.hutool.core.date.DateException; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.TypeReference; import cn.hutool.core.map.MapUtil; -import cn.hutool.core.math.Money; import cn.hutool.core.util.ByteUtil; import cn.hutool.core.util.HexUtil; -import cn.hutool.core.util.StrUtil; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter; @@ -40,33 +38,33 @@ public class ConvertTest { @Test public void toObjectTest() { - Object result = Convert.convert(Object.class, "aaaa"); + final Object result = Convert.convert(Object.class, "aaaa"); Assert.assertEquals("aaaa", result); } @Test public void toStrTest() { - int a = 1; - long[] b = { 1, 2, 3, 4, 5 }; + final int a = 1; + final long[] b = { 1, 2, 3, 4, 5 }; Assert.assertEquals("[1, 2, 3, 4, 5]", Convert.convert(String.class, b)); - String aStr = Convert.toStr(a); + final String aStr = Convert.toStr(a); Assert.assertEquals("1", aStr); - String bStr = Convert.toStr(b); + final String bStr = Convert.toStr(b); Assert.assertEquals("[1, 2, 3, 4, 5]", Convert.toStr(bStr)); } @Test public void toStrTest2() { - String result = Convert.convert(String.class, "aaaa"); + final String result = Convert.convert(String.class, "aaaa"); Assert.assertEquals("aaaa", result); } @Test public void toStrTest3() { - char a = 'a'; - String result = Convert.convert(String.class, a); + final char a = 'a'; + final String result = Convert.convert(String.class, a); Assert.assertEquals("a", result); } @@ -80,160 +78,160 @@ public class ConvertTest { @Test public void toIntTest() { - String a = " 34232"; - Integer aInteger = Convert.toInt(a); + final String a = " 34232"; + final Integer aInteger = Convert.toInt(a); Assert.assertEquals(Integer.valueOf(34232), aInteger); - int aInt = ConverterRegistry.getInstance().convert(int.class, a); + final int aInt = ConverterRegistry.getInstance().convert(int.class, a); Assert.assertEquals(34232, aInt); // 带小数测试 - String b = " 34232.00"; - Integer bInteger = Convert.toInt(b); + final String b = " 34232.00"; + final Integer bInteger = Convert.toInt(b); Assert.assertEquals(Integer.valueOf(34232), bInteger); - int bInt = ConverterRegistry.getInstance().convert(int.class, b); + final int bInt = ConverterRegistry.getInstance().convert(int.class, b); Assert.assertEquals(34232, bInt); // boolean测试 - boolean c = true; - Integer cInteger = Convert.toInt(c); + final boolean c = true; + final Integer cInteger = Convert.toInt(c); Assert.assertEquals(Integer.valueOf(1), cInteger); - int cInt = ConverterRegistry.getInstance().convert(int.class, c); + final int cInt = ConverterRegistry.getInstance().convert(int.class, c); Assert.assertEquals(1, cInt); // boolean测试 - String d = "08"; - Integer dInteger = Convert.toInt(d); + final String d = "08"; + final Integer dInteger = Convert.toInt(d); Assert.assertEquals(Integer.valueOf(8), dInteger); - int dInt = ConverterRegistry.getInstance().convert(int.class, d); + final int dInt = ConverterRegistry.getInstance().convert(int.class, d); Assert.assertEquals(8, dInt); } @Test public void toIntTest2() { - ArrayList array = new ArrayList<>(); - Integer aInt = Convert.convertQuietly(Integer.class, array, -1); + final ArrayList array = new ArrayList<>(); + final Integer aInt = Convert.convertQuietly(Integer.class, array, -1); Assert.assertEquals(Integer.valueOf(-1), aInt); } @Test public void toLongTest() { - String a = " 342324545435435"; - Long aLong = Convert.toLong(a); + final String a = " 342324545435435"; + final Long aLong = Convert.toLong(a); Assert.assertEquals(Long.valueOf(342324545435435L), aLong); - long aLong2 = ConverterRegistry.getInstance().convert(long.class, a); + final long aLong2 = ConverterRegistry.getInstance().convert(long.class, a); Assert.assertEquals(342324545435435L, aLong2); // 带小数测试 - String b = " 342324545435435.245435435"; - Long bLong = Convert.toLong(b); + final String b = " 342324545435435.245435435"; + final Long bLong = Convert.toLong(b); Assert.assertEquals(Long.valueOf(342324545435435L), bLong); - long bLong2 = ConverterRegistry.getInstance().convert(long.class, b); + final long bLong2 = ConverterRegistry.getInstance().convert(long.class, b); Assert.assertEquals(342324545435435L, bLong2); // boolean测试 - boolean c = true; - Long cLong = Convert.toLong(c); + final boolean c = true; + final Long cLong = Convert.toLong(c); Assert.assertEquals(Long.valueOf(1), cLong); - long cLong2 = ConverterRegistry.getInstance().convert(long.class, c); + final long cLong2 = ConverterRegistry.getInstance().convert(long.class, c); Assert.assertEquals(1, cLong2); // boolean测试 - String d = "08"; - Long dLong = Convert.toLong(d); + final String d = "08"; + final Long dLong = Convert.toLong(d); Assert.assertEquals(Long.valueOf(8), dLong); - long dLong2 = ConverterRegistry.getInstance().convert(long.class, d); + final long dLong2 = ConverterRegistry.getInstance().convert(long.class, d); Assert.assertEquals(8, dLong2); } @Test public void toCharTest() { - String str = "aadfdsfs"; - Character c = Convert.toChar(str); + final String str = "aadfdsfs"; + final Character c = Convert.toChar(str); Assert.assertEquals(Character.valueOf('a'), c); // 转换失败 - Object str2 = ""; - Character c2 = Convert.toChar(str2); + final Object str2 = ""; + final Character c2 = Convert.toChar(str2); Assert.assertNull(c2); } @Test public void toNumberTest() { - Object a = "12.45"; - Number number = Convert.toNumber(a); + final Object a = "12.45"; + final Number number = Convert.toNumber(a); Assert.assertEquals(12.45D, number.doubleValue(), 2); } @Test public void emptyToNumberTest() { - Object a = ""; - Number number = Convert.toNumber(a); + final Object a = ""; + final Number number = Convert.toNumber(a); Assert.assertNull(number); } @Test public void intAndByteConvertTest() { // 测试 int 转 byte - int int0 = 234; - byte byte0 = Convert.intToByte(int0); + final int int0 = 234; + final byte byte0 = Convert.intToByte(int0); Assert.assertEquals(-22, byte0); - int int1 = Convert.byteToUnsignedInt(byte0); + final int int1 = Convert.byteToUnsignedInt(byte0); Assert.assertEquals(int0, int1); } @Test public void intAndBytesTest() { // 测试 int 转 byte 数组 - int int2 = 1417; - byte[] bytesInt = Convert.intToBytes(int2); + final int int2 = 1417; + final byte[] bytesInt = Convert.intToBytes(int2); // 测试 byte 数组转 int - int int3 = Convert.bytesToInt(bytesInt); + final int int3 = Convert.bytesToInt(bytesInt); Assert.assertEquals(int2, int3); } @Test public void longAndBytesTest() { // 测试 long 转 byte 数组 - long long1 = 2223; + final long long1 = 2223; - byte[] bytesLong = Convert.longToBytes(long1); - long long2 = Convert.bytesToLong(bytesLong); + final byte[] bytesLong = Convert.longToBytes(long1); + final long long2 = Convert.bytesToLong(bytesLong); Assert.assertEquals(long1, long2); } @Test public void shortAndBytesTest() { - short short1 = 122; - byte[] bytes = Convert.shortToBytes(short1); - short short2 = Convert.bytesToShort(bytes); + final short short1 = 122; + final byte[] bytes = Convert.shortToBytes(short1); + final short short2 = Convert.bytesToShort(bytes); Assert.assertEquals(short2, short1); } @Test public void toListTest() { - List list = Arrays.asList("1", "2"); - String str = Convert.toStr(list); - List list2 = Convert.toList(String.class, str); + final List list = Arrays.asList("1", "2"); + final String str = Convert.toStr(list); + final List list2 = Convert.toList(String.class, str); Assert.assertEquals("1", list2.get(0)); Assert.assertEquals("2", list2.get(1)); - List list3 = Convert.toList(Integer.class, str); + final List list3 = Convert.toList(Integer.class, str); Assert.assertEquals(1, list3.get(0).intValue()); Assert.assertEquals(2, list3.get(1).intValue()); } @Test public void toListTest2(){ - String str = "1,2"; - List list2 = Convert.toList(String.class, str); + final String str = "1,2"; + final List list2 = Convert.toList(String.class, str); Assert.assertEquals("1", list2.get(0)); Assert.assertEquals("2", list2.get(1)); - List list3 = Convert.toList(Integer.class, str); + final List list3 = Convert.toList(Integer.class, str); Assert.assertEquals(1, list3.get(0).intValue()); Assert.assertEquals(2, list3.get(1).intValue()); } @@ -259,14 +257,14 @@ public class ConvertTest { @Test public void toAtomicIntegerArrayTest(){ - String str = "1,2"; + final String str = "1,2"; final AtomicIntegerArray atomicIntegerArray = Convert.convert(AtomicIntegerArray.class, str); Assert.assertEquals("[1, 2]", atomicIntegerArray.toString()); } @Test public void toAtomicLongArrayTest(){ - String str = "1,2"; + final String str = "1,2"; final AtomicLongArray atomicLongArray = Convert.convert(AtomicLongArray.class, str); Assert.assertEquals("[1, 2]", atomicLongArray.toString()); } @@ -312,7 +310,7 @@ public class ConvertTest { private final int id; private final String name; - BuildingType(int id, String name){ + BuildingType(final int id, final String name){ this.id = id; this.name = name; } @@ -338,7 +336,7 @@ public class ConvertTest { @Test public void toHashtableTest(){ - Map map = MapUtil.newHashMap(); + final Map map = MapUtil.newHashMap(); map.put("a1", "v1"); map.put("a2", "v2"); map.put("a3", "v3"); @@ -353,7 +351,7 @@ public class ConvertTest { @Test public void toBigDecimalTest(){ // https://github.com/dromara/hutool/issues/1818 - String str = "33020000210909112800000124"; + final String str = "33020000210909112800000124"; final BigDecimal bigDecimal = Convert.toBigDecimal(str); Assert.assertEquals(str, bigDecimal.toPlainString()); } @@ -361,7 +359,7 @@ public class ConvertTest { @Test public void toFloatTest(){ // https://gitee.com/dromara/hutool/issues/I4M0E4 - String hex2 = "CD0CCB43"; + final String hex2 = "CD0CCB43"; final byte[] value = HexUtil.decodeHex(hex2); final float f = Convert.toFloat(value); Assert.assertEquals(406.1F, f, 2); @@ -369,22 +367,22 @@ public class ConvertTest { @Test public void floatToDoubleTest(){ - float a = 0.45f; - double b = Convert.toDouble(a); + final float a = 0.45f; + final double b = Convert.toDouble(a); Assert.assertEquals(a, b, 5); } @Test public void floatToDoubleAddrTest(){ - float a = 0.45f; + final float a = 0.45f; final DoubleAdder adder = Convert.convert(DoubleAdder.class, a); Assert.assertEquals(a, adder.doubleValue(), 5); } @Test public void doubleToFloatTest(){ - double a = 0.45f; - float b = Convert.toFloat(a); + final double a = 0.45f; + final float b = Convert.toFloat(a); Assert.assertEquals(a, b, 5); } @@ -408,22 +406,7 @@ public class ConvertTest { } @Test - public void testChineseMoneyAmount2Number(){ - String[] strs = new String[]{ - "陆万柒仟伍佰伍拾陆圆", - "陆万柒仟伍佰伍拾陆元", - "叁角", - "贰分", - "陆万柒仟伍佰伍拾陆元叁角", - "陆万柒仟伍佰伍拾陆元贰分", - "叁角贰分", - "陆万柒仟伍佰伍拾陆元叁角贰分", - }; - - for(String s: strs) { - System.out.println("s="+s+", n="+Convert.chineseMoneyAmount2Number(s)); - } - + public void testChineseMoneyToNumber(){ /* * s=陆万柒仟伍佰伍拾陆圆, n=67556 * s=陆万柒仟伍佰伍拾陆元, n=67556 @@ -434,6 +417,14 @@ public class ConvertTest { * s=叁角贰分, n=0.32 * s=陆万柒仟伍佰伍拾陆元叁角贰分, n=67556.32 */ + Assert.assertEquals(67556, Convert.chineseMoneyToNumber("陆万柒仟伍佰伍拾陆圆").longValue()); + Assert.assertEquals(67556, Convert.chineseMoneyToNumber("陆万柒仟伍佰伍拾陆元").longValue()); + Assert.assertEquals(0.3D, Convert.chineseMoneyToNumber("叁角").doubleValue(), 2); + Assert.assertEquals(0.02, Convert.chineseMoneyToNumber("贰分").doubleValue(), 2); + Assert.assertEquals(67556.3, Convert.chineseMoneyToNumber("陆万柒仟伍佰伍拾陆元叁角").doubleValue(), 2); + Assert.assertEquals(67556.02, Convert.chineseMoneyToNumber("陆万柒仟伍佰伍拾陆元贰分").doubleValue(), 2); + Assert.assertEquals(0.32, Convert.chineseMoneyToNumber("叁角贰分").doubleValue(), 2); + Assert.assertEquals(67556.32, Convert.chineseMoneyToNumber("陆万柒仟伍佰伍拾陆元叁角贰分").doubleValue(), 2); }