19

TimeSpan在我的数据库中保存一个(来自.NET)值,就像BIGINT在 SQL Server 中一样(保存 Ticks 属性)。我想知道如何将此BIGINT值转换为DATETIMESQL Server(而不是 .NET)中的值。有任何想法吗?

干杯

编辑:

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

在系统内部,一切都很好,不需要这种转换。但是,在 SQL Server 中执行随机查询时,很难理解TimeSpan. 因此,我传递Ticks值并DateTime返回 a 的函数将以小时、分钟和秒为单位给出它所TimeSpan代表的数量。

4

7 回答 7

25

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

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

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

于 2015-03-20T19:45:05.787 回答
19

我不确定几秒钟的准确度,但您可以尝试以下操作:

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')
于 2010-02-22T19:27:08.427 回答
8

您可以使用Pavel Gatilov 博客中的此函数将 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()
于 2012-11-29T23:16:23.357 回答
5

ATimeSpan不是日期,因此保存它可能会在将来引起混乱。

您是否有理由不能简单地将刻度保存到整数字段而不改变其含义?

于 2010-02-22T18:50:00.390 回答
2

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

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

然后,您可以将其除以 60 以获得分钟等。

于 2010-02-22T19:18:12.143 回答
1

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

SELECT(CAST(CAST(CAST ('02/02/10' AS datetime) AS BIGINT) AS datetime)) 

你得到 2010-02-02 00:00:00.000

于 2010-02-22T18:55:10.613 回答
0

我自己想通了:

288,000,000,000 个刻度代表 8 小时,因此以下SELECT返回一个虚拟日期,其中指定了小时数...

SELECT DATEADD(millisecond, 288000000000/10000, CAST('1900-01-01' AS DATETIME))

感谢大家的努力。

于 2010-02-22T19:19:35.890 回答