2012-08-15 189 views
9

我有一個.CSV文件,我正在讀入一個C#程序。在其中一列中,有一個日期,但是它是「一般」格式,因此它在.CSV中顯示爲一個數字。例如:41172.將Double轉換爲DateTime?

如何將此數字轉換爲格式爲dd/mm/yyyy的C#中的日期? 41172相當於20/09/2012。

+0

我同意沒有這樣的日期格式,因爲我知道我的asp.net!它只是一個隨機數!你sholud嘗試導出一個有效的日期到CSV文件。什麼程序正在創建CSV文件? – Haris 2012-08-15 11:40:01

+4

DateTime.FromOADate(41172)是否適合您? – dash 2012-08-15 11:48:49

回答

13

編輯:正如在評論和其他答案中指出的,DateTime.FromOADate是一個更好的方法。如果它不被接受,我會刪除這個答案。 (但是,仍然有像.NET核心在不支持FromOADate平臺所以還是使用這些平臺的人有用。)

我懷疑你想:

DateTime date = new DateTime(1900, 1, 1).AddDays(days - 2); 

(見爲什麼其他答案您需要減去2.)

+4

http://msdn.microsoft.com/en-us/library/system.datetime.fromoadate.aspx - 「基準日期之前或之後的天數,1899年12月30日午夜」 – Richard 2012-08-15 11:50:47

+1

而傳言是:因爲1900年不是一個閏年,但有人忘了。 – 2012-08-15 11:54:21

+0

它似乎是一致的,所以我可以減去2.非常感謝。 – Paul 2012-08-15 11:54:38

2

Excel使用的日期格式舊,但DateTime.FromOADate函數仍支持該函數,您可以使用該函數轉換此數字。它被定義爲

數天前,或在基準日期後,午夜,12月30日 1899年

+0

這就是我們通常使用Excel日期的方式。 – dash 2012-08-15 11:55:25

30

若要從日期時間去在「Excel的格式」的C#日期時間,你可以使用DateTime.FromOADate函數。

在你上面的例子:

DateTime myDate = DateTime.FromOADate(41172); 

把它寫出來顯示在所需的格式,使用:

myDate.ToString("dd/MM/yyyy"); 

如果你想知道哪裏在Excel中的日期處理的差異從何而來,它應該是故意的:

當Lotus 1-2-3首次發佈時,該程序假定年儘管它實際上不是一個閏年,1900年仍是一個閏年。這個 使程序更容易處理閏年,並且幾乎不會對Lotus 1-2-3中的所有日期計算造成傷害 。

當Microsoft Multiplan和Microsoft Excel發佈時,他們還假設1900年是閏年。這允許Microsoft Multiplan 和Microsoft Excel使用Lotus 1-2-3使用的相同的序列日期系統,並提供與Lotus 1-2-3的更大兼容性。作爲一個閏年處理 1900也使用戶更容易將工作表 從一個程序移動到另一個程序。

雖然技術上可以糾正這種行爲,以致當前版本的Microsoft Excel不會假設1900年是飛躍 年,但這樣做的缺點超過了優勢。

來源:http://www.ozgrid.com/Excel/ExcelDateandTimes.htm

+1

這是另一個有趣的軼事關於同樣的特質:http://www.joelonsoftware.com/items/2006/06/16.html – CrazyPyro 2014-07-02 17:25:22

-1

我已經看到了這個來自MSDN:http://msdn.microsoft.com/en-us/library/system.datetime.fromoadate.aspx,但實際上我認爲這是錯誤的。

真正的問題是,Excel錯誤地認爲,世紀年(1900年)是一個閏年,而事實上它不是,而是2000年!

要檢查此操作,請嘗試在Excel中格式化單元格作爲日期,然後輸入1,它給出1 Jan 1900。現在輸入59,它給出28 Feb 190060給出29 Feb 1900(不是真實日期),然後61給出01 March 1900

所以......

switch (days) 
{ 
    case < 1: 
    // Not valid. Do whatever... 
    break; 
    case < 59: 
    DateTime date = new DateTime(1900, 1, 1).AddDays(days); 
    break; 
    default: 
    // Knock off the extra days caused by 29 Feb 1900 and 29 Feb 2000 
    DateTime date = new DateTime(1900, 1, 1).AddDays(days-2); 
    break; 
} 
+0

2000這是一個閏年。就像1600和2400一樣。所以你只有1900左右。 – 2012-08-15 12:01:15

+0

@亨克:謝謝!我確實知道這一點,但不知何故忘了。哈哈,我是個白癡!我會編輯我的答案... – 2012-08-15 12:02:55

2

如果你正在尋找的.Net核心FromOADate它不存在。

我分解了實現.Net Framework並創建了一個擴展方法。

 public static DateTime FromOADate(this double date) 
     { 
      return new DateTime(DoubleDateToTicks(date), DateTimeKind.Unspecified); 
     } 

     internal static long DoubleDateToTicks(double value) 
     { 
      if (value >= 2958466.0 || value <= -657435.0) 
       throw new ArgumentException("Not a valid value"); 
      long num1 = (long)(value * 86400000.0 + (value >= 0.0 ? 0.5 : -0.5)); 
      if (num1 < 0L) 
       num1 -= num1 % 86400000L * 2L; 
      long num2 = num1 + 59926435200000L; 
      if (num2 < 0L || num2 >= 315537897600000L) 
       throw new ArgumentException("Not a valid value"); 
      return num2 * 10000L; 
     } 

還需要測試它。