2010/08/18

[C#][Java] Excel 日期欄位的數值轉換

在 Excel 中, 如果將儲存格的資料設定至 "日期", 就可以輸入一個數字表示日期. (下圖)
儲存格格式
也因為 Excel 用數字表示日期, 所以有些 API 在讀取 Excel 裡的儲存格資料時, 會讀出一個數字的字串, 而不是一般預期的日期字串.

數字字串的轉換規則如下:
  1. 整數部分: 該整數是從1900/1/1 起算, 數字 1 表示 1900/1/1.
  2. 小數部分: 小數部份是指佔該天的百分比, 所以 0.5 表示中午 12 點, 0.25 表示上午 6 點.
知道規則後, 剩下的就是如何實作轉換的程式. 以下是將一個數字字串 "40380.966042" 轉換至 "2010/7/21  23:11:06” 的 Sample Code:
  • C#:
    //先準備好一個 1900/1/1 的 DateTime
    DateTime dtDate = new DateTime(1900, 1, 1);
    string strDateNumber = "40380.966042";
    //將數字字串以小數點做分隔符號, 拆成整數與小數
    string[] aryDateTime = strDateNumber.Split('.');
    int intDays = int.Parse(aryDateTime[0]);
    //設定天數 (因為 1 表示 1900/1/1, 所以記得要減 1, 不然會多算一天)
    dtDate = dtDate.AddDays(intDays - 1);
    double dblSecond = 0d;
    if (aryDateTime.Length == 2)
    {
      float fltTime = float.Parse("0." + aryDateTime[1]);
      //如果要精準到毫秒, 可用 86400000, 不過後續要用 AddMilliseconds()
      //同理, 用 24 小時去計算時, 後續要用 AddHours()
      dblSecond = 86400 * fltTime;
      dtDate = dtDate.AddSeconds(dblSecond);
    }
    //以指定格式進行輸出
    Console.WriteLine(dtDate.ToString("yyyy/M/d HH:mm:ss"));
  • Java:
    //先準備好一個 Calendar 物件, 並將時間歸零
    Calendar calObj = Calendar.getInstance();
    calObj.setTimeInMillis(0L);
    String strDateNumber = "40380.966042";
    String[] aryDateTime = strDateNumber.split("\\.");
    //設定天數
    calObj.set(1900, 0, Integer.parseInt(aryDateTime[0]) - 1);
    if (aryDateTime.length == 2) {
        //設定時間, 做法同 C# 的 Sample Code
        float f = Float.parseFloat("0." + aryDateTime[1]) * 86400;
        calObj.add(Calendar.SECOND, (int) f);
    }
    // 要用 GMT 格式才能抓到我們要的日期
    // 各位可以比較 toGMTString(), toLocaleString() 和 toString() 的差別
    System.out.println(calObj.getTime().toGMTString());
    System.out.println(calObj.getTime().toLocaleString());
    System.out.println(calObj.getTime().toString());

1 則留言: