文章首发于个人博客,欢迎访问关注: 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 ) { // 从 1900 年 1 月 0 日(不存在的日期,相当于计算机中经常从 0 计起) 计起, // 然后 date 那天也算是 1 天,所以这里要加 2 BigDecimal days = new BigDecimal ( ( date . getTime ( ) - EXCEL_BEGIN_TIME ) / ( DAY_MILLISECONDS ) + 2 ) ; // date 那天的 0时0分0秒 Date begin = DateUtil . beginOfDay ( date ) ; // excel 把一天的某个时刻当成 0 - 1 之间的一个小数 BigDecimal time = new BigDecimal ( ( date . getTime ( ) - begin . getTime ( ) ) ) // 要设置 scale,否则可能因为无限循环小数而报错 . 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