2012-08-15 183 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; 
     } 

还需要测试它。