一. 前言
我在讀取客戶提供的excel中發現某幾列時間是數值類型,最開始還以為客戶給錯了,最后才發現這屬於一種時間格式,一起來看看如果遇到這種該怎么處理吧
二. 分析這種時間
假如在我們excel中有一列數據,我們需要讀取出來,使用POI讀取一下試試
1 //獲取字符串 2 public static String getCellValueString(Cell cell) { 3 if (cell == null) return ""; 4 cell.setCellType(CellType.STRING); 5 return cell.getRichStringCellValue().getString().trim(); 6 } 7 //獲取時間 8 public static Long getCellValueLong(Cell cell) throws Exception { 9 if (cell == null) return null; 10 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); 11 Date cellD = cell.getDateCellValue(); 12 if (cellD == null) return null; 13 long res = cellD.getTime(); 14 String format = simpleDateFormat.format(res); 15 Date parse = simpleDateFormat.parse(format); 16 // Long long1 = Long.valueOf(format); 17 return parse.getTime(); 18 } 19 public static void main(String[] args){ 20 String path = "時間測試.xlsx"; 21 try { 22 FileInputStream fileInputStream = new FileInputStream(new File(path)); 23 Map<String, Integer> titleIndexMap = new HashMap<>(); 24 XSSFWorkbook hssfWorkbook = new XSSFWorkbook(fileInputStream); 25 XSSFSheet sheet = hssfWorkbook.getSheetAt(0); 26 XSSFRow titleRow = sheet.getRow(0); 27 int lastRowNum = sheet.getLastRowNum(); 28 for (int j = 0; j <= titleRow.getLastCellNum(); j++) { 29 titleIndexMap.put(getCellValueString(titleRow.getCell(j)), j); 30 } 31 String time1 = ""; 32 Long time2 = null; 33 for (int k = 1; k <= lastRowNum; k++) { 34 XSSFRow rowTemp = sheet.getRow(k); 35 if (null == rowTemp) { 36 continue; 37 } 38 time1 = getCellValueString(rowTemp.getCell(titleIndexMap.get("日期"))); 39 System.out.println(time1); 40 //time2 = getCellValueLong(rowTemp.getCell(titleIndexMap.get("日期"))); 41 //System.out.println(time2); 42 } 43 hssfWorkbook.close(); 44 fileInputStream.close(); 45 }catch (Exception e){ 46 e.printStackTrace(); 47 } 49 }
第一種通過讀取字符串來讀取,結果如下
我們可以看到是數字,這種時間類型當時可能不太理解,這里我們可以直接用第二種Long類型來讀取,如果讀取出來是時間戳,那么就不需要轉換,但是有些時候excel的數據就是這些數字,這時候就必須開始轉換了,如果在強行讀取會報錯,下邊看看如何轉換,提供兩個方法,兩種方式都可以
三.轉換數字類型時間為時間戳
1 public static String getDateByString(String value){ 2 SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd"); 3 //Excel讀取日期讀到全為數字,數字是從1900年到該日期的天數 4 if(value.matches("^[0-9]+$")){ 5 Long dayNum=Long.valueOf(value); 6 //獲取初始時間 7 Calendar calendar=new GregorianCalendar(1900,0,-1); 8 Date initDate=calendar.getTime(); 9 //獲取相差秒數 10 Long addTime=dayNum*24*60*60*1000; 11 //得到當前時間 12 Long time=initDate.getTime()+addTime; 13 Date actualDate=new Date(time); 14 return simpleDateFormat.format(actualDate); 15 } 16 //if(value.contains("-")){ 17 // try{ 18 // Date temp=simpleDateFormat.parse(value); 19 // return simpleDateFormat.format(temp); 20 // }catch (Exception e){ 21 // e.printStackTrace(); 22 // } 23 //} 24 //if(value.contains("無")){ 25 // return ""; 26 //} 27 //return ""; 28 return ""; 29 } 30 public static String HSSFDateFormat(String value){ 31 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); 32 //這里使用POI自帶方法傳入數字,自動轉換為Date 33 Date javaDate = HSSFDateUtil.getJavaDate(Double.parseDouble(value)); 34 //System.out.println(javaDate.getTime()); 35 String format = simpleDateFormat.format(javaDate); 36 return format; 37 }
這里我調用這兩個方法,看看效果
傳入的參數就是讀取到的第一個數字日期,2016-3-5
結果就是格式化后的String類型的日期,時間戳同理,這里我們就可以存入數據庫或者其他的操作了
四. 大家可能不知道這種時間是如何出現,簡單說一下,如果有興趣,可以看一下
這個時間是1900年1月1日到某個日期經過了多少天,例如1900-1-1到2016-3-5經過了42434天,要考慮到平閏年的差值,那么我們可以簡單得出一個理論
我們推斷一個算法,X=當前年 Y=當前月 N=當前日 Z = (X-1900)中閏年的數量 那么我們需要 (X-1900)*365 + Z + Y(閏年中當前月需要判斷月份)+ N 即可
下邊用代碼實現,大部分內容為 https://blog.csdn.net/weixin_49689284/article/details/108168783 其中做了一些修改
1 public static void main(String[] args) { 2 //Scanner sc = new Scanner(System.in); 3 //System.out.println("輸入年份:"); 4 //int year = sc.nextInt(); 5 //System.out.println("輸入月份:"); 6 //int month = sc.nextInt(); 7 //System.out.println("輸入日期:"); 8 //int days = sc.nextInt(); 9 int year = 2020; 10 int month = 5; 11 int days = 20; 12 /*1,年:(閏年能將4整除,不能將100整除) 13 1.1,按平年算,每年365天 14 1.2,每個閏年加1天,若輸入的那年是閏年,2月后,要加1天,反之不用*/ 15 int yDays = (year -1900)*365; 16 17 int rDays = 0;//每個潤年加1 18 for (int i = 1900; i <=year ; i++) { 19 if (DateUtil.isLeapYear(i)) { 20 rDays++; 21 if (month < 3) {//若輸入的年份為潤,判斷其是否過了2月,沒過減1 22 rDays = rDays - 1; 23 } 24 } 25 } 26 27 /*2,月:按照平年每個月的天數:31,28,31,30,31,30,31,31,30,31,30,31*/ 28 int[] months = {31,28,31,30,31,30,31,31,30,31,30,31}; 29 int mDays = 0; 30 //如果當前 年是閏年並且月份大於3,那么月份需要先累加+1 31 if(DateUtil.isLeapYear(year)&&month>3){ 32 mDays++; 33 } 34 if (month == 1){//如果等於1月份,不算月份直接加天數即可 35 mDays = 0; 36 }else{ 37 for (int i = 0; i <month-1 ; i++){ //減1,因為當月沒過,按下面的日期來算 38 mDays += months[i]; //累加當月之前的天數 39 } 40 } 41 /*4,日期: 天數直接相加*/ 42 int sum = yDays + rDays + mDays +days; 43 System.out.println(yDays); 44 System.out.println(rDays); 45 System.out.println(mDays); 46 System.out.println(days); 47 System.out.println(sum); 48 }
//改用DataUtil判斷平潤,下邊是maven
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.9</version>
</dependency>
可以用前邊的代碼,驗證一下