Qual è il tipo SQL corretto per archiviare un intervallo di tempo .Net con valori> 24:00:00?


196

Sto cercando di memorizzare un .Net TimeSpanin SQL Server 2008 R2.

EF Code First sembra suggerire che dovrebbe essere archiviato come Time(7)in SQL.

Tuttavia, TimeSpanin .Net può gestire periodi più lunghi di 24 ore.

Qual è il modo migliore per gestire l'archiviazione .Net TimeSpanin SQL Server?


15
Lo sto usando per memorizzare la lunghezza degli eventi ricorrenti. Quindi volevo catturare la durata dell'evento indipendentemente dalla data
GraemeMiller,


1
Correlato non duplicato. Li ho scritti entrambi. Uno riguarda il codice in primo luogo e come modificare la mappa per TimeSpan. L'altro riguarda l'effettivo tipo .Net Mappatura da Timespan a SQL.
GraemeMiller,

Risposte:


222

Lo memorizzerei nel database come a BIGINTe memorizzerei il numero di tick (es. TimeSpan.Ticks Proprietà ).

In questo modo, se volessi ottenere un oggetto TimeSpan quando lo recuperavo, avrei potuto farlo TimeSpan.FromTicks (valore) che sarebbe facile.


3
Come gestiresti i calcoli in sql diciamo che dovevi calcolare quante ore contiene?
Peter,

10
Probabilmente sarei convertire lo zecche in un oggetto momento come questo: SELECT CAST(DATEADD(MILLISECOND, @Ticks/CAST(10000 AS BIGINT), '1900-01-01') AS TIME). La '1900-01-01'data non importa, ovviamente, è solo la terza variabile richiesta dalla DATEADD(...)funzione. Ricorda che ci sono 100 nanosecondi in un segno di spunta, ma se lo usi DATEADD(NANOSECOND...probabilmente otterrai un overflow, quindi usando i millisecondi. Ricorda anche che dovresti verificare questo fatto usando C # TimeSpan.TicksPerMillisecond(dovrebbe essere 10000) per essere sicuro.
Tom Chantler,

Un'opzione è memorizzarlo come una stringa, quindi è possibile caricarlo utilizzando TimeSpan.Parse (testo). non ideale dal punto di vista dimensionale o query SQL, ma può essere analizzato in TSQL se necessario
Walter Vehoeven,

65

Grazie per il consiglio. Poiché non esiste un equivalente in SQL Server. Ho semplicemente creato un secondo campo che ha convertito il TimeSpan in tick e l'ho memorizzato nel DB. Ho quindi impedito di memorizzare il TimeSpan

public Int64 ValidityPeriodTicks { get; set; }

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

6
Anche per chiunque utilizzi EF Core - in 2.1 è possibile utilizzare conversioni di valori e TimeSpanToTicksConverter per mappare in modo trasparente le
finestre temporali

30

Se non è necessario archiviare più di 24 ore, è possibile archiviare solo il tempo , dal momento che SQL Server 2008 e versioni successive sono il mapping

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

Non sono necessarie conversioni se è necessario archiviare solo 24 ore o meno.

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

Ma , se si desidera archiviare più di 24 ore, sarà necessario memorizzarle in tick, recuperare i dati e quindi convertirli in TimeSpan. Per esempio

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

23
Come dice l'OP, il tipo di dati "time" in SQL Server supporta solo fino a 24 ore, vuole archiviare> 24 ore
MichelZ

11
Inoltre, TimeSpan (.NET) può essere negativo, mentre Time (SQL Server) non può.
Edward

11
C'è una grande differenza tra un tempo e una durata. L'ora rappresenta l'ora di un determinato giorno mentre la durata è la differenza tra due momenti. Confrontalo con una posizione (tempo) e distanza (durata).
Ramon de Klein,

3
^ Esatto. - Il Timetipo SQL non è pensato per rappresentare una durata, ma la parte Time di un valore DateTime; è una scelta terribile per TimeSpan.
BrainSlugs83


7

So che questa è una vecchia domanda, ma volevo assicurarmi che venissero notate un paio di altre opzioni.

Poiché non è possibile memorizzare un intervallo di tempo superiore a 24 ore in un campo del tipo di dati time sql; un paio di altre opzioni potrebbero essere.

  1. Utilizzare un varchar (xx) per memorizzare la ToString del TimeSpan. Il vantaggio di questo è che la precisione non deve essere inserita nel tipo di dati o nel calcolo (secondi contro millisecondi contro giorni contro quindicine) Tutto ciò che devi fare è usare TimeSpan.Parse / TryParse. Questo è quello che vorrei fare.

  2. Utilizzare una seconda data, datetime o datetimeoffset, che memorizza il risultato della prima data + intervallo di tempo. La lettura dal db è una questione di TimeSpan x = SecondDate - FirstDate. L'uso di questa opzione ti proteggerà per le altre librerie di accesso ai dati non .NET che accedono agli stessi dati ma non comprendono TimeSpans; nel caso abbiate un tale ambiente.


1
L'opzione 2 sembra che possa tornare utile di tanto in tanto. thx
rahicks,

3

Per essere coerenti con quella che è probabilmente la fonte più probabile di generazione di un intervallo di tempo (calcolando la differenza di 2 volte o data-ora), potresti voler archiviare un .NET TimeSpancome SQL ServerDateTime .

Questo perché in SQL Server, la differenza di 2 DateTime( Casta Float'e poi di Castnuovo a DateTime) è semplicemente aDateTime parente rispetto al 1 gennaio 1900. Es. Una differenza di +0,1 secondi sarebbe 1 gennaio 1900 00: 00: 00,100 e -0,1 secondi sarebbe 31 dicembre 1899 23: 59: 59,900.

Per convertire un .NET TimeSpanin un tipo di SQL Server DateTime, devi prima convertirlo in un DateTimetipo di .NET aggiungendolo a un DateTime1 gennaio 1900. Naturalmente, quando lo leggi in .NET da SQL Server, dovresti prima leggilo in un .NET DateTimee poi sottrai il 1 gennaio 1900 da esso per convertirlo in un .NET TimeSpan.

Per i casi in cui i periodi di tempo vengono generati da SQL Server DateTimee all'interno di SQL Server (ovvero tramite T-SQL) e SQL Server è precedente al 2016, a seconda dell'intervallo e delle esigenze di precisione, potrebbe non essere pratico archiviarli come millisecondi (per non parlare Ticks) perché il IntTipo restituito da DateDiff(rispetto a BigIntda SS 2016 + DateDiff_Big) trabocca dopo ~ 24 giorni di millisecondi e ~ 67 anni. di secondi. Considerando che, questa soluzione gestirà gli intervalli di tempo con precisione fino a 0,1 secondi e da -147 a +8.099 anni.

AVVERTENZE:

  1. Ciò funzionerebbe solo se la differenza rispetto al 1 gennaio 1900 comporterebbe un valore compreso nell'intervallo di un tipo di SQL Server DateTime(1 gennaio 1753-31 dicembre 9999, ovvero da -147 a +8.099 anni). Non dobbiamo preoccuparci troppo sul TimeSpanlato .NET , poiché può contenere da ~ 29 k a +29 k anni. Non ho menzionato il tipo di SQL Server DateTime2(il cui intervallo, sul lato negativo, è molto maggiore di quello di SQL Server DateTime), perché: a) non può essere convertito in un valore numerico tramite un intervallo semplice Casteb) DateTimedovrebbe essere sufficiente per la stragrande maggioranza dei casi d'uso.

  2. Le DateTimedifferenze di SQL Server calcolate con il metodo Castda - a Float- e - e indietro non sembrano essere accurate oltre 0,1 secondi.


Ho dimenticato di aver letto questa Q molto meno che ho scritto questa A, e stavo cercando di nuovo una A. Ho iniziato a leggere questa A e ho pensato: (Wow, questa è la risposta migliore finora!). : D
Tom,

3

Esistono diversi modi per presentare un intervallo di tempo nel database.

tempo

Questo tipo di dati è supportato da SQL Server 2008 ed è il modo preferito per archiviare un file TimeSpan. Non è necessaria alcuna mappatura. Funziona bene anche con il codice SQL.

public TimeSpan ValidityPeriod { get; set; }

Tuttavia, come indicato nella domanda originale, questo tipo di dati è limitato a 24 ore.

datetimeoffset

Il datetimeoffsettipo di dati viene mappato direttamente a System.DateTimeOffset. È usato per esprimere l'offset tra a datetime/ datetime2e UTC, ma puoi anche usarlo per TimeSpan.

Tuttavia, poiché il tipo di dati suggerisce un semantico molto specifico, quindi dovresti considerare anche altre opzioni.

datetime / datetime2

Un approccio potrebbe essere quello di utilizzare i tipi datetimeo datetime2. Questo è il migliore negli scenari in cui è necessario elaborare direttamente i valori nel database, ad es. per visualizzazioni, stored procedure o report. Lo svantaggio è che è necessario sottrarre il valore DateTime(1900,01,01,00,00,00)dalla data per ripristinare la tempistica nella logica aziendale.

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

Un altro approccio potrebbe essere quello di convertire il TimeSpan in tick e utilizzare il biginttipo di dati. Tuttavia, questo approccio ha lo svantaggio di essere ingombrante da utilizzare nelle query SQL.

public long ValidityPeriod { get; set; }

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

varchar (N)

Questo è il migliore per i casi in cui il valore dovrebbe essere leggibile dall'uomo. È inoltre possibile utilizzare questo formato nelle query SQL utilizzando la CONVERT(datetime, ValidityPeriod)funzione. A seconda della precisione richiesta, saranno necessari da 8 a 25 caratteri.

public string ValidityPeriod { get; set; }

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

Bonus: periodo e durata

Usando una stringa, puoi anche memorizzare i tipi di dati NodaTime , in particolare Duratione Period. Il primo è sostanzialmente lo stesso di un TimeSpan, mentre il secondo rispetta che alcuni giorni e mesi sono più lunghi o più brevi di altri (cioè gennaio ha 31 giorni e febbraio ha 28 o 29; alcuni giorni sono più lunghi o più brevi a causa dell'ora legale ). In tali casi, l'utilizzo di un TimeSpan è la scelta sbagliata.

È possibile utilizzare questo codice per convertire i periodi:

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)));
    }
}

E poi usalo come

public string ValidityPeriod { get; set; }

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

Mi piace molto NodaTimee spesso mi salva da bug insidiosi e molti mal di testa. Lo svantaggio qui è che non puoi davvero usarlo nelle query SQL e devi eseguire calcoli in memoria.

Tipo definito dall'utente CLR

Hai anche la possibilità di utilizzare un tipo di dati personalizzato e supportare TimeSpandirettamente una classe personalizzata . Vedere i tipi definiti dall'utente CLR per i dettagli.

Lo svantaggio qui è che il tipo di dati potrebbe non funzionare bene con SQL Reports. Inoltre, alcune versioni di SQL Server (Azure, Linux, Data Warehouse) non sono supportate.

Conversioni di valore

A partire da EntityFramework Core 2.1, hai la possibilità di utilizzare Conversioni di valori .

Tuttavia, quando si utilizza questo, EF non sarà in grado di convertire molte query in SQL, causando l'esecuzione in memoria delle query; potenzialmente trasferendo un sacco di dati alla tua applicazione.

Quindi, almeno per ora, potrebbe essere meglio non usarlo e mappare il risultato della query con Automapper .


1

In genere, memorizzo un TimeSpan come un bigint popolato con segni di spunta dalla proprietà TimeSpan.Ticks come suggerito in precedenza. È inoltre possibile memorizzare un TimeSpan come varchar (26) popolato con l'output di TimeSpan.ToString (). Le quattro funzioni scalari (ConvertFromTimeSpanString, ConvertToTimeSpanString, DateAddTicks, DateDiffTicks) che ho scritto sono utili per gestire TimeSpan sul lato SQL ed evitare gli hack che produrrebbero intervalli con limiti artificiali. Se riesci a memorizzare l'intervallo in un TimeSpan .NET, dovrebbe funzionare anche con queste funzioni. Inoltre, le funzioni consentono di lavorare con TimeSpans e tick da 100 nanosecondi anche quando si utilizzano tecnologie che non includono .NET Framework.

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 ---
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.