C# 将 Double 转换为 DateTime?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11968570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting Double to DateTime?
提问by Paul
I have a .CSV file which I am reading into a C# program. In one of the columns, there is a date, but it is in the "general" format, so it shows up in the .CSV as a number. For example: 41172.
我有一个 .CSV 文件,我正在将其读入 C# 程序。在其中一列中,有一个日期,但它采用“常规”格式,因此它在 .CSV 中显示为数字。例如:41172。
How can I convert this number to a date with format dd/mm/yyyy in C#? 41172 is equivalent to 20/09/2012.
如何在 C# 中将此数字转换为格式为 dd/mm/yyyy 的日期?41172 相当于 20/09/2012。
采纳答案by Jon Skeet
EDIT: As noted in comments and other answers, DateTime.FromOADateis a much better approach. I'll remove this answer if it's ever unaccepted. (But, there are still platforms like .NET Core where FromOADateis not supported so it is still useful for people using these platforms.)
编辑:如评论和其他答案中所述,DateTime.FromOADate是一种更好的方法。如果它不被接受,我会删除这个答案。(但是,仍然有像 .NET Core 这样的平台FromOADate不受支持,因此对于使用这些平台的人来说它仍然有用。)
I suspect you want:
我怀疑你想要:
DateTime date = new DateTime(1900, 1, 1).AddDays(days - 2);
(See other answers for why you need to subtract 2.)
(有关为什么需要减去 2,请参阅其他答案。)
回答by Richard
The date format used by Excel is old, but is still supported by the DateTime.FromOADatefunction, which you can use to convert this number. It is defined as
Excel 使用的日期格式很旧,但仍受DateTime.FromOADate函数支持,您可以使用它来转换此数字。它被定义为
number of days before or after the base date, midnight, 30 December 1899
基准日期之前或之后的天数,1899 年 12 月 30 日午夜
回答by dash
To go from an DateTime in the "Excel Format" to a C# Date Time you can use the DateTime.FromOADatefunction.
要将“Excel 格式”中的日期时间转换为 C# 日期时间,您可以使用DateTime.FromOADate函数。
In your example above:
在你上面的例子中:
DateTime myDate = DateTime.FromOADate(41172);
To write it out for display in the desired format, use:
要将其写出以所需格式显示,请使用:
myDate.ToString("dd/MM/yyyy");
If you are wondering where the discrepancies in Excel's date handling come from, it's supposed to be on purpose:
如果您想知道 Excel 日期处理中的差异从何而来,那应该是故意的:
When Lotus 1-2-3 was first released, the program assumed that the year 1900 was a leap year even though it actually was not a leap year. This made it easier for the program to handle leap years and caused no harm to almost all date calculations in Lotus 1-2-3.
When Microsoft Multiplan and Microsoft Excel were released, they also assumed that 1900 was a leap year. This allowed Microsoft Multiplan and Microsoft Excel to use the same serial date system used by Lotus 1-2-3 and provide greater compatibility with Lotus 1-2-3. Treating 1900 as a leap year also made it easier for users to move worksheets from one program to the other.
Although it is technically possible to correct this behavior so that current versions of Microsoft Excel do not assume that 1900 is a leap year, the disadvantages of doing so outweigh the advantages.
当 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 年是闰年,但这样做的弊大于利。
回答by Tom Chantler
I've seen this from MSDN: http://msdn.microsoft.com/en-us/library/system.datetime.fromoadate.aspx, but I actually think it's wrong.
我从 MSDN 看到过这个:http: //msdn.microsoft.com/en-us/library/system.datetime.fromoadate.aspx,但我实际上认为这是错误的。
The real issue is that Excel erroneously supposes that the century year (1900) is a leap year, whereas in fact it was not, but 2000 WAS!
真正的问题是 Excel 错误地假设世纪年(1900 年)是闰年,而实际上它不是,而是 2000 年!
To check this out, try formatting a cell in Excel as Date and then enter 1and it gives 1 Jan 1900. Now enter 59and it gives 28 Feb 1900. 60gives 29 Feb 1900(not a real date) and then 61gives 01 March 1900.
要检查这一点,请尝试将 Excel 中的单元格格式化为日期,然后输入1并给出1 Jan 1900. 现在输入59,它给出28 Feb 1900. 60给出29 Feb 1900(不是真正的日期)然后61给出01 March 1900.
So...
所以...
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;
}
回答by Chandermani
In case you are looking for FromOADatein .Net Core it is not there.
如果您FromOADate在 .Net Core中寻找,它不存在。
I dissembled the implementation .Net Framework and created an extension method.
我拆解了 .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;
}
Still need to test it.
还是需要测试一下。

