24:00:00を超える値を持つ.Netタイムスパンを格納するための正しいSQLタイプは何ですか?


196

TimeSpanSQL Server 2008 R2に.Netを保存しようとしています。

EFコードファーストはTime(7)、SQL として保存する必要があることを示唆しているようです。

ただしTimeSpan、.Netでは24時間よりも長い期間を処理できます。

TimeSpanSQL Serverでの.Netの格納を処理する最良の方法は何ですか?


15
定期的なイベントの長さを保存するために使用しています。したがって、日付に
関係なく


1
関連は重複していません。両方書いた。1つは、Code FirstとTimeSpanのマップを変更する方法です。もう1つは、実際の.NetタイプのタイムスパンからSQLへのマッピングに関するものです。
GraemeMiller 2013

回答:


222

としてデータベースにBIGINT保存し、ティックの数を保存します(例:TimeSpan.Ticksプロパティ)。

このようにして、取得時にTimeSpanオブジェクトを取得したい場合は、TimeSpan.FromTicks(value)を実行するだけで簡単にできます。


3
SQLで計算をどのように処理しますか?
Peter

10
私はおそらくティックを次のような時間オブジェクトに変換します:SELECT CAST(DATEADD(MILLISECOND, @Ticks/CAST(10000 AS BIGINT), '1900-01-01') AS TIME)'1900-01-01'もちろん、日付は重要ではありません。これは、DATEADD(...)関数が必要とする3番目の変数にすぎません。ティックには100ナノ秒があることを覚えておいてください。ただし、使用DATEADD(NANOSECOND...するとオーバーフローが発生する可能性が高いため、ミリ秒を使用します。また、C#TimeSpan.TicksPerMillisecond(10000である必要があります)を使用してこの事実を確認してください。
Tom Chantler、2016年

オプションとして、それを文字列として保存し、TimeSpan.Parse(text)を使用してロードできます。サイズの観点やSQL
クエリ

65

アドバイスありがとうございます。SQLサーバーには同等のものがないため。TimeSpanをティックに変換する2番目のフィールドを作成し、それをDBに保存しました。次に、TimeSpanの保存を禁止しました

public Int64 ValidityPeriodTicks { get; set; }

[NotMapped]
public TimeSpan ValidityPeriod
{
    get { return TimeSpan.FromTicks(ValidityPeriodTicks); }
    set { ValidityPeriodTicks = value.Ticks; }
}

6
また、EF Coreを使用するすべての人にとって-2.1では、値変換とTimeSpanToTicksConverterを使用して、タイムスパンをデータベースのティックに透過的にマップできます
GraemeMiller

30

あなたは24時間以上を保存する必要がない場合は、単に保存することができ、時間を SQL Serverの2008年以来、以降マッピングがあります

time (SQL Server) <-> TimeSpan(.NET)

24時間以内に保存するだけでよい場合は、変換は必要ありません。

ソース:http : //msdn.microsoft.com/en-us/library/cc716729(v=vs.110).aspx

ただし、24時間を超えて格納する場合は、ティックで格納し、データを取得して、TimeSpanに変換する必要があります。例えば

int timeData = yourContext.yourTable.FirstOrDefault();
TimeSpan ts = TimeSpan.FromMilliseconds(timeData);

23
OPが言うように、SQL Serverの "time" DataTypeは最大24時間しかサポートしないため、24時間を
超え

11
また、TimeSpan(.NET)は負の値になる可能性がありますが、Time(SQL Server)は負の値にはなりません。
エドワード

11
時間と期間の間には大きな違いがあります。時間は特定の日の時間を表し、期間は2つの瞬間の差です。場所(時間)と距離(期間)と比較してください。
Ramon de Klein 2016年

3
^その通り。-SQL Timeタイプは期間を表すものではなく、DateTime値のTime部分です。それはひどい選択ですTimeSpan
BrainSlugs83 2017


7

これは古い質問であることはわかっていますが、他のいくつかのオプションが記載されていることを確認したかったのです。

24時間を超えるTimeSpanをtime sqlデータ型フィールドに格納することはできないため。他にもいくつかのオプションがあります。

  1. varchar(xx)を使用して、TimeSpanのToStringを格納します。この利点は、データ型や計算に精度をベイクする必要がないことです(秒対ミリ秒対日対2週間)。必要なのは、TimeSpan.Parse / TryParseを使用することだけです。これが私がすることです。

  2. 最初の日付+タイムスパンの結果を格納する2番目の日付、datetimeまたはdatetimeoffsetを使用します。データベースからの読み取りは、TimeSpan x = SecondDate-FirstDateの問題です。このオプションを使用すると、他の非.NETデータアクセスライブラリが同じデータにアクセスしても、TimeSpansを理解できなくなります。そのような環境がある場合に備えて。


1
オプション2は、時々重宝するかもしれません。thx
rahicks 2018

3

タイムスパン(2倍または日時の差の計算)を生成する最も可能性の高いソースと一致するようにするには、.NET TimeSpanをSQL Server DateTimeタイプとして保存します。

SQL Serverの、2の差があるためであるDateTime「(S Castに対するFloatS」と、次にCastバックにDateTime)単純にDateTime1月1日、1900年例に対して。+0.1秒の差は1900年1月1日00:00:00.100であり、-0.1秒の差は1899年12月31日23:59:59.900です。

.NET TimeSpanをSQL Server DateTimeタイプに変換するには、まず1900年1月1日の.NET DateTimeに追加して.NET タイプに変換しますDateTime。もちろん、SQL Serverから.NETにそれを読み込むときは、最初にそれを.NETに読み込んでDateTimeから、1900年1月1日を引いて.NET に変換しますTimeSpan

期間がSQL ServerからDateTime、およびSQL Server内で(つまりT-SQLを介して)生成され、SQL Serverが2016年より前のユースケースの場合、範囲と精度のニーズによっては、それらを保存するのは現実的ではない場合があります。 (ない言及ミリ秒などTicks)ので、Intタイプによって返されたDateDiff(対BigIntSS 2016 +さんからのDateDiff_Big)ミリ秒〜67歳の〜24日分後にオーバーフローします。秒の。一方、このソリューションは、0.1秒までの精度で-147〜+8,099年の時間範囲を処理します。

警告:

  1. これは、1900年1月1日との差がSQL ServerのDateTime種類(1753年1月1日から9999年12月31日、別名-147から+8,099年)の範囲内の値になる場合にのみ機能します。.NET TimeSpan側では、約29 k〜+29 k年間保持できるので、それほど心配する必要はありません。次の理由により、SQL ServerのDateTime2種類(マイナス側の範囲はSQL Serverの範囲よりもはるかに大きいDateTime)については触れませんでした。それはCast、a)単純な方法では数値に変換できず、b)DateTimeの範囲で十分であるためです。ユースケースの大部分。

  2. SQL ServerのDateTimeを経由して計算違いCastに- -はFloat-と-バック方法は0.1秒を超えて正確であるとは思われません。


このAを書くよりもずっとこのQを読むのを忘れて、もう一度Aを探していました。私はこのAを読み始め、自分自身で考えました(これが、これまでのところ最良の答えです!):D
トム

3

データベースにタイムスパンを表示する方法はいくつかあります。

時間

このデータ型はSQL Server 2008以降でサポートされており、を格納するために推奨される方法TimeSpanです。マッピングは必要ありません。また、SQLコードでもうまく機能します。

public TimeSpan ValidityPeriod { get; set; }

ただし、元の質問で述べたように、このデータ型は24時間に制限されています。

datetimeoffset

datetimeoffsetデータ型は、に直接マップSystem.DateTimeOffsetdatetime/ datetime2からUTCへのオフセットを表すために使用されますが、に使用することもできますTimeSpan

ただし、データ型は非常に具体的なセマンティクスを示唆しているため、他のオプションも検討する必要があります。

datetime / datetime2

1つのアプローチは、datetimeまたはdatetime2タイプを使用することです。これは、データベースの値を直接処理する必要があるシナリオに最適です。ビュー、ストアドプロシージャ、またはレポート用。欠点はDateTime(1900,01,01,00,00,00)、ビジネスロジックでタイムスパンを取得するために、日付から値を減算する必要があることです。

public DateTime ValidityPeriod { get; set; }

[NotMapped]
public TimeSpan ValidityPeriodTimeSpan
{
    get { return ValidityPeriod - DateTime(1900,01,01,00,00,00); }
    set { ValidityPeriod = DateTime(1900,01,01,00,00,00) + value; }
}

bigint

別のアプローチは、TimeSpanをティックに変換し、bigintデータ型を使用することです。ただし、このアプローチには、SQLクエリで使用するのが面倒であるという欠点があります。

public long ValidityPeriod { get; set; }

[NotMapped]
public TimeSpan ValidityPeriodTimeSpan
{
    get { return TimeSpan.FromTicks(ValidityPeriod); }
    set { ValidityPeriod = value.Ticks; }
}

varchar(N)

これは、人間が値を読み取れるようにする必要がある場合に最適です。CONVERT(datetime, ValidityPeriod)関数を利用して、SQLクエリでこの形式を使用することもできます。必要な精度に応じて、8〜25文字が必要になります。

public string ValidityPeriod { get; set; }

[NotMapped]
public TimeSpan ValidityPeriodTimeSpan
{
    get { return TimeSpan.Parse(ValidityPeriod); }
    set { ValidityPeriod = value.ToString("HH:mm:ss"); }
}

ボーナス:期間と期間

文字列を使用して、NodaTimeデータ型、特にDurationandを格納することもできますPeriod。最初のものは基本的にTimeSpanと同じですが、後者はいくつかの日と月が他のものより長いか短いかを尊重します(つまり、1月は31日、2月は28または29です。夏時間のためにいくつかの日は長いまたは短いです。 )。このような場合、TimeSpanを使用するのは間違った選択です。

このコードを使用して、期間を変換できます。

using NodaTime;
using NodaTime.Serialization.JsonNet;

internal static class PeriodExtensions
{
    public static Period ToPeriod(this string input)
    {
        var js = JsonSerializer.Create(new JsonSerializerSettings());
        js.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
        var quoted = string.Concat(@"""", input, @"""");
        return js.Deserialize<Period>(new JsonTextReader(new StringReader(quoted)));
    }
}

そしてそれを次のように使います

public string ValidityPeriod { get; set; }

[NotMapped]
public Period ValidityPeriodPeriod
{
    get => ValidityPeriod.ToPeriod();
    set => ValidityPeriod = value.ToString();
}

私は本当に好きでNodaTime、それはしばしば私をトリッキーなバグとたくさんの頭痛から救います。ここでの欠点は、SQLクエリで実際に使用できず、メモリ内で計算を行う必要があることです。

CLRユーザー定義型

また、カスタムデータ型を使用して、カスタムTimeSpanクラスを直接サポートするオプションもあります。詳細については、CLRユーザー定義型を参照してください。

ここでの欠点は、データ型がSQLレポートで適切に動作しない可能性があることです。また、SQL Serverの一部のバージョン(Azure、Linux、Data Warehouse)はサポートされていません。

値の変換

EntityFramework Core 2.1以降、値の変換を使用するオプションがあります。

ただし、これを使用すると、EFは多くのクエリをSQL に変換できなくなり、クエリがメモリ内で実行されます。大量のデータをアプリケーションに転送する可能性があります。

したがって、少なくとも現時点では、それを使用せずに、クエリ結果をAutomapperでマップするだけの方がよいでしょう。


1

通常、以前に提案したように、TimeSpanは、TimeSpan.Ticksプロパティからの目盛りが入力されたbigintとして格納されます。TimeSpan.ToString()の出力が入力されたvarchar(26)としてTimeSpanを格納することもできます。私が書いた4つのスカラー関数(ConvertFromTimeSpanString、ConvertToTimeSpanString、DateAddTicks、DateDiffTicks)は、SQL側でTimeSpanを処理し、人為的に範囲を制限するハックを回避するのに役立ちます。間隔を.NET TimeSpanに保存できる場合は、これらの関数でも機能するはずです。さらに、これらの関数を使用すると、.NET Frameworkを含まないテクノロジを使用している場合でも、TimeSpansと100ナノ秒のティックを操作できます。

DROP FUNCTION [dbo].[DateDiffTicks]
GO

DROP FUNCTION [dbo].[DateAddTicks]
GO

DROP FUNCTION [dbo].[ConvertToTimeSpanString]
GO

DROP FUNCTION [dbo].[ConvertFromTimeSpanString]
GO

SET ANSI_NULLS OFF
GO

SET QUOTED_IDENTIFIER OFF
GO

-- =============================================
-- Author:      James Coe
-- Create date: 2011-05-23
-- Description: Converts from a varchar(26) TimeSpan string to a bigint containing the number of 100 nanosecond ticks.
-- =============================================
/*
    [-][d.]hh:mm:ss[.fffffff] 

    "-" 
     A minus sign, which indicates a negative time interval. No sign is included for a positive time span.

    "d" 
     The number of days in the time interval. This element is omitted if the time interval is less than one day. 

    "hh" 
     The number of hours in the time interval, ranging from 0 to 23. 

    "mm" 
     The number of minutes in the time interval, ranging from 0 to 59. 

    "ss" 
     The number of seconds in the time interval, ranging from 0 to 59. 

    "fffffff" 
     Fractional seconds in the time interval. This element is omitted if the time interval does not include 
     fractional seconds. If present, fractional seconds are always expressed using seven decimal digits.
    */
CREATE FUNCTION [dbo].[ConvertFromTimeSpanString] (@timeSpan varchar(26))
RETURNS bigint
AS
BEGIN
    DECLARE @hourStart int
    DECLARE @minuteStart int
    DECLARE @secondStart int
    DECLARE @ticks bigint
    DECLARE @hours bigint
    DECLARE @minutes bigint
    DECLARE @seconds DECIMAL(9, 7)

    SET @hourStart = CHARINDEX('.', @timeSpan) + 1
    SET @minuteStart = CHARINDEX(':', @timeSpan) + 1
    SET @secondStart = CHARINDEX(':', @timespan, @minuteStart) + 1
    SET @ticks = 0

    IF (@hourStart > 1 AND @hourStart < @minuteStart)
    BEGIN
        SET @ticks = CONVERT(bigint, LEFT(@timespan, @hourstart - 2)) * 864000000000
    END
    ELSE
    BEGIN
        SET @hourStart = 1
    END

    SET @hours = CONVERT(bigint, SUBSTRING(@timespan, @hourStart, @minuteStart - @hourStart - 1))
    SET @minutes = CONVERT(bigint, SUBSTRING(@timespan, @minuteStart, @secondStart - @minuteStart - 1))
    SET @seconds = CONVERT(DECIMAL(9, 7), SUBSTRING(@timespan, @secondStart, LEN(@timeSpan) - @secondStart + 1))

    IF (@ticks < 0)
    BEGIN
        SET @ticks = @ticks - @hours * 36000000000
    END
    ELSE
    BEGIN
        SET @ticks = @ticks + @hours * 36000000000
    END

    IF (@ticks < 0)
    BEGIN
        SET @ticks = @ticks - @minutes * 600000000
    END
    ELSE
    BEGIN
        SET @ticks = @ticks + @minutes * 600000000
    END

    IF (@ticks < 0)
    BEGIN
        SET @ticks = @ticks - @seconds * 10000000.0
    END
    ELSE
    BEGIN
        SET @ticks = @ticks + @seconds * 10000000.0
    END

    RETURN @ticks
END
GO

-- =============================================
-- Author:      James Coe
-- Create date: 2011-05-23
-- Description: Converts from a bigint containing the number of 100 nanosecond ticks to a varchar(26) TimeSpan string.
-- =============================================
/*
[-][d.]hh:mm:ss[.fffffff] 

"-" 
 A minus sign, which indicates a negative time interval. No sign is included for a positive time span.

"d" 
 The number of days in the time interval. This element is omitted if the time interval is less than one day. 

"hh" 
 The number of hours in the time interval, ranging from 0 to 23. 

"mm" 
 The number of minutes in the time interval, ranging from 0 to 59. 

"ss" 
 The number of seconds in the time interval, ranging from 0 to 59. 

"fffffff" 
 Fractional seconds in the time interval. This element is omitted if the time interval does not include 
 fractional seconds. If present, fractional seconds are always expressed using seven decimal digits.
*/
CREATE FUNCTION [dbo].[ConvertToTimeSpanString] (@ticks bigint)
RETURNS varchar(26)
AS
BEGIN
    DECLARE @timeSpanString varchar(26)

    IF (@ticks < 0)
    BEGIN
        SET @timeSpanString = '-'
    END
    ELSE
    BEGIN
        SET @timeSpanString = ''
    END

    -- Days
    DECLARE @days bigint

    SET @days = FLOOR(ABS(@ticks / 864000000000.0))

    IF (@days > 0)
    BEGIN
        SET @timeSpanString = @timeSpanString + CONVERT(varchar(26), @days) + '.'
    END

    SET @ticks = ABS(@ticks % 864000000000)
    -- Hours
    SET @timeSpanString = @timeSpanString + RIGHT('0' + CONVERT(varchar(26), FLOOR(@ticks / 36000000000.0)), 2) + ':'
    SET @ticks = @ticks % 36000000000
    -- Minutes
    SET @timeSpanString = @timeSpanString + RIGHT('0' + CONVERT(varchar(26), FLOOR(@ticks / 600000000.0)), 2) + ':'
    SET @ticks = @ticks % 600000000
    -- Seconds
    SET @timeSpanString = @timeSpanString + RIGHT('0' + CONVERT(varchar(26), FLOOR(@ticks / 10000000.0)), 2)
    SET @ticks = @ticks % 10000000

    -- Fractional Seconds
    IF (@ticks > 0)
    BEGIN
        SET @timeSpanString = @timeSpanString + '.' + LEFT(CONVERT(varchar(26), @ticks) + '0000000', 7)
    END

    RETURN @timeSpanString
END
GO

-- =============================================
-- Author:      James Coe
-- Create date: 2011-05-23
-- Description: Adds the specified number of 100 nanosecond ticks to a date.
-- =============================================
CREATE FUNCTION [dbo].[DateAddTicks] (
    @ticks bigint
    , @starting_date datetimeoffset
    )
RETURNS datetimeoffset
AS
BEGIN
    DECLARE @dateTimeResult datetimeoffset

    IF (@ticks < 0)
    BEGIN
        -- Hours
        SET @dateTimeResult = DATEADD(HOUR, CEILING(@ticks / 36000000000.0), @starting_date)
        SET @ticks = @ticks % 36000000000
        -- Seconds
        SET @dateTimeResult = DATEADD(SECOND, CEILING(@ticks / 10000000.0), @dateTimeResult)
        SET @ticks = @ticks % 10000000
        -- Nanoseconds
        SET @dateTimeResult = DATEADD(NANOSECOND, @ticks * 100, @dateTimeResult)
    END
    ELSE
    BEGIN
        -- Hours
        SET @dateTimeResult = DATEADD(HOUR, FLOOR(@ticks / 36000000000.0), @starting_date)
        SET @ticks = @ticks % 36000000000
        -- Seconds
        SET @dateTimeResult = DATEADD(SECOND, FLOOR(@ticks / 10000000.0), @dateTimeResult)
        SET @ticks = @ticks % 10000000
        -- Nanoseconds
        SET @dateTimeResult = DATEADD(NANOSECOND, @ticks * 100, @dateTimeResult)
    END

    RETURN @dateTimeResult
END
GO

-- =============================================
-- Author:      James Coe
-- Create date: 2011-05-23
-- Description:  Gets the difference between two dates in 100 nanosecond ticks.
-- =============================================
CREATE FUNCTION [dbo].[DateDiffTicks] (
    @starting_date datetimeoffset
    , @ending_date datetimeoffset
    )
RETURNS bigint
AS
BEGIN
    DECLARE @ticks bigint
    DECLARE @days bigint
    DECLARE @hours bigint
    DECLARE @minutes bigint
    DECLARE @seconds bigint

    SET @hours = DATEDIFF(HOUR, @starting_date, @ending_date)
    SET @starting_date = DATEADD(HOUR, @hours, @starting_date)
    SET @ticks = @hours * 36000000000
    SET @seconds = DATEDIFF(SECOND, @starting_date, @ending_date)
    SET @starting_date = DATEADD(SECOND, @seconds, @starting_date)
    SET @ticks = @ticks + @seconds * 10000000
    SET @ticks = @ticks + CONVERT(bigint, DATEDIFF(NANOSECOND, @starting_date, @ending_date)) / 100

    RETURN @ticks
END
GO

--- BEGIN Test Harness ---
SET NOCOUNT ON

DECLARE @dateTimeOffsetMinValue datetimeoffset
DECLARE @dateTimeOffsetMaxValue datetimeoffset
DECLARE @timeSpanMinValueString varchar(26)
DECLARE @timeSpanZeroString varchar(26)
DECLARE @timeSpanMaxValueString varchar(26)
DECLARE @timeSpanMinValueTicks bigint
DECLARE @timeSpanZeroTicks bigint
DECLARE @timeSpanMaxValueTicks bigint
DECLARE @dateTimeOffsetMinMaxDiffTicks bigint
DECLARE @dateTimeOffsetMaxMinDiffTicks bigint

SET @dateTimeOffsetMinValue = '0001-01-01T00:00:00.0000000+00:00'
SET @dateTimeOffsetMaxValue = '9999-12-31T23:59:59.9999999+00:00'
SET @timeSpanMinValueString = '-10675199.02:48:05.4775808'
SET @timeSpanZeroString = '00:00:00'
SET @timeSpanMaxValueString = '10675199.02:48:05.4775807'
SET @timeSpanMinValueTicks = -9223372036854775808
SET @timeSpanZeroTicks = 0
SET @timeSpanMaxValueTicks = 9223372036854775807
SET @dateTimeOffsetMinMaxDiffTicks = 3155378975999999999
SET @dateTimeOffsetMaxMinDiffTicks = -3155378975999999999

-- TimeSpan Conversion Tests
PRINT 'Testing TimeSpan conversions...'

DECLARE @convertToTimeSpanStringMinTicksResult varchar(26)
DECLARE @convertFromTimeSpanStringMinTimeSpanResult bigint
DECLARE @convertToTimeSpanStringZeroTicksResult varchar(26)
DECLARE @convertFromTimeSpanStringZeroTimeSpanResult bigint
DECLARE @convertToTimeSpanStringMaxTicksResult varchar(26)
DECLARE @convertFromTimeSpanStringMaxTimeSpanResult bigint

SET @convertToTimeSpanStringMinTicksResult = dbo.ConvertToTimeSpanString(@timeSpanMinValueTicks)
SET @convertFromTimeSpanStringMinTimeSpanResult = dbo.ConvertFromTimeSpanString(@timeSpanMinValueString)
SET @convertToTimeSpanStringZeroTicksResult = dbo.ConvertToTimeSpanString(@timeSpanZeroTicks)
SET @convertFromTimeSpanStringZeroTimeSpanResult = dbo.ConvertFromTimeSpanString(@timeSpanZeroString)
SET @convertToTimeSpanStringMaxTicksResult = dbo.ConvertToTimeSpanString(@timeSpanMaxValueTicks)
SET @convertFromTimeSpanStringMaxTimeSpanResult = dbo.ConvertFromTimeSpanString(@timeSpanMaxValueString)

-- Test Results
SELECT 'Convert to TimeSpan String from Ticks (Minimum)' AS Test
    , CASE 
        WHEN @convertToTimeSpanStringMinTicksResult = @timeSpanMinValueString
            THEN 'Pass'
        ELSE 'Fail'
        END AS [Test Status]
    , @timeSpanMinValueTicks AS [Ticks]
    , CONVERT(varchar(26), NULL) AS [TimeSpan String]
    , CONVERT(varchar(26), @convertToTimeSpanStringMinTicksResult) AS [Actual Result]
    , CONVERT(varchar(26), @timeSpanMinValueString) AS [Expected Result]
UNION ALL
SELECT 'Convert from TimeSpan String to Ticks (Minimum)' AS Test
    , CASE 
        WHEN @convertFromTimeSpanStringMinTimeSpanResult = @timeSpanMinValueTicks
            THEN 'Pass'
        ELSE 'Fail'
        END AS [Test Status]
    , NULL AS [Ticks]
    , @timeSpanMinValueString AS [TimeSpan String]
    , CONVERT(varchar(26), @convertFromTimeSpanStringMinTimeSpanResult) AS [Actual Result]
    , CONVERT(varchar(26), @timeSpanMinValueTicks) AS [Expected Result]
UNION ALL
SELECT 'Convert to TimeSpan String from Ticks (Zero)' AS Test
    , CASE 
        WHEN @convertToTimeSpanStringZeroTicksResult = @timeSpanZeroString
            THEN 'Pass'
        ELSE 'Fail'
        END AS [Test Status]
    , @timeSpanZeroTicks AS [Ticks]
    , CONVERT(varchar(26), NULL) AS [TimeSpan String]
    , CONVERT(varchar(26), @convertToTimeSpanStringZeroTicksResult) AS [Actual Result]
    , CONVERT(varchar(26), @timeSpanZeroString) AS [Expected Result]
UNION ALL
SELECT 'Convert from TimeSpan String to Ticks (Zero)' AS Test
    , CASE 
        WHEN @convertFromTimeSpanStringZeroTimeSpanResult = @timeSpanZeroTicks
            THEN 'Pass'
        ELSE 'Fail'
        END AS [Test Status]
    , NULL AS [Ticks]
    , @timeSpanZeroString AS [TimeSpan String]
    , CONVERT(varchar(26), @convertFromTimeSpanStringZeroTimeSpanResult) AS [Actual Result]
    , CONVERT(varchar(26), @timeSpanZeroTicks) AS [Expected Result]
UNION ALL
SELECT 'Convert to TimeSpan String from Ticks (Maximum)' AS Test
    , CASE 
        WHEN @convertToTimeSpanStringMaxTicksResult = @timeSpanMaxValueString
            THEN 'Pass'
        ELSE 'Fail'
        END AS [Test Status]
    , @timeSpanMaxValueTicks AS [Ticks]
    , CONVERT(varchar(26), NULL) AS [TimeSpan String]
    , CONVERT(varchar(26), @convertToTimeSpanStringMaxTicksResult) AS [Actual Result]
    , CONVERT(varchar(26), @timeSpanMaxValueString) AS [Expected Result]
UNION ALL
SELECT 'Convert from TimeSpan String to Ticks (Maximum)' AS Test
    , CASE 
        WHEN @convertFromTimeSpanStringMaxTimeSpanResult = @timeSpanMaxValueTicks
            THEN 'Pass'
        ELSE 'Fail'
        END AS [Test Status]
    , NULL AS [Ticks]
    , @timeSpanMaxValueString AS [TimeSpan String]
    , CONVERT(varchar(26), @convertFromTimeSpanStringMaxTimeSpanResult) AS [Actual Result]
    , CONVERT(varchar(26), @timeSpanMaxValueTicks) AS [Expected Result]

-- Ticks Date Add Test
PRINT 'Testing DateAddTicks...'

DECLARE @DateAddTicksPositiveTicksResult datetimeoffset
DECLARE @DateAddTicksZeroTicksResult datetimeoffset
DECLARE @DateAddTicksNegativeTicksResult datetimeoffset

SET @DateAddTicksPositiveTicksResult = dbo.DateAddTicks(@dateTimeOffsetMinMaxDiffTicks, @dateTimeOffsetMinValue)
SET @DateAddTicksZeroTicksResult = dbo.DateAddTicks(@timeSpanZeroTicks, @dateTimeOffsetMinValue)
SET @DateAddTicksNegativeTicksResult = dbo.DateAddTicks(@dateTimeOffsetMaxMinDiffTicks, @dateTimeOffsetMaxValue)

-- Test Results
SELECT 'Date Add with Ticks Test (Positive)' AS Test
    , CASE 
        WHEN @DateAddTicksPositiveTicksResult = @dateTimeOffsetMaxValue
            THEN 'Pass'
        ELSE 'Fail'
        END AS [Test Status]
    , @dateTimeOffsetMinMaxDiffTicks AS [Ticks]
    , @dateTimeOffsetMinValue AS [Starting Date]
    , @DateAddTicksPositiveTicksResult AS [Actual Result]
    , @dateTimeOffsetMaxValue AS [Expected Result]
UNION ALL
SELECT 'Date Add with Ticks Test (Zero)' AS Test
    , CASE 
        WHEN @DateAddTicksZeroTicksResult = @dateTimeOffsetMinValue
            THEN 'Pass'
        ELSE 'Fail'
        END AS [Test Status]
    , @timeSpanZeroTicks AS [Ticks]
    , @dateTimeOffsetMinValue AS [Starting Date]
    , @DateAddTicksZeroTicksResult AS [Actual Result]
    , @dateTimeOffsetMinValue AS [Expected Result]
UNION ALL
SELECT 'Date Add with Ticks Test (Negative)' AS Test
    , CASE 
        WHEN @DateAddTicksNegativeTicksResult = @dateTimeOffsetMinValue
            THEN 'Pass'
        ELSE 'Fail'
        END AS [Test Status]
    , @dateTimeOffsetMaxMinDiffTicks AS [Ticks]
    , @dateTimeOffsetMaxValue AS [Starting Date]
    , @DateAddTicksNegativeTicksResult AS [Actual Result]
    , @dateTimeOffsetMinValue AS [Expected Result]

-- Ticks Date Diff Test
PRINT 'Testing Date Diff Ticks...'

DECLARE @dateDiffTicksMinMaxResult bigint
DECLARE @dateDiffTicksMaxMinResult bigint

SET @dateDiffTicksMinMaxResult = dbo.DateDiffTicks(@dateTimeOffsetMinValue, @dateTimeOffsetMaxValue)
SET @dateDiffTicksMaxMinResult = dbo.DateDiffTicks(@dateTimeOffsetMaxValue, @dateTimeOffsetMinValue)

-- Test Results
SELECT 'Date Difference in Ticks Test (Min, Max)' AS Test
    , CASE 
        WHEN @dateDiffTicksMinMaxResult = @dateTimeOffsetMinMaxDiffTicks
            THEN 'Pass'
        ELSE 'Fail'
        END AS [Test Status]
    , @dateTimeOffsetMinValue AS [Starting Date]
    , @dateTimeOffsetMaxValue AS [Ending Date]
    , @dateDiffTicksMinMaxResult AS [Actual Result]
    , @dateTimeOffsetMinMaxDiffTicks AS [Expected Result]
UNION ALL
SELECT 'Date Difference in Ticks Test (Max, Min)' AS Test
    , CASE 
        WHEN @dateDiffTicksMaxMinResult = @dateTimeOffsetMaxMinDiffTicks
            THEN 'Pass'
        ELSE 'Fail'
        END AS [Test Status]
    , @dateTimeOffsetMaxValue AS [Starting Date]
    , @dateTimeOffsetMinValue AS [Ending Date]
    , @dateDiffTicksMaxMinResult AS [Actual Result]
    , @dateTimeOffsetMaxMinDiffTicks AS [Expected Result]

PRINT 'Tests Complete.'
GO
--- END Test Harness ---
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.