web-dev-qa-db-fra.com

Temps de calcul avec t-sql

Étant donné deux dates/heures:

@start_date = '2009-04-15 10:24:00.000'
@end_date = '2009-04-16 19:43:01.000'

Est-il possible de calculer le temps écoulé entre les deux dates dans le format suivant

1j 9h 19m

39
jdiaz

Vous pouvez obtenir la différence entre les deux dates quelle que soit la résolution souhaitée (dans votre exemple, minutes):

DATEDIFF(minute, @start_date, @end_date)

À partir de là, il suffit de diviser les minutes en heures et en heures en jours et de modifier le reste.

67
Rex M

Je sais que ce fil est ancien et que les participants d'origine ne regardent probablement plus, mais je suis tombé dessus et j'avais déjà écrit du code assez récemment pour faire quelque chose de très proche de ce que demande jdiaz. Le résultat est rendu sous forme de chaîne au format D: H: M: S.

La première étape serait d'obtenir le laps de temps en secondes:

DECLARE @ElapsedS INT
SET @ElapsedS = DATEDIFF(second, @start_date, @end_date)

Créez maintenant la fonction scalaire suivante:

CREATE FUNCTION [dbo].[udfTimeSpanFromSeconds]
(
    @Seconds int
)
RETURNS varchar(15)
AS
BEGIN
DECLARE 
    --Variable to hold our result
      @DHMS varchar(15)
    --Integers for doing the math
    , @Days int --Integer days
    , @Hours int --Integer hours
    , @Minutes int --Integer minutes
    --Strings for providing the display
    , @sDays varchar(5) --String days
    , @sHours varchar(2) --String hours
    , @sMinutes varchar(2) --String minutes
    , @sSeconds varchar(2) --String seconds

--Get the values using modulos where appropriate
SET @Hours = @Seconds/3600
SET @Minutes = (@Seconds % 3600) /60
SET @Seconds = (@Seconds % 3600) % 60

--If we have 24 or more hours, split the @Hours value into days and hours
IF @Hours > 23 
BEGIN
    SET @Days = @Hours/24
    SET @Hours = (@Hours % 24)
END
ELSE
BEGIN
    SET @Days = 0
END

--Now render the whole thing as string values for display
SET @sDays = convert(varchar, @Days)
SET @sHours = RIGHT('0' + convert(varchar, @Hours), 2)
SET @sMinutes = RIGHT('0' + convert(varchar, @Minutes), 2)
SET @sSeconds = RIGHT('0' + convert(varchar, @Seconds), 2)

--Concatenate, concatenate, concatenate
SET @DHMS =  @sDays + ':' + @sHours + ':' + @sMinutes + ':' + @sSeconds

RETURN @DHMS

END

Maintenant, insérez votre temps dans la fonction nouvellement créée:

SELECT TimeSpan = dbo.udfTimeSpanFromSeconds(@ElapsedS)

Devrait produire '1: 09: 19: 01'

27
stinkyP
CONVERT(varchar,(@end_date-@start_date),108)

Cela vous le donnera en tant que HH: MM: SS

À votre santé

14
Dom

DATEDIFF peut renvoyer des valeurs non intuitives. Par exemple, les deux dates ci-dessous diffèrent d'une seconde et pourtant DATEDIFF avec les paramètres ci-dessous et interprétés comme d'autres l'interprètent ci-dessus renvoie 1 année:

SELECT DATEDIFF (année, '2005-12-31 23:59:59', '2006-01-01 00:00:00')

Consultez la documentation MSDN de DATEDIFF pour comprendre son fonctionnement.

4
Paul S...

datiff (datepart, date1, date2);

La réponse de Rex est plus complète.

1
tpdi

Voici comment formater la date (50j 8h 35m) dans une requête 

Declare @Date1 as Datetime, @Date2 as Datetime
Set @Date1 = '2005-01-01 08:00:00'
Set @Date2 = '2005-02-20 16:35:30'

Select
CAST(DATEDIFF(Minute,@Date1, @Date2)/60/24 as Varchar(50)) ++ 'd ' ++ 
CAST((DATEDIFF(Minute,@Date1, @Date2)/60)-((DATEDIFF(Minute,@Date1, @Date2)/60/24)*24) as Varchar(50)) ++ 'h ' ++
CAST((DATEDIFF(Minute,@Date1, @Date2)) - (DATEDIFF(HOUR,@Date1, @Date2)*60) as Varchar(50)) ++ 'm' as FormattedDateDiff
0
Trevor Noel
DECLARE @FirstDate DATETIME, @SecondDate DATETIME, @result VARCHAR(MAX)
SELECT @FirstDate = '2017-03-01 09:54:00.637', @SecondDate = GETDATE()

DECLARE @Day INT,@Month INT,@Hour INT, @Minute INT,@TotalSeconds INT,@Year INT
SELECT @TotalSeconds = ABS(DATEDIFF(SECOND,@FirstDate,@SecondDate))

-- Standard values in seconds
DECLARE @YearSeconds INT, @MonthSeconds INT, @DaySeconds INT, @HourSeconds INT, @MinuteSeconds INT

SELECT  @MinuteSeconds = 60
SELECT  @HourSeconds = 60 * @MinuteSeconds 
SELECT  @DaySeconds = 24 * @HourSeconds
SELECT  @MonthSeconds = 30 * @DaySeconds
SELECT  @YearSeconds = 12 * @MonthSeconds

--SELECT @MinuteSeconds AS [Minutes], @HourSeconds AS [Hours], @DaySeconds AS [Day],@MonthSeconds AS [Month],@YearSeconds AS [Year]

IF @TotalSeconds < @MinuteSeconds
BEGIN
    SELECT @result = CAST(@TotalSeconds AS NVARCHAR(20)) + ' seconds ago' 
END
ELSE IF @TotalSeconds < @HourSeconds
BEGIN
    SELECT @result = CAST(ABS(DATEDIFF(MINUTE,@FirstDate,@SecondDate)) AS NVARCHAR(20)) + ' minutes ago' 
END
ELSE IF @TotalSeconds < @DaySeconds
BEGIN
    SELECT @result = CAST(ABS(DATEDIFF(HOUR,@FirstDate,@SecondDate)) AS     NVARCHAR(20)) + ' hours ago' 
END
ELSE IF @TotalSeconds < @MonthSeconds
BEGIN
    SELECT @result = CAST(ABS(DATEDIFF(DAY,@FirstDate,@SecondDate)) AS NVARCHAR(20)) + ' days ago' 
END
ELSE IF @TotalSeconds < @YearSeconds
BEGIN
    SELECT @result = CAST(ABS(DATEDIFF(MONTH,@FirstDate,@SecondDate)) AS NVARCHAR(20)) + ' months ago' 
END
ELSE IF @TotalSeconds > @YearSeconds
BEGIN
    SELECT @result = CAST(ABS(DATEDIFF(YEAR,@FirstDate,@SecondDate)) AS NVARCHAR(20)) + ' year ago' 
END


SELECT @result
0
Jignesh