文章首发于个人博客,欢迎访问关注:
https://www.lin2j.tech
写这个转换函数的原因是之前在开发的过程中出现了一个 Bug。业务背景是打算导出一批数据到 Excel ,然后导入第三方系统。但是导入的时候就发生了错误,因为时间的那个字段,在导入第三方系统时,没能被第三方系统正确识别。经过对比正常导入的 Excel 发现,正常导入时,时间单元格的格式是
常规
,而我导出来的是
文本
,需要手动双击单元格才能变为
常规
。猜测可能是第三方系统读取时,读的是时间的数值(真是奇葩),也就是这篇文章的重点。
easypoi 使用模板导出数据时,模板中自定义的单元格时间格式(yyyy-MM-dd hh:mm:ss)没能起作用。后来发现是因为导出的时候,将时间字段写为文本了,导出后需要手动双击单元格,这样 Excel 才会把这个单元格转换为
常规
,让时间由字符串变成对应的一个数值。
PS:这个 Bug 不是我写的,我完全是在给别人擦屁股!!!为此我还研究了一波 Excel 单元格格式的问题。对比了正常导入和非正常导入的 Excel 很多遍,最后才发现这个小细节,问题才能得到解决。
Excel 中的日期是一个数值,由 Excel 自己的规则去定义
Excel 中的日期转换成数值的方式
-
计算当前日期距离 1900年1月0日的天数作为整数部分
-
Excel 把 24 小时当成1,比如 12 时,就是 0.5,所以一天中的某个时刻是 0-1之间的某个小数
-
最后把整数和小数部分加起来就是当前日期的数值表示
-
1900 年之前的日期 Excel 会表示为文本,用不了日期函数,可以用加载宏 Extended Date Functions
这里提供一个转换方法以及使用到的常量
* Excel 中日期的计算是从 1900年1月0日开始的 <br>
* 但是实际日期没有 1 月 0 日 <br>
* 这个数值是 1900年1月1日0时0分0秒 的时间戳<br>
private
static
final
long
EXCEL_BEGIN_TIME
=
-
2209017600000
L
;
* Excel 中日期数值保留的小数位是 10
public
static
final
int
EXCEL_SCALE
=
10
;
* 24 小时的毫秒数
private
static
final
long
DAY_MILLISECONDS
=
1000
*
3600
*
24
;
* 将日期转换成excel中日期对应的数值
private
static
BigDecimal
date2ExcelNumber
(
Date date
)
{
BigDecimal days
=
new
BigDecimal
(
(
date
.
getTime
(
)
-
EXCEL_BEGIN_TIME
)
/
(
DAY_MILLISECONDS
)
+
2
)
;
Date begin
=
DateUtil
.
beginOfDay
(
date
)
;
BigDecimal time
=
new
BigDecimal
(
(
date
.
getTime
(
)
-
begin
.
getTime
(
)
)
)
.
divide
(
new
BigDecimal
(
DAY_MILLISECONDS
)
,
EXCEL_SCALE
,
BigDecimal
.
ROUND_HALF_UP
)
;
return
days
.
add
(
time
)
;
从xlsx格式
中
解析
日期
在
Java
开发
中
,我们经常需要处理
Excel
文件。然而,当我们从xlsx文件
中
读取
日期
数据时,可能会遇到一个问题:
日期
数据被解析成了数字。这是因为
Excel
中
的
日期
是以数字形式存储的,而不是直接以
日期
的格式保存的。因此,我们需要对这些数字进行处理,将其
转换成
日期
格式。
日期
数据转换
我们可以使用J...
if (DateUtil.isCellDateFormatted(cell)) {//判断是否时时间格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
value = sdf.format(cell.getDateCellValue());
把上一个bug解决好了之后,当我的心情逐渐的好了的时候,突然还是有问题,当
excel
把单元格调成文本的时候(见下图),正常的
日期
格式的,按照我上篇博客写的,也会出问题,不会正常的格式化,糟糕,又挨批了(此时的心情…)
其实锁定了问题,就好解决了,其实有的时候我们限制不了用户用什么样的形式(当把模板规定好,用文本形式的也可以)当万一出现传的不是文本的情况,所以我做了双重的判断,如下图:
下图是判断是否为int类型的方法:
经历了这次,我觉得以后我会更加细心对于每个细节,如果我还有问题,大家
在
Excel
中
的
日期
格式,其
数值
为距离1900年1月1日的天数,比如2009-12-24将其转化为数字格式时变成了40171,在用
java
处理的时候,读取的也将是40171。
在POI处理
Excel
中
的
日期
类型的单元格时,如果仅仅是判断它是否为
日期
类型的话,最终会以NUMERIC类型来处理。正确的处理方法是先判断单元格的类型是否则NUMERIC类型,然后再判断单元格是否为
日期
格式,如果是的话,
用过Jxl或者POI导入
Excel
信息的朋友应该都遇到过这样的问题。
日期
格式的单元格有些会识别成数字单元格。(为什么说有些呢?因为在
Excel
文件
中
输入2008-3-18的
日期
可以正确导入,但是输入3-18的就会识别成数字。)关于这个问题我找了很久,都没有找到解答。现在解决了,所以记录以下,一是怕以后忘了,二是希望遇到这个问题的朋友可以少走弯路。
首先来分析一下这个问题的成因。既然两个开源包...
生成 方法调用图 和 Maven 依赖图: Draw Graph
解析 Mapper.xml 中的 SQL,涉及的表和条件列,Git 最后修改时间和作者,生成 Excel 表格:SQL List
逐层解压,删除相同文件,反编译 class 对比:Compare Jar
查找多个文件或行的作者 与 导出搜索: Find Author