如何在c#中将double值转换为DateTime?

17

我有一个双精度数值为40880.051388,如果我在Excel中将其粘贴到单元格中并应用以下自定义格式“m/d/yyyy h:mm”,那么我会得到"12/3/2011 1:14"

如何在C#中进行此解析/转换?我不知道这个值是距某个检查点的毫秒数,比如纪元时间,还是它遵循某种特定的准备好的格式,但Excel是如何得出这个特定值的?在C#中是否也可以做到?

我已经尝试使用Visual Studio中的TimeSpanDateTime和其他类似的东西,但没有取得任何进展。


2
也许这个链接可以帮到你:http://stackoverflow.com/questions/8829171/conversion-of-double-to-datetime-always-fails - Felipe Oriani
如果你不知道这个数字实际上代表什么,那么你怎么知道 Excel 格式化它的选择是正确的呢?在考虑如何编程之前,你应该知道这个数字实际上对应的日期,并确定它在逻辑上代表什么。 - Servy
5个回答

35

看起来你正在使用旧的OLE自动化日期。请使用

DateTime.FromOADate(myDouble)

2
这是Joel(不是我)关于一些信息的版本:http://www.joelonsoftware.com/items/2008/02/19.html - Joel Rondeau
@JoelRondeau 我刚刚发现DateTime.FromOADate只能提供1毫秒的精度。如果你关心的话,可以获得更高的精度。请参见我在旧帖子中的新答案 - Jeppe Stig Nielsen

4

可以尝试以下方法:

double d = 40880.051388 ;
DateTime dt = DateTime.FromOADate(d);

3

尝试使用var dateTime = DateTime.FromOADate(40880.051388);

如果您需要将其格式化为字符串,请使用dateTime.ToString("M/d/yyyy H:mm", CultureInfo.InvariantCulture)。这将给您24小时制的字符串(将H更改为h可获得12小时制)。

如果您需要比FromOADate提供的精度更高(1000倍或更多),请参见我在另一个主题中的答案


2
该值是距离1899年12月30日的偏移天数。因此您需要:
new DateTime(1899, 12, 30).AddDays(40880.051388)

你说得对,我忘记了他们使用1899年12月30日作为起点。Excel的人很奇怪。已修复。 - Cory Nelson
1
@EricLippert非常正确。但是它也会失去精度,因为参数会被四舍五入/截断到最近的毫秒。您知道框架为什么总是丢弃这样的精度吗?这毫无意义。我在另一个帖子中写了一个长答案,希望您想阅读。[https://dev59.com/bW865IYBdhLWcg3wnf9t#13922172] - Jeppe Stig Nielsen

0

以下简单的代码将会运行

DateTime.FromOADate(myDouble)

然而,如果性能至关重要,它可能无法运行得足够快。这个操作非常依赖于处理器,因为OLE自动化日期格式的日期范围始于1899年12月30日,而DateTime始于公历0001年1月1日。

FromOADate调用DoubleDateToTicks函数,使用myDouble作为唯一参数。这将返回滴答数,并使用此值创建一个未指定DateTimeKind的新DateTime。

大部分工作都由mscorlib中的DoubleDateToTicks函数完成。这包括在double的值为NaN时抛出ArgumentException的代码,以及根据您的确切需求进行各种性能优化的多种方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接