如何在C#中将此数字转换为格式为dd/mm/yyyy的日期? 41172等同于20/09/2012。
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相同的序列日期系统,并提供更大的兼容性。将1900年视为闰年也使用户更容易从一个程序移动工作表到另一个程序。
尽管在技术上可以纠正此行为,以便当前版本的Microsoft Excel不假定1900年是闰年,但这样做的缺点大于优点。
编辑:正如评论和其他答案中所提到的,DateTime.FromOADate
是一个更好的方法。如果有人取消接受此答案,我将删除它。(但是,在像.NET Core这样仍不支持FromOADate
的平台上,它仍然对使用这些平台的人很有用。)
我猜你想要:
DateTime date = new DateTime(1900, 1, 1).AddDays(days - 2);
(参见其他答案,了解为什么需要减去2.)
如果你正在寻找.Net Core中的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;
}
仍需要对其进行测试。
我在 MSDN 上看到了这个链接:http://msdn.microsoft.com/en-us/library/system.datetime.fromoadate.aspx,但我认为它是错误的。
真正的问题是 Excel 错误地认为世纪年(1900)是闰年,而实际上不是,但 2000 年是!
要检查这一点,请将 Excel 中的单元格格式设置为日期,然后输入 1
,它会显示 1900 年 1 月 1 日
。现在输入 59
,它会显示 1900 年 2 月 28 日
。 60
显示 1900 年 2 月 29 日
(不是真实日期),然后 61
显示 1900 年 3 月 1 日
。
所以...
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;
}