将.NET刻度转换为SQL Server DateTime

问题描述 投票:13回答:8

我在数据库中将TimeSpan(来自.NET)值保存为SQL Server中的BIGINT(保存Ticks属性)。我想知道如何在SQL Server(而不是.NET)中将此BIGINT值转换为DATETIME值。有什么想法吗?

欢呼声

编辑:

我正在使用NHibernate映射我拥有的TimeSpan属性,并且该属性保留了Ticks属性。我将它用于某个日期的相对小时(或分钟)控制。

在系统内部,一切正常,不需要这种转换。但是,在SQL Server中执行随机查询时,很难理解TimeSpan的持久形式。因此,我传递Ticks值并返回DateTime的函数将给出TimeSpan表示的小时,分​​钟和秒数。

sql-server-2005 nhibernate datetime timespan
8个回答
17
投票

我不确定秒的精确度,但是您可以尝试类似的操作:

Declare @TickValue bigint
Declare @Days float

Set @TickValue = 634024345696365272 
Select @Days = @TickValue * POWER(10.00000000000,-7) / 60 / 60 / 24

Select DATEADD(d, Cast(@Days As int), Cast('0001-01-01' As DATE)) 
    + Cast( (@Days - FLOOR(@Days)) As DateTime)

实际上,在SQL 2005中可用的另一种方法是注意,从0001-01-01到1900-01-01的滴答数是599266080000000000。使用该方法,您可以这样做:

Declare @TickOf19000101 bigint
Declare @TickValue bigint
Declare @Minutes float

Set @TickOf19000101  = 599266080000000000
Set @TickValue = DATEDIFF(mi, 0 ,CURRENT_TIMESTAMP) * Cast(60 As BigInt) 
                   * POWER(10.00000000000,7) + @TickOf19000101

Select @TickValue
Select @Minutes = (@TickValue - @TickOf19000101) * POWER(10.00000000000,-7) / 60

Select @Minutes
Select DATEADD(MI, @Minutes, '1900-01-01')

15
投票

我不是很了解SQL Server,但是今天我的一位同事遇到了同样的问题,我认为我找到了这样的解决方案:

CAST(([ticks] - 599266080000000000) / 10000000 / 24 / 60 / 60 AS datetime)

其中599266080000000000是01/01/1900 00:00:00的刻度值。


7
投票

您可以使用取自Pavel Gatilov's blog的此函数将服务器本地时间中的毫秒级精度的64位整数转换为日期时间值:

CREATE FUNCTION NetFxUtcTicksToDateTime
(
   @Ticks bigint
)
RETURNS datetime
AS
BEGIN

-- First, we will convert the ticks into a datetime value with UTC time
DECLARE @BaseDate datetime;
SET @BaseDate = '01/01/1900';

DECLARE @NetFxTicksFromBaseDate bigint;
SET @NetFxTicksFromBaseDate = @Ticks - 599266080000000000;
-- The numeric constant is the number of .Net Ticks between the System.DateTime.MinValue (01/01/0001) and the SQL Server datetime base date (01/01/1900)

DECLARE @DaysFromBaseDate int;
SET @DaysFromBaseDate = @NetFxTicksFromBaseDate / 864000000000;
-- The numeric constant is the number of .Net Ticks in a single day.

DECLARE @TimeOfDayInTicks bigint;
SET @TimeOfDayInTicks = @NetFxTicksFromBaseDate - @DaysFromBaseDate * 864000000000;

DECLARE @TimeOfDayInMilliseconds int;
SET @TimeOfDayInMilliseconds = @TimeOfDayInTicks / 10000;
-- A Tick equals to 100 nanoseconds which is 0.0001 milliseconds

DECLARE @UtcDate datetime;
SET @UtcDate = DATEADD(ms, @TimeOfDayInMilliseconds, DATEADD(d, @DaysFromBaseDate, @BaseDate));
-- The @UtcDate is already useful. If you need the time in UTC, just return this value.

-- Now, some magic to get the local time
RETURN @UtcDate + GETDATE() - GETUTCDATE();
END
GO

适合内联用法的替代代码:

DECLARE @Ticks bigint
set @Ticks = 634899090000000000
select DATEADD(ms, ((@Ticks - 599266080000000000) - 
   FLOOR((@Ticks - 599266080000000000) / 864000000000) * 864000000000) / 10000,
   DATEADD(d, (@Ticks - 599266080000000000) / 864000000000, '01/01/1900')) +
   GETDATE() - GETUTCDATE()

5
投票

TimeSpan不是日期,照这样保存可能会在将来引起混乱。

是否有不能简单地将刻度保存到整数字段并且不改变其含义的原因?


2
投票

在.NET中获取TimeSpan.TicksPerSecond的值(只需写下来即可。)>

然后,在您的SQL中,您可以将滴答计数除以该数字,得到秒数。

然后您可以将其除以60得到分钟,依此类推。


1
投票

您应该能够使用SQL Server内置的CAST函数。


0
投票

我已经自己弄清楚了:


0
投票

这里的大多数答案都不正确或令人困惑。我发现这是简短,甜美且完全准确的内容:

© www.soinside.com 2019 - 2024. All rights reserved.