Java 读取 Excel 中的时间数据
在 Java 中读取 Excel 文件中的时间数据需要注意 Excel 存储日期/时间的特殊方式,以下是几种常用的方法:
使用 Apache POI 读取 Excel 时间
Apache POI 是最常用的 Java 操作 Excel 的库。
基本步骤
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExcelDateReader {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("example.xlsx");
Workbook workbook = new XSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);
// 假设时间在第一行第一列
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
// 处理日期单元格
if (cell.getCellType() == CellType.NUMERIC) {
// 检查是否是日期格式
if (DateUtil.isCellDateFormatted(cell)) {
Date date = cell.getDateCellValue();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("日期: " + sdf.format(date));
} else {
// 如果不是日期格式,可能是数字
double numericValue = cell.getNumericCellValue();
System.out.println("数字: " + numericValue);
}
} else if (cell.getCellType() == CellType.STRING) {
// 如果是字符串格式,尝试解析
String dateStr = cell.getStringCellValue();
System.out.println("字符串: " + dateStr);
}
workbook.close();
fis.close();
}
}
处理不同日期格式
// 获取单元格的日期格式
CellStyle cellStyle = cell.getCellStyle();
short formatIndex = cellStyle.getDataFormat();
String formatStr = cellStyle.getDataFormatString();
// 使用 POI 的 DateFormat 处理
DataFormatter dataFormatter = new DataFormatter();
String formattedDate = dataFormatter.formatCellValue(cell);
System.out.println("格式化日期: " + formattedDate);
使用 EasyExcel 读取时间
EasyExcel 是阿里巴巴开源的 Excel 处理库,性能更好。
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.metadata.ReadRowHolder;
import java.text.SimpleDateFormat;
import java.util.Date;
public class EasyExcelDateReader {
public static void main(String[] args) {
String fileName = "example.xlsx";
EasyExcel.read(fileName, ExcelData.class, new AnalysisEventListener<ExcelData>() {
@Override
public void invoke(ExcelData data, AnalysisContext context) {
// 假设日期字段名为dateField
if (data.getDateField() != null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("日期: " + sdf.format(data.getDateField()));
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("读取完成");
}
// 处理日期格式
@Override
public void extraRead(CellData cellData, ReadRowHolder readRowHolder) {
if (cellData.getType() == CellData.DateType.NUMBER) {
Date date = cellData.getDateValue();
readRowHolder.getCurrentRowHolder().getCurrentRow()
.getCell(readRowHolder.getCellIndex())
.setCellValue(date);
}
}
}).sheet().doRead();
}
}
// 定义实体类
class ExcelData {
@ExcelProperty("日期")
private Date dateField;
// getters and setters
}
处理 Excel 日期数字
Excel 中日期实际上是存储为数字的,从 1900/1/1 开始的天数。
// 将 Excel 序列号转换为 Java Date
public static Date excelDateToDate(double excelDate) {
// Excel 的日期是从 1900-01-01 开始的,但 Excel 认为是 1900-01-00
// 所以需要减去 2 天来修正
// 对于 1900-02-29 这个不存在的日期,Excel 也认为存在
// 所以需要额外处理
if (excelDate < 60) {
// 1900-02-29 之前的情况
return new Date((long)((excelDate - 2) * 24 * 60 * 60 * 1000));
} else {
return new Date((long)((excelDate - 1) * 24 * 60 * 60 * 1000));
}
}
常见问题解决
问题1:读取的日期是数字而不是日期
原因:单元格没有设置为日期格式
解决:使用 DateUtil.isCellDateFormatted() 检查,或者强制转换为日期
if (cell.getNumericCellValue() > 0) {
Date date = DateUtil.getJavaDate(cell.getNumericCellValue());
System.out.println(date);
}
问题2:日期格式不正确
原因:Excel 中的日期格式与 Java 期望的不一致 解决:获取 Excel 中的格式字符串并正确解析
DataFormatter formatter = new DataFormatter();
String formattedDate = formatter.formatCellValue(cell);
System.out.println("原始格式: " + formattedDate);
问题3:时区问题
原因:Excel 和 Java 使用不同的时区 解决:指定时区
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+8")); // 设置为东八区
System.out.println(sdf.format(date));
完整示例代码
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.DateUtil;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class CompleteExcelDateExample {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("dates.xlsx");
Workbook workbook = new XSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);
DataFormatter dataFormatter = new DataFormatter();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
for (Row row : sheet) {
for (Cell cell : row) {
switch (cell.getCellType()) {
case STRING:
System.out.println("字符串: " + cell.getStringCellValue());
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
Date date = cell.getDateCellValue();
System.out.println("日期(原始): " + date);
System.out.println("日期(格式化): " + sdf.format(date));
// 获取 Excel 格式
CellStyle style = cell.getCellStyle();
String format = style.getDataFormatString();
System.out.println("Excel 格式: " + format);
} else {
System.out.println("数字: " + cell.getNumericCellValue());
}
break;
case BOOLEAN:
System.out.println("布尔值: " + cell.getBooleanCellValue());
break;
case FORMULA:
System.out.println("公式: " + cell.getCellFormula());
break;
default:
System.out.println("其他类型");
}
}
}
workbook.close();
fis.close();
}
}
方法应该能帮助你正确处理 Java 读取 Excel 中的时间数据,根据你的具体需求选择合适的方法。
