diff --git a/CHANGELOG.md b/CHANGELOG.md index 3816909cb..fdd19a094 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,14 +3,16 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.3 (2020-12-02) +# 5.5.3 (2020-12-05) ### 新特性 * 【core 】 IdcardUtil增加行政区划83(issue#1277@Github) * 【core 】 multipart中int改为long,解决大文件上传越界问题(issue#I27WZ3@Gitee) +* 【core 】 ListUtil.page增加检查(pr#224@Gitee) ### Bug修复 * 【cache 】 修复Cache中get重复misCount计数问题(issue#1281@Github) +* 【poi 】 修复sax读取自定义格式单元格无法识别日期类型的问题(issue#1283@Github) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java index 98bf9645d..b3bffe1c9 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java @@ -245,7 +245,7 @@ public class ListUtil { int resultSize = list.size(); // 每页条目数大于总数直接返回所有 if (resultSize <= pageSize) { - if (pageNo < (PageUtil.getFirstPageNo()+1)) { + if (pageNo < (PageUtil.getFirstPageNo() + 1)) { return Collections.unmodifiableList(list); } else { // 越界直接返回空 @@ -253,7 +253,7 @@ public class ListUtil { } } // 相乘可能会导致越界 临时用long - if (((long) (pageNo-PageUtil.getFirstPageNo()) * pageSize) > resultSize) { + if (((long) (pageNo - PageUtil.getFirstPageNo()) * pageSize) > resultSize) { // 越界直接返回空 return new ArrayList<>(0); } @@ -261,6 +261,9 @@ public class ListUtil { final int[] startEnd = PageUtil.transToStartEnd(pageNo, pageSize); if (startEnd[1] > resultSize) { startEnd[1] = resultSize; + if (startEnd[0] > startEnd[1]) { + return empty(); + } } return list.subList(startEnd[0], startEnd[1]); 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 96f17de45..a300dc01e 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 @@ -1516,7 +1516,7 @@ public class NumberUtil { */ public static int processMultiple(int selectNum, int minNum) { int result; - result = mathSubnode(selectNum, minNum) / mathNode(selectNum - minNum); + result = mathSubNode(selectNum, minNum) / mathNode(selectNum - minNum); return result; } @@ -2494,11 +2494,11 @@ public class NumberUtil { } // ------------------------------------------------------------------------------------------- Private method start - private static int mathSubnode(int selectNum, int minNum) { + private static int mathSubNode(int selectNum, int minNum) { if (selectNum == minNum) { return 1; } else { - return selectNum * mathSubnode(selectNum - 1, minNum); + return selectNum * mathSubNode(selectNum - 1, minNum); } } diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java index 3e240709d..101c53db8 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java @@ -187,4 +187,12 @@ public class ValidatorTest { zipCode = Validator.isZipCode("102629"); Assert.assertTrue(zipCode); } + + @Test + public void isBetweenTest() { + Assert.assertTrue(Validator.isBetween(0, 0, 1)); + Assert.assertTrue(Validator.isBetween(1L, 0L, 1L)); + Assert.assertTrue(Validator.isBetween(0.19f, 0.1f, 0.2f)); + Assert.assertTrue(Validator.isBetween(0.19, 0.1, 0.2)); + } } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java index 67d31b67f..dbd97dd04 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java @@ -268,7 +268,7 @@ public class Excel03SaxReader implements HSSFListener, ExcelSaxReader createSaxReader(boolean isXlsx, RowHandler rowHandler) { + return isXlsx + ? new Excel07SaxReader(rowHandler) + : new Excel03SaxReader(rowHandler); + } + /** * 根据数据类型获取数据 * @@ -175,14 +190,34 @@ public class ExcelSaxUtil { /** * 判断数字Record中是否为日期格式 - * @param cell 单元格记录 + * + * @param cell 单元格记录 * @param formatListener {@link FormatTrackingHSSFListener} * @return 是否为日期格式 * @since 5.4.8 */ - public static boolean isDateFormat(CellValueRecordInterface cell, FormatTrackingHSSFListener formatListener){ + public static boolean isDateFormat(CellValueRecordInterface cell, FormatTrackingHSSFListener formatListener) { final int formatIndex = formatListener.getFormatIndex(cell); final String formatString = formatListener.getFormatString(cell); + return isDateFormat(formatIndex, formatString); + } + + /** + * 判断日期格式 + * + * @param formatIndex 格式索引,一般用于内建格式 + * @param formatString 格式字符串 + * @return 是否为日期格式 + * @since 5.5.3 + */ + 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); } @@ -208,43 +243,22 @@ public class ExcelSaxUtil { return DateUtil.date(org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value, false)); } - /** - * 创建 {@link ExcelSaxReader} - * - * @param isXlsx 是否为xlsx格式(07格式) - * @param rowHandler 行处理器 - * @return {@link ExcelSaxReader} - * @since 5.4.4 - */ - public static ExcelSaxReader createSaxReader(boolean isXlsx, RowHandler rowHandler) { - return isXlsx - ? new Excel07SaxReader(rowHandler) - : new Excel03SaxReader(rowHandler); - } - /** * 在Excel03 sax读取中获取日期或数字类型的结果值 - * @param cell 记录单元格 - * @param value 值 + * + * @param cell 记录单元格 + * @param value 值 * @param formatListener {@link FormatTrackingHSSFListener} * @return 值,可能为Date或Double或Long * @since 5.5.0 */ - public static Object getNumberOrDateValue(CellValueRecordInterface cell, double value, FormatTrackingHSSFListener formatListener){ + public static Object getNumberOrDateValue(CellValueRecordInterface cell, double value, FormatTrackingHSSFListener formatListener) { Object result; - if(ExcelSaxUtil.isDateFormat(cell, formatListener)){ + if (isDateFormat(cell, formatListener)) { // 可能为日期格式 - result = ExcelSaxUtil.getDateValue(value); - } else { - final long longPart = (long) value; - // 对于无小数部分的数字类型,转为Long,否则保留原数字 - if (((double) longPart) == value) { - result = longPart; - } else { - result = value; - } + return getDateValue(value); } - return result; + return getNumberValue(value, formatListener.getFormatString(cell)); } /** @@ -259,9 +273,20 @@ public class ExcelSaxUtil { if (StrUtil.isBlank(value)) { return null; } - double numValue = Double.parseDouble(value); + return getNumberValue(Double.parseDouble(value), numFmtString); + } + + /** + * 获取数字类型值,除非格式中明确数字保留小数,否则无小数情况下按照long返回 + * + * @param numValue 值 + * @param numFmtString 格式 + * @return 数字,可以是Double、Long + * @since 5.5.3 + */ + private static Number getNumberValue(double numValue, String numFmtString) { // 普通数字 - if (null != numFmtString && numFmtString.indexOf(StrUtil.C_DOT) < 0) { + if (null != numFmtString && false == StrUtil.contains(numFmtString, CharUtil.DOT)) { final long longPart = (long) numValue; //noinspection RedundantIfStatement if (longPart == numValue) { diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/BigExcelWriteTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java similarity index 93% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/BigExcelWriteTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java index 6cf85898d..1b5cf41ed 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/BigExcelWriteTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java @@ -1,13 +1,10 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.poi.excel.BigExcelWriter; -import cn.hutool.poi.excel.ExcelUtil; -import cn.hutool.poi.excel.ExcelWriter; import cn.hutool.poi.excel.style.StyleUtil; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.FillPatternType; @@ -163,21 +160,21 @@ public class BigExcelWriteTest { @Test @Ignore public void writeBeanTest() { - TestBean bean1 = new TestBean(); + cn.hutool.poi.excel.TestBean bean1 = new cn.hutool.poi.excel.TestBean(); bean1.setName("张三"); bean1.setAge(22); bean1.setPass(true); bean1.setScore(66.30); bean1.setExamDate(DateUtil.date()); - TestBean bean2 = new TestBean(); + cn.hutool.poi.excel.TestBean bean2 = new cn.hutool.poi.excel.TestBean(); bean2.setName("李四"); bean2.setAge(28); bean2.setPass(false); bean2.setScore(38.50); bean2.setExamDate(DateUtil.date()); - List rows = CollUtil.newArrayList(bean1, bean2); + List rows = CollUtil.newArrayList(bean1, bean2); // 通过工具类创建writer String file = "e:/bigWriteBeanTest.xlsx"; FileUtil.del(file); diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/CellUtilTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/CellUtilTest.java similarity index 86% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/CellUtilTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/CellUtilTest.java index 63a4cac69..11f11f896 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/CellUtilTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/CellUtilTest.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import org.apache.poi.ss.usermodel.BuiltinFormats; import org.junit.Ignore; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelReadTest.java similarity index 95% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelReadTest.java index 1ed8526e1..ea6ba57a3 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelReadTest.java @@ -1,11 +1,9 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.poi.excel.ExcelReader; -import cn.hutool.poi.excel.ExcelUtil; import lombok.Data; import org.junit.Assert; import org.junit.Ignore; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java similarity index 79% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java index c1319182a..3407be109 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; @@ -6,7 +6,6 @@ import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.util.StrUtil; -import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.cell.FormulaCellValue; import cn.hutool.poi.excel.sax.Excel03SaxReader; import cn.hutool.poi.excel.sax.handler.RowHandler; @@ -65,7 +64,7 @@ public class ExcelSaxReadTest { @Test @Ignore public void readBySaxTest2() { - ExcelUtil.readBySax("e:/B23_20180404164901240.xlsx", 2, (sheetIndex, rowIndex, rowList) -> Console.log(rowList)); + ExcelUtil.readBySax("d:/test/default.xlsx", -1, (sheetIndex, rowIndex, rowList) -> Console.log(rowList)); } private RowHandler createRowHandler() { @@ -138,15 +137,33 @@ public class ExcelSaxReadTest { } @Test - public void dateReadTest() { + public void dateReadXlsTest() { List rows = new ArrayList<>(); - ExcelUtil.readBySax("data_for_sax_test.xls", 0, (i, i1, list) -> - rows.add(StrUtil.toString(list.get(0)))); + ExcelUtil.readBySax("data_for_sax_test.xls", 0, + (i, i1, list) ->{ + rows.add(StrUtil.toString(list.get(0))); + } + ); Assert.assertEquals("2020-10-09 00:00:00", rows.get(1)); // 非日期格式不做转换 Assert.assertEquals("112233", rows.get(2)); - Assert.assertEquals("1000", rows.get(3)); + Assert.assertEquals("1000.0", rows.get(3)); + Assert.assertEquals("2012-12-21 00:00:00", rows.get(4)); + } + + @Test + public void dateReadXlsxTest() { + List rows = new ArrayList<>(); + ExcelUtil.readBySax("data_for_sax_test.xlsx", 0, + (i, i1, list) -> rows.add(StrUtil.toString(list.get(0))) + ); + + Assert.assertEquals("2020-10-09 00:00:00", rows.get(1)); + // 非日期格式不做转换 + Assert.assertEquals("112233", rows.get(2)); + Assert.assertEquals("1000.0", rows.get(3)); + Assert.assertEquals("2012-12-21 00:00:00", rows.get(4)); } @Test diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelUtilTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelUtilTest.java similarity index 92% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelUtilTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelUtilTest.java index 8d723f9bf..0a0a7d1ca 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelUtilTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelUtilTest.java @@ -1,6 +1,5 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; -import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.cell.CellLocation; import org.junit.Assert; import org.junit.Test; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelWriteTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java similarity index 93% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelWriteTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java index 17bc26ba7..4d16c964d 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelWriteTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; @@ -6,8 +6,6 @@ import cn.hutool.core.io.FileUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.poi.excel.ExcelUtil; -import cn.hutool.poi.excel.ExcelWriter; import cn.hutool.poi.excel.style.StyleUtil; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.FillPatternType; @@ -340,21 +338,21 @@ public class ExcelWriteTest { @Test @Ignore public void writeBeanTest() { - TestBean bean1 = new TestBean(); + cn.hutool.poi.excel.TestBean bean1 = new cn.hutool.poi.excel.TestBean(); bean1.setName("张三"); bean1.setAge(22); bean1.setPass(true); bean1.setScore(66.30); bean1.setExamDate(DateUtil.date()); - TestBean bean2 = new TestBean(); + cn.hutool.poi.excel.TestBean bean2 = new cn.hutool.poi.excel.TestBean(); bean2.setName("李四"); bean2.setAge(28); bean2.setPass(false); bean2.setScore(38.50); bean2.setExamDate(DateUtil.date()); - List rows = CollUtil.newArrayList(bean1, bean2); + List rows = CollUtil.newArrayList(bean1, bean2); // 通过工具类创建writer String file = "e:/writeBeanTest.xlsx"; FileUtil.del(file); @@ -376,17 +374,17 @@ public class ExcelWriteTest { @Test @Ignore public void writeBeanTest2() { - OrderExcel order1 = new OrderExcel(); + cn.hutool.poi.excel.OrderExcel order1 = new cn.hutool.poi.excel.OrderExcel(); order1.setId("1"); order1.setNum("123"); order1.setBody("body1"); - OrderExcel order2 = new OrderExcel(); + cn.hutool.poi.excel.OrderExcel order2 = new cn.hutool.poi.excel.OrderExcel(); order1.setId("2"); order1.setNum("456"); order1.setBody("body2"); - List rows = CollUtil.newArrayList(order1, order2); + List rows = CollUtil.newArrayList(order1, order2); // 通过工具类创建writer String file = "f:/test/writeBeanTest2.xlsx"; FileUtil.del(file); diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/OrderExcel.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/OrderExcel.java similarity index 73% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/OrderExcel.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/OrderExcel.java index 279221787..10bf20af9 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/OrderExcel.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/OrderExcel.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import lombok.Data; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/TestBean.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/TestBean.java similarity index 79% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/TestBean.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/TestBean.java index 62c8405ba..a1ee1644a 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/TestBean.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/TestBean.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import lombok.Data; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/word/test/WordWriterTest.java b/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java similarity index 94% rename from hutool-poi/src/test/java/cn/hutool/poi/word/test/WordWriterTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java index b05131edd..22effb9a8 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/word/test/WordWriterTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.word.test; +package cn.hutool.poi.word; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.FileUtil; diff --git a/hutool-poi/src/test/resources/data_for_sax_test.xls b/hutool-poi/src/test/resources/data_for_sax_test.xls index ebebc51bc..a5f18d634 100644 Binary files a/hutool-poi/src/test/resources/data_for_sax_test.xls and b/hutool-poi/src/test/resources/data_for_sax_test.xls differ diff --git a/hutool-poi/src/test/resources/data_for_sax_test.xlsx b/hutool-poi/src/test/resources/data_for_sax_test.xlsx index 8fb64fd8b..ecbac56a9 100644 Binary files a/hutool-poi/src/test/resources/data_for_sax_test.xlsx and b/hutool-poi/src/test/resources/data_for_sax_test.xlsx differ