我假设.NET中的 DateTime.FromOADate和MS SQL 中的 DateTime 的工作方式相同。
但是,给定值:41640
DateTime.FromOADate(值)返回:2014-01-01
CAST(值AS DATETIME)返回:2014-01-03
这是由于不同的开始日期导致的预期行为,还是不正确?
我假设.NET中的 DateTime.FromOADate和MS SQL 中的 DateTime 的工作方式相同。
但是,给定值:41640
DateTime.FromOADate(值)返回:2014-01-01
CAST(值AS DATETIME)返回:2014-01-03
这是由于不同的开始日期导致的预期行为,还是不正确?
这是 T-SQL 中 2014 年 1 月的第三天:
SELECT CAST(41640 AS DATETIME)
这是 .NET 中 2014 年 1 月的第一天:
DateTime dt = DateTime.FromOADate(41640)
原因记录在 MSDN 中:
“零”日期是1900-01-01
基准日期, 1899 年 12 月 30 日午夜
01/01/1900
所以和之间有两天的差异 12/30/1899
。
要对此进行调查,您必须先查看基准日期,
在 MSSQLprint CAST(0 AS DATETIME)
中会输出:
1900 年 1 月 1 日上午 12:00
在 C# .NetConsole.WriteLine(DateTime.FromOADate(0));
中将输出:
1899 年 12 月 30 日凌晨 12:00:00
所以你可以看到 2 个基准日期之间有2 天的差异。这就是为什么你面临这样的问题。
OLE 自动化日期(又名“OADates”)用于与 COM 接口兼容,并用于通过 VBA 与 Microsoft Excel 等进行通信。您不应该在与 SQL Server 通信时使用它们。只需返回本机 SQL date
、datetime
或datetime2
键入您的查询并将其转换为DateTime
.NET 代码中的 a 。
DateTime dt = (DateTime) myDataReader["FooDateTime"];
正如其他人所提到的,SQL Server 时代与 OLE 自动化时代不同。OLE 自动化日期也有一些带有负值的古怪行为,而且 1900 年 3 月 1 日之前的日期可能使用一个时代12/30/1899
或12/31/1899
取决于哪个程序正在使用它。SQL Server 使用1/1/1900
.
和许多 Windows 和 .NET 类型一样,纪元并不固定为 UTC,因此您还必须知道什么上下文时区信息也在起作用。DateTime
(尽管除非您注意该.Kind
属性,否则也会发生这种情况。)
SQL Server 的基准日期是 '19000101';尝试铸造 0。
据此: http: //msdn.microsoft.com/en-us/library/system.datetime.fromoadate.aspx FromOADate 开始于 1899-12-30