Skip to content

Commit

Permalink
# 4.0.2
Browse files Browse the repository at this point in the history
* 兼容部分日期格式读取异常的问题
  • Loading branch information
zhuangjiaju committed Sep 11, 2024
1 parent efa7dff commit fab7653
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>4.0.2</version>
<version>4.0.3</version>
</dependency>
```

Expand Down
101 changes: 96 additions & 5 deletions easyexcel-core/src/main/java/com/alibaba/excel/util/DateUtils.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */

package com.alibaba.excel.util;

import java.math.BigDecimal;
Expand All @@ -9,13 +26,16 @@
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Pattern;

import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;

/**
* Date utils
Expand Down Expand Up @@ -63,6 +83,15 @@ public class DateUtils {

public static String defaultLocalDateFormat = DATE_FORMAT_10;

public static final int SECONDS_PER_MINUTE = 60;
public static final int MINUTES_PER_HOUR = 60;
public static final int HOURS_PER_DAY = 24;
public static final int SECONDS_PER_DAY = (HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE);

// used to specify that date is invalid
private static final int BAD_DATE = -1;
public static final long DAY_MILLISECONDS = SECONDS_PER_DAY * 1000L;

private DateUtils() {}

/**
Expand Down Expand Up @@ -301,13 +330,75 @@ private static DateFormat getCacheDateFormat(String dateFormat) {
* @return Java representation of the date, or null if date is not a valid Excel date
*/
public static Date getJavaDate(double date, boolean use1904windowing) {
//To calculate the Date, in the use of `org.apache.poi.ss.usermodel.DateUtil.getJavaDate(double, boolean,
// java.util.TimeZone, boolean), Date when similar `2023-01-01 00:00:00.500`, returns the`2023-01-01
// 00:00:01`, but excel in fact shows the `2023-01-01 00:00:00`.
// `org.apache.poi.ss.usermodel.DateUtil.getLocalDateTime(double, boolean, boolean)` There is no problem.
return Date.from(getLocalDateTime(date, use1904windowing).atZone(ZoneId.systemDefault()).toInstant());
Calendar calendar = getJavaCalendar(date, use1904windowing, null, true);
return calendar == null ? null : calendar.getTime();
}

/**
* Get EXCEL date as Java Calendar with given time zone.
* @param date The Excel date.
* @param use1904windowing true if date uses 1904 windowing,
* or false if using 1900 date windowing.
* @param timeZone The TimeZone to evaluate the date in
* @param roundSeconds round to closest second
* @return Java representation of the date, or null if date is not a valid Excel date
*/
public static Calendar getJavaCalendar(double date, boolean use1904windowing, TimeZone timeZone, boolean roundSeconds) {
if (!isValidExcelDate(date)) {
return null;
}
int wholeDays = (int)Math.floor(date);
int millisecondsInDay = (int)((date - wholeDays) * DAY_MILLISECONDS + 0.5);
Calendar calendar;
if (timeZone != null) {
calendar = LocaleUtil.getLocaleCalendar(timeZone);
} else {
calendar = LocaleUtil.getLocaleCalendar(); // using default time-zone
}
setCalendar(calendar, wholeDays, millisecondsInDay, use1904windowing, roundSeconds);
return calendar;
}


public static void setCalendar(Calendar calendar, int wholeDays,
int millisecondsInDay, boolean use1904windowing, boolean roundSeconds) {
int startYear = 1900;
int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
if (use1904windowing) {
startYear = 1904;
dayAdjust = 1; // 1904 date windowing uses 1/2/1904 as the first day
}
else if (wholeDays < 61) {
// Date is prior to 3/1/1900, so adjust because Excel thinks 2/29/1900 exists
// If Excel date == 2/29/1900, will become 3/1/1900 in Java representation
dayAdjust = 0;
}
calendar.set(startYear, Calendar.JANUARY, wholeDays + dayAdjust, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, millisecondsInDay);
if (calendar.get(Calendar.MILLISECOND) == 0) {
calendar.clear(Calendar.MILLISECOND);
}
if (roundSeconds) {
// This is different from poi where you need to change 500 to 499
calendar.add(Calendar.MILLISECOND, 499);
calendar.clear(Calendar.MILLISECOND);
}
}


/**
* Given a double, checks if it is a valid Excel date.
*
* @return true if valid
* @param value the double value
*/

public static boolean isValidExcelDate(double value)
{
return (value > -Double.MIN_VALUE);
}


/**
* Given an Excel date with either 1900 or 1904 date windowing,
* converts it to a java.time.LocalDateTime.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import java.io.File;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;

import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson2.JSON;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
Expand All @@ -22,13 +24,16 @@
@Slf4j
public class DateFormatTest {

private static File file07V2;
private static File file07;
private static File file03;

@BeforeAll
public static void init() {
file07 = TestFileUtil.readFile("dataformat" + File.separator + "dataformat.xlsx");
file03 = TestFileUtil.readFile("dataformat" + File.separator + "dataformat.xls");
file07V2 = TestFileUtil.readFile("dataformat" + File.separator + "dataformatv2.xlsx");

}

@Test
Expand All @@ -43,6 +48,16 @@ public void t02Read03() {
readUs(file03);
}

@Test
public void t03Read() {
List<Map<Integer, String>> dataMap = EasyExcel.read(file07V2).headRowNumber(0).doReadAllSync();
log.info("dataMap:{}", JSON.toJSONString(dataMap));
Assertions.assertEquals("15:00", dataMap.get(0).get(0));
Assertions.assertEquals("2023-1-01 00:00:00", dataMap.get(1).get(0));
Assertions.assertEquals("2023-1-01 00:00:00", dataMap.get(2).get(0));
Assertions.assertEquals("2023-1-01 00:00:01", dataMap.get(3).get(0));
}

private void readCn(File file) {
List<DateFormatData> list =
EasyExcel.read(file, DateFormatData.class, null).locale(Locale.CHINA).sheet().doReadSync();
Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@


<properties>
<revision>4.0.2</revision>
<revision>4.0.3</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jdk.version>1.8</jdk.version>
<gpg.skip>true</gpg.skip>
Expand Down
4 changes: 4 additions & 0 deletions update.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 4.0.3

* 兼容部分日期格式读取异常的问题

# 4.0.2

* 兼容某些特殊的xls: 修改了内置的样式导致判断样式错误
Expand Down

0 comments on commit fab7653

Please sign in to comment.