使用easyexcel进行excel读取时,发现对日期的转换不对,读取到的日期是一个dubble型的浮点数。比如说43458.234189814815
经查资料,这个浮点数其实就是excel内部存储时间的形式,也叫时间序列号
规则如下:
Excel将日期和时间存储为称为日期序列号或日期时序列号的数字。
当你在Excel中查看日期时,它实际上是一个常规数字,其格式设置为日期。如果将单元格格式更改为“常规”,则会看到基础日期序列号。
日期序列号的整数部分表示日期,小数部分表示时间。日期从1900年1月1日开始,即1/1/1900的日期序列号为1。
警告!1900年2月28日之后的Excel日期实际上是一天。Excel表现得好像1900年2月29日存在,但事实并非如此。
Microsoft故意在Excel中包含此错误,以便它与当时占据大部分市场份额的电子表格程序保持兼容;
但是这个bug,只要您的所有日期都晚于1900年3月1日,这不是问题。
日期
Excel中,这些被称为“日期序列号”,它们使我们能够进行数学计算并在公式中使用日期。
Excel日期序列号示例
“日期序列号”列显示日期序列号等效的“日期”列值。
例如,2017年1月1日有42736.即日期序号 , 2017年1月是42736天自 1899年12月31日。
提示:将日期序列号列格式化为日期,您将看到它们与日期列值相同。
时间
时间也使用序列号格式并表示为小数部分。
小时:由于24小时= 1天,我们可以推断24小时的时间序列号为1,可以格式化为24:00或12:00 AM或0:00显示的时间。而12小时或12:00的时间值为0.50,因为它是24小时或半天的一半,而1小时是0.41666’,因为它是一天的1/24。
分钟:由于1小时是一天的1/24,1分钟是1/60小时,我们也可以说1分钟是一天的1/1440,或者它的时间序列号是0.00069444’
秒:因为秒是1/60分钟,即1/60小时,即一天的1/24。我们还可以说一秒是1/86400的一天或时间序列号形式它是0.0000115740740740741 …
Excel时间序列号示例
日期和时间在一起
现在我们知道如何存储日期和时间,我们可以把它们放在一起 ddddd.tttttt
例如,2012年1月为10:00:00 am有日期时间的序列值40909.4166666667
40909是代表2012年1 月1 日的序列值,4166666667是10:00 AM和00秒的十进制值。
知道以上规则,我们可以自己手写一个转换方法,虽然poi里面也内置了这个方法,但是没有必要为了转换一个日期而引入如此庞大的框架。
/**
* 解析时间 43458.234189814815 解析秒数的例子
*/
public static LocalTime getTime(double d) {
//全部转成秒
int sec = (int) (d * 86400);
//时
int s = sec / 3600;
//分
int h = sec % 3600 / 60;
//秒
int m = sec % 3600 % 60;
String ss = s + "";
String hh = h + "";
String mm = m + "";
if (s < 10) {
ss = "0" + ss;
}
if (h < 10) {
hh = "0" + hh;
}
if (m < 10) {
mm = "0" + mm;
}
LocalTime time = LocalTime.parse(ss + ":" + hh + ":" + mm);
return time;
}
不过推荐使用这个方法 是从poi里面截取出来的
/**
* @param use1904windowing
* @param value
* @return
*/
public String getPOIDate(boolean use1904windowing, double value) {
log.info("getDate: " + value);
int wholeDays = (int) Math.floor(value);
int millisecondsInDay = (int) ((value - (double) wholeDays) * 8.64E7D + 0.5D);
Calendar calendar = new GregorianCalendar();
short startYear = 1900;
byte dayAdjust = -1;
if (use1904windowing) {
startYear = 1904;
dayAdjust = 1;
} else if (wholeDays < 61) {
dayAdjust = 0;
}
calendar.set(startYear, 0, wholeDays + dayAdjust, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, millisecondsInDay);
if (calendar.get(Calendar.MILLISECOND) == 0) {
calendar.clear(Calendar.MILLISECOND);
}
Date date = calendar.getTime();
SimpleDateFormat s = new SimpleDateFormat(“yyyy-MM-dd hh:mm:ss”);
return s.format(date);
}
在使用EasyExcel处理Excel时遇到日期转换问题,实际读取到的是日期序列号(如43458.234189814815)。Excel中的日期以浮点数形式存储,整数部分代表日期,小数部分代表时间,起始于1900年1月1日。由于1900年2月29日的错误,需要注意日期范围。可以通过手动转换或使用POI的内置方法将序列号转为日期。
259





