Human Readable DateDiff
The DateDiff function is frustrating. You can only get a single element (seconds, minutes, hours, days, months or years). At work we currently use the DateDiff function for DTS statistics. Its handy cause you can get an idea of where your spending your time durring DTS execution. However, it’s not very reasonable. I wanted a function to return Human Readable text…not just the number of seconds or minutes between dates.
WireLust has a good article here. However this function uses DATEDIFF and this function has its flaws.
Take a look at this…
SELECT dbo.DateDiffHumanReadable('11:50:48.000', '12:12:45.000', 's')
RESULT
----------------------
1h
(1 row(s) affected)
The code below is my implementation of a HumanReadable DateDiff. There are imperfections with the DateDiff function. My function gets the total seconds between 2 dates and derives the Seconds, Minutes, Hours and Days. Since we use the function for DTS Execution metrics we don’t need anything more than hours…but I included days cause it was easy to do.
My function would return this…
SELECT dbo.DateDiffHumanReadable('11:50:48.000', '12:12:45.000'c)
RESULT
----------------------
21m 57s
(1 row(s) affected)
So here it is the Improved Human Readable DateDiff…
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: ADAM CLARK -- Create date: 3/12/2009 -- Description: Generates a human readable -- difference between two dates -- ============================================= CREATE FUNCTION [dbo].[dateDiffHumanReadable] ( @dateStart DATETIME, @dateEnd DATETIME ) RETURNS VARCHAR(200) AS BEGIN DECLARE @diffAsString VARCHAR(200), @TotalSeconds INT DECLARE @day INT, @hour INT, @minute INT, @second INT SET @second = 0 SET @minute = 0 SET @hour = 0 SET @day = 0 SET @diffAsString = '' IF (@dateStart IS NULL OR @dateEnd IS NULL) BEGIN RETURN @diffAsString END SET @TotalSeconds = DATEDIFF(ss, @dateStart, @dateEnd); IF (@TotalSeconds < 0) BEGIN RETURN 'ERR: StartDate After EndDate' END -- seconds IF @TotalSeconds < 60 BEGIN SET @second = @TotalSeconds END ELSE BEGIN SET @minute = @TotalSeconds / 60 SET @second = @TotalSeconds - (@minute * 60) -- minutes IF @minute > 59 BEGIN SET @hour = @minute / 60 SET @minute = @minute - (@hour * 60) --hours IF @hour > 23 BEGIN SET @day = @hour / 24 SET @hour = @hour - (@day * 24) END END END -- Build the output string IF @day <> 0 BEGIN SET @diffAsString = @diffAsString + CAST(@day AS VARCHAR(10)) + 'd ' + CAST(@hour AS VARCHAR(10)) + 'h ' + CAST(@minute AS VARCHAR(10)) + 'm ' + CAST(@second AS VARCHAR(10)) + 's ' END ELSE BEGIN IF @hour <> 0 BEGIN SET @diffAsString = @diffAsString + CAST(@hour AS VARCHAR(10)) + 'h ' + CAST(@minute AS VARCHAR(10)) + 'm ' + CAST(@second AS VARCHAR(10)) + 's ' END ELSE BEGIN IF @minute <> 0 BEGIN SET @diffAsString = @diffAsString + CAST(@minute AS VARCHAR(10)) + 'm ' + CAST(@second AS VARCHAR(10)) + 's ' END ELSE BEGIN IF @second <> 0 BEGIN SET @diffAsString = @diffAsString + CAST(@second AS VARCHAR(10)) + 's ' END ELSE BEGIN SET @diffAsString = '0s' END END END END RETURN @diffAsString END GO
hey, good to see someone is making use of my code I post.
What is the problem with the datediff function that makes you want to use it less?
I had originally coded the function more like yours where you datediff to get the smallest increment first (ms in my case) but this is problematic because it gets an overflow error when the number is too big. With ‘ms’, it will overflow at like 10 years, with ’s’ it takes almost 100 years. My particular application I needed to have accuracy to ‘ms’ for up to 20 years.
As an example, dateDiffHumanReadableAdam is your version and overflows on this large date span.
DECLARE @birthday DATETIME
SET @birthday = ‘6/2/1910 16:00:00′
PRINT dbo.dateDiffHumanReadable(@birthday, GETDATE(), ‘ms’)
PRINT dbo.dateDiffHumanReadableAdam(@birthday, GETDATE())
Honestly, I needed a function to process date differences that are no more than a week long…honestly not more than a day long. If I have a DTS package that runs longer than a day…I’m in trouble. As for why I didn’t want to use your function…or DATEDIFF for that matter…check the post. Your function returns 1h for time span that should be 21m 57s.
Ahhh. good catch. I didn’t see your comment about it returning 1d, which is incorrect.
I was under the mistaken thinking that
SELECT DATEDIFF(hour, ‘11:50:48.000′, ‘12:12:45.000′)
would return 0, when in fact it returns 1.
I updated my function to use DATEDIFF to lop off the year, then use a ms calculation to count up like yours. This way it works for long time spans as well as short. I should spend some time testing though to see if there are any other problems with it.