diff --git a/CHANGELOG.md b/CHANGELOG.md
index d89819707..67d9a174b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,14 +3,22 @@
-------------------------------------------------------------------------------------------------------------
-# 5.5.5 (2020-12-17)
+# 5.5.5 (2020-12-24)
### 新特性
* 【core 】 URLUtil.normalize新增重载(pr#233@Gitee)
* 【core 】 PathUtil增加isSub和toAbsNormal方法
+* 【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/lang/tree/TreeUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/tree/TreeUtil.java
index 8a4d9e0e4..1babcc1fb 100644
--- a/hutool-core/src/main/java/cn/hutool/core/lang/tree/TreeUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/tree/TreeUtil.java
@@ -74,7 +74,7 @@ public class TreeUtil {
List
* 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
diff --git a/hutool-db/src/main/java/cn/hutool/db/handler/HandleHelper.java b/hutool-db/src/main/java/cn/hutool/db/handler/HandleHelper.java
index 5fb86e344..0a3ce2a95 100644
--- a/hutool-db/src/main/java/cn/hutool/db/handler/HandleHelper.java
+++ b/hutool-db/src/main/java/cn/hutool/db/handler/HandleHelper.java
@@ -154,7 +154,12 @@ public class HandleHelper {
row.put(meta.getColumnLabel(i), getColumnValue(rs, i, type, null));
}
if (withMetaInfo) {
- row.setTableName(meta.getTableName(1));
+ try {
+ row.setTableName(meta.getTableName(1));
+ } catch (SQLException ignore){
+ //issue#I2AGLU@Gitee
+ // Hive等NoSQL中无表的概念,此处报错,跳过。
+ }
row.setFieldNames(row.keySet());
}
return row;
diff --git a/hutool-db/src/main/java/cn/hutool/db/nosql/redis/RedisDS.java b/hutool-db/src/main/java/cn/hutool/db/nosql/redis/RedisDS.java
index d32603fd1..325be3487 100644
--- a/hutool-db/src/main/java/cn/hutool/db/nosql/redis/RedisDS.java
+++ b/hutool-db/src/main/java/cn/hutool/db/nosql/redis/RedisDS.java
@@ -9,6 +9,7 @@ import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Protocol;
import java.io.Closeable;
+import java.io.Serializable;
/**
* Jedis数据源
@@ -16,7 +17,8 @@ import java.io.Closeable;
* @author looly
* @since 3.2.3
*/
-public class RedisDS implements Closeable{
+public class RedisDS implements Closeable, Serializable {
+ private static final long serialVersionUID = -5605411972456177456L;
/** 默认配置文件 */
public final static String REDIS_CONFIG_PATH = "config/redis.setting";
@@ -29,7 +31,7 @@ public class RedisDS implements Closeable{
/**
* 创建RedisDS,使用默认配置文件,默认分组
*
- * @return {@link RedisDS}
+ * @return RedisDS
*/
public static RedisDS create() {
return new RedisDS();
@@ -39,7 +41,7 @@ public class RedisDS implements Closeable{
* 创建RedisDS,使用默认配置文件
*
* @param group 配置文件中配置分组
- * @return {@link RedisDS}
+ * @return RedisDS
*/
public static RedisDS create(String group) {
return new RedisDS(group);
@@ -50,7 +52,7 @@ public class RedisDS implements Closeable{
*
* @param setting 配置文件
* @param group 配置文件中配置分组
- * @return {@link RedisDS}
+ * @return RedisDS
*/
public static RedisDS create(Setting setting, String group) {
return new RedisDS(setting, group);
diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml
index c760a920d..e1f6d2b76 100644
--- a/hutool-extra/pom.xml
+++ b/hutool-extra/pom.xml
@@ -19,7 +19,7 @@
2.2
- 3.2.4.RELEASE
+ 3.3.1.RELEASE
1.3.0
2.3.30
4.9.03
diff --git a/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java b/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java
index 66a37197f..aabf78763 100644
--- a/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java
+++ b/hutool-http/src/test/java/cn/hutool/http/HttpRequestTest.java
@@ -9,8 +9,6 @@ import cn.hutool.json.JSONUtil;
import org.junit.Ignore;
import org.junit.Test;
-import java.net.Authenticator;
-import java.net.PasswordAuthentication;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -142,26 +140,4 @@ public class HttpRequestTest {
HttpResponse execute = get.execute();
Console.log(execute.body());
}
-
- @Test
- public void getByProxy(){
- System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
-
- // 用户名密码, 若已添加白名单则不需要添加
- final String ProxyUser = "t10757311156848";
- final String ProxyPass = "ikm5uu44";
-
- Authenticator.setDefault(new Authenticator() {
- public PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication(ProxyUser, ProxyPass.toCharArray());
- }
- });
-
- final HttpResponse res = HttpRequest.get("https://httpbin.org/get")
- .basicAuth(ProxyUser, ProxyPass)
- .setHttpProxy("tps193.kdlapi.com", 15818).execute();
-
- Console.log(res.body());
- }
-
}
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelDateUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelDateUtil.java
new file mode 100644
index 000000000..fb6349036
--- /dev/null
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelDateUtil.java
@@ -0,0 +1,70 @@
+package cn.hutool.poi.excel;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.StrUtil;
+import org.apache.poi.ss.formula.ConditionalFormattingEvaluator;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.ExcelNumberFormat;
+
+/**
+ * Excel中日期判断、读取、处理等补充工具类
+ *
+ * @author looly
+ * @since 5.5.5
+ */
+public class ExcelDateUtil {
+
+ /**
+ * 某些特殊的自定义日期格式
+ */
+ private static final int[] customFormats = new int[]{28, 30, 31, 32, 33, 55, 56, 57, 58};
+
+ public static boolean isDateFormat(Cell cell){
+ return isDateFormat(cell, null);
+ }
+
+ /**
+ * 判断是否日期格式
+ * @param cell 单元格
+ * @param cfEvaluator {@link ConditionalFormattingEvaluator}
+ * @return 是否日期格式
+ */
+ public static boolean isDateFormat(Cell cell, ConditionalFormattingEvaluator cfEvaluator){
+ final ExcelNumberFormat nf = ExcelNumberFormat.from(cell, cfEvaluator);
+ return isDateFormat(nf);
+ }
+
+ /**
+ * 判断是否日期格式
+ * @param numFmt {@link ExcelNumberFormat}
+ * @return 是否日期格式
+ */
+ public static boolean isDateFormat(ExcelNumberFormat numFmt) {
+ return isDateFormat(numFmt.getIdx(), numFmt.getFormat());
+ }
+
+ /**
+ * 判断日期格式
+ *
+ * @param formatIndex 格式索引,一般用于内建格式
+ * @param formatString 格式字符串
+ * @return 是否为日期格式
+ * @since 5.5.3
+ */
+ public static boolean isDateFormat(int formatIndex, String formatString) {
+ // issue#1283@Github
+ if (ArrayUtil.contains(customFormats, formatIndex)) {
+ return true;
+ }
+
+ // 自定义格式判断
+ if (StrUtil.isNotEmpty(formatString) &&
+ StrUtil.containsAny(formatString, "周", "星期", "aa")) {
+ // aa -> 周一
+ // aaa -> 星期一
+ return true;
+ }
+
+ return org.apache.poi.ss.usermodel.DateUtil.isADateFormat(formatIndex, formatString);
+ }
+}
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java
index 2b71e08aa..390e297f8 100644
--- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java
@@ -3,6 +3,7 @@ package cn.hutool.poi.excel.cell;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
+import cn.hutool.poi.excel.ExcelDateUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.StyleSet;
import cn.hutool.poi.excel.editors.TrimEditor;
@@ -102,7 +103,7 @@ public class CellUtil {
if (null == cell) {
return null;
}
- if(cell instanceof NullCell){
+ if (cell instanceof NullCell) {
return null == cellEditor ? null : cellEditor.edit(cell, null);
}
if (null == cellType) {
@@ -111,7 +112,7 @@ public class CellUtil {
// 尝试获取合并单元格,如果是合并单元格,则重新获取单元格类型
final Cell mergedCell = getMergedRegionCell(cell);
- if(mergedCell != cell){
+ if (mergedCell != cell) {
cell = mergedCell;
cellType = cell.getCellTypeEnum();
}
@@ -235,7 +236,7 @@ public class CellUtil {
}
/**
- *获取单元格,如果单元格不存在,返回{@link NullCell}
+ * 获取单元格,如果单元格不存在,返回{@link NullCell}
*
* @param row Excel表的行
* @param cellIndex 列号
@@ -377,7 +378,7 @@ public class CellUtil {
* @since 5.1.5
*/
public static Cell getMergedRegionCell(Cell cell) {
- if(null == cell){
+ if (null == cell) {
return null;
}
return ObjectUtil.defaultIfNull(
@@ -404,10 +405,10 @@ public class CellUtil {
/**
* 为特定单元格添加批注
*
- * @param cell 单元格
- * @param commentText 批注内容
+ * @param cell 单元格
+ * @param commentText 批注内容
* @param commentAuthor 作者
- * @param anchor 批注的位置、大小等信息,null表示使用默认
+ * @param anchor 批注的位置、大小等信息,null表示使用默认
* @since 5.4.8
*/
public static void setComment(Cell cell, String commentText, String commentAuthor, ClientAnchor anchor) {
@@ -431,16 +432,16 @@ public class CellUtil {
// -------------------------------------------------------------------------------------------------------------- Private method start
/**
- * 获取合并单元格,非合并单元格返回null
+ * 获取合并单元格,非合并单元格返回{@code null}
* 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格
*
* @param sheet {@link Sheet}
* @param x 列号,从0开始,可以是合并单元格范围中的任意一列
* @param y 行号,从0开始,可以是合并单元格范围中的任意一行
- * @return 合并单元格,如果非合并单元格,返回null
+ * @return 合并单元格,如果非合并单元格,返回{@code null}
* @since 5.4.5
*/
- private static Cell getCellIfMergedRegion(Sheet sheet, int x, int y){
+ private static Cell getCellIfMergedRegion(Sheet sheet, int x, int y) {
final int sheetMergeCount = sheet.getNumMergedRegions();
CellRangeAddress ca;
for (int i = 0; i < sheetMergeCount; i++) {
@@ -463,9 +464,8 @@ public class CellUtil {
final CellStyle style = cell.getCellStyle();
if (null != style) {
- final short formatIndex = style.getDataFormat();
// 判断是否为日期
- if (isDateType(cell, formatIndex)) {
+ if (ExcelDateUtil.isDateFormat(cell)) {
return DateUtil.date(cell.getDateCellValue());// 使用Hutool的DateTime包装
}
@@ -483,32 +483,5 @@ public class CellUtil {
// 某些Excel单元格值为double计算结果,可能导致精度问题,通过转换解决精度问题。
return Double.parseDouble(NumberToTextConverter.toText(value));
}
-
- /**
- * 是否为日期格式
- * 判断方式:
- *
- *
- * 1、指定序号
- * 2、org.apache.poi.ss.usermodel.DateUtil.isADateFormat方法判定
- *
- *
- * @param cell 单元格
- * @param formatIndex 格式序号
- * @return 是否为日期格式
- */
- private static boolean isDateType(Cell cell, int formatIndex) {
- // yyyy-MM-dd----- 14
- // yyyy年m月d日---- 31
- // yyyy年m月------- 57
- // m月d日 ---------- 58
- // HH:mm----------- 20
- // h时mm分 -------- 32
- if (formatIndex == 14 || formatIndex == 31 || formatIndex == 57 || formatIndex == 58 || formatIndex == 20 || formatIndex == 32) {
- return true;
- }
-
- return org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell);
- }
// -------------------------------------------------------------------------------------------------------------- Private method end
}
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java
index 5f50f9c12..e92095674 100644
--- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java
@@ -6,6 +6,7 @@ import cn.hutool.core.exceptions.DependencyException;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.StrUtil;
+import cn.hutool.poi.excel.ExcelDateUtil;
import cn.hutool.poi.excel.sax.handler.RowHandler;
import cn.hutool.poi.exceptions.POIException;
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
@@ -209,16 +210,10 @@ public class ExcelSaxUtil {
* @param formatString 格式字符串
* @return 是否为日期格式
* @since 5.5.3
+ * @see ExcelDateUtil#isDateFormat(int, String)
*/
public static boolean isDateFormat(int formatIndex, String formatString) {
- // https://blog.csdn.net/u014342130/article/details/50619503
- // issue#1283@Github
- if (formatIndex == 28 || formatIndex == 31) {
- // 28 -> m月d日
- // 31 -> yyyy年m月d日
- return true;
- }
- return org.apache.poi.ss.usermodel.DateUtil.isADateFormat(formatIndex, formatString);
+ return ExcelDateUtil.isDateFormat(formatIndex, formatString);
}
/**
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/style/StyleUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/style/StyleUtil.java
index 880764166..ab9fc3a57 100644
--- a/hutool-poi/src/main/java/cn/hutool/poi/excel/style/StyleUtil.java
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/style/StyleUtil.java
@@ -1,8 +1,10 @@
package cn.hutool.poi.excel.style;
+import cn.hutool.core.util.StrUtil;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
@@ -10,20 +12,18 @@ import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
-import cn.hutool.core.util.StrUtil;
-
/**
* Excel样式工具类
- *
+ *
* @author looly
* @since 4.0.0
*/
public class StyleUtil {
-
+
/**
* 克隆新的{@link CellStyle}
- *
- * @param cell 单元格
+ *
+ * @param cell 单元格
* @param cellStyle 被复制的样式
* @return {@link CellStyle}
*/
@@ -33,8 +33,8 @@ public class StyleUtil {
/**
* 克隆新的{@link CellStyle}
- *
- * @param workbook 工作簿
+ *
+ * @param workbook 工作簿
* @param cellStyle 被复制的样式
* @return {@link CellStyle}
*/
@@ -43,13 +43,13 @@ public class StyleUtil {
newCellStyle.cloneStyleFrom(cellStyle);
return newCellStyle;
}
-
+
/**
* 设置cell文本对齐样式
- *
+ *
* @param cellStyle {@link CellStyle}
- * @param halign 横向位置
- * @param valign 纵向位置
+ * @param halign 横向位置
+ * @param valign 纵向位置
* @return {@link CellStyle}
*/
public static CellStyle setAlign(CellStyle cellStyle, HorizontalAlignment halign, VerticalAlignment valign) {
@@ -60,8 +60,8 @@ public class StyleUtil {
/**
* 设置cell的四个边框粗细和颜色
- *
- * @param cellStyle {@link CellStyle}
+ *
+ * @param cellStyle {@link CellStyle}
* @param borderSize 边框粗细{@link BorderStyle}枚举
* @param colorIndex 颜色的short值
* @return {@link CellStyle}
@@ -81,12 +81,12 @@ public class StyleUtil {
return cellStyle;
}
-
+
/**
* 给cell设置颜色
- *
- * @param cellStyle {@link CellStyle}
- * @param color 背景颜色
+ *
+ * @param cellStyle {@link CellStyle}
+ * @param color 背景颜色
* @param fillPattern 填充方式 {@link FillPatternType}枚举
* @return {@link CellStyle}
*/
@@ -96,9 +96,9 @@ public class StyleUtil {
/**
* 给cell设置颜色
- *
- * @param cellStyle {@link CellStyle}
- * @param color 背景颜色
+ *
+ * @param cellStyle {@link CellStyle}
+ * @param color 背景颜色
* @param fillPattern 填充方式 {@link FillPatternType}枚举
* @return {@link CellStyle}
*/
@@ -107,12 +107,12 @@ public class StyleUtil {
cellStyle.setFillPattern(fillPattern);
return cellStyle;
}
-
+
/**
* 创建字体
- *
+ *
* @param workbook {@link Workbook}
- * @param color 字体颜色
+ * @param color 字体颜色
* @param fontSize 字体大小
* @param fontName 字体名称,可以为null使用默认字体
* @return {@link Font}
@@ -121,24 +121,24 @@ public class StyleUtil {
final Font font = workbook.createFont();
return setFontStyle(font, color, fontSize, fontName);
}
-
+
/**
* 设置字体样式
- *
- * @param font 字体{@link Font}
- * @param color 字体颜色
+ *
+ * @param font 字体{@link Font}
+ * @param color 字体颜色
* @param fontSize 字体大小
* @param fontName 字体名称,可以为null使用默认字体
* @return {@link Font}
*/
public static Font setFontStyle(Font font, short color, short fontSize, String fontName) {
- if(color > 0) {
+ if (color > 0) {
font.setColor(color);
}
- if(fontSize > 0) {
+ if (fontSize > 0) {
font.setFontHeightInPoints(fontSize);
}
- if(StrUtil.isNotBlank(fontName)) {
+ if (StrUtil.isNotBlank(fontName)) {
font.setFontName(fontName);
}
return font;
@@ -153,7 +153,7 @@ public class StyleUtil {
* @since 5.4.0
*/
public static CellStyle createCellStyle(Workbook workbook) {
- if(null == workbook){
+ if (null == workbook) {
return null;
}
return workbook.createCellStyle();
@@ -161,12 +161,12 @@ public class StyleUtil {
/**
* 创建默认普通单元格样式
- *
+ *
*
* 1. 文字上下左右居中
* 2. 细边框,黑色
*
- *
+ *
* @param workbook {@link Workbook} 工作簿
* @return {@link CellStyle}
*/
@@ -179,7 +179,7 @@ public class StyleUtil {
/**
* 创建默认头部样式
- *
+ *
* @param workbook {@link Workbook} 工作簿
* @return {@link CellStyle}
*/
@@ -190,15 +190,28 @@ public class StyleUtil {
setColor(cellStyle, IndexedColors.GREY_25_PERCENT, FillPatternType.SOLID_FOREGROUND);
return cellStyle;
}
-
+
/**
- * 给定样式是否为null(无样式)或默认样式,默认样式为workbook.getCellStyleAt(0)
+ * 给定样式是否为null(无样式)或默认样式,默认样式为{@code workbook.getCellStyleAt(0)}
+ *
* @param workbook 工作簿
- * @param style 被检查的样式
+ * @param style 被检查的样式
* @return 是否为null(无样式)或默认样式
* @since 4.6.3
*/
public static boolean isNullOrDefaultStyle(Workbook workbook, CellStyle style) {
return (null == style) || style.equals(workbook.getCellStyleAt(0));
}
+
+ /**
+ * 创建数据格式并获取格式
+ *
+ * @param format 数据格式
+ * @return 数据格式
+ * @since 5.5.5
+ */
+ public Short getFormat(Workbook workbook, String format) {
+ final DataFormat dataFormat = workbook.createDataFormat();
+ return dataFormat.getFormat(format);
+ }
}
diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java
index 4d5ef39f8..785eb2899 100644
--- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java
+++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java
@@ -164,6 +164,14 @@ public class ExcelSaxReadTest {
Assert.assertEquals("2012-12-21 00:00:00", rows.get(4));
}
+ @Test
+ @Ignore
+ public void dateReadXlsxTest2() {
+ ExcelUtil.readBySax("d:/test/custom_date_format2.xlsx", 0,
+ (i, i1, list) -> Console.log(list)
+ );
+ }
+
@Test
@Ignore
public void readBlankTest() {