November 21, 2006 at 2:03 pm
So in my expirience I've found that the most accurate and fastest way of taking '2006-11-21 13:00:00' to '2006-11-21 00:00:00:000' has been...
SELECT DATEADD(dd, DATEDIFF(dd,0,@mydate), 0)
I was reveiwing some code in an application that I inherited that was malfunctioning, or rather doing what it was supposed to do based on some odd code.
the code I'm fixing uses the convert(datetime, cast(@mydate as int)) method getting a date at midnight. Unfortuantely I've noticed that datetimes after 1200 Noon end up converting to the next day. I know this is because of the cast(@mydate to int) part of the statement. I just want to know more of the why than yes this is what happens.
Example code
DECLARE @mydate datetime,
@mydate2 datetime
SELECT @mydate = '2006-11-21 11:00', @mydate2 = '2006-11-21 12:00'
SELECT CONVERT(datetime, CAST(@mydate AS INT)) AS convertedDate,
CAST(@mydate AS INT) AS CasttoInt,
DATEADD(dd, DATEDIFF(dd,0,@mydate), 0) AS correctMydateMinusTime
SELECT CONVERT(datetime, CAST(@mydate2 AS INT)) AS convertedDate,
CAST(@mydate2 AS INT) AS CasttoInt,
DATEADD(dd, DATEDIFF(dd,0,@mydate2), 0) AS correctMydateMinusTime
thanks in advance.
-Luke.
November 21, 2006 at 2:09 pm
The cast rounds the value. If you convert to float or decimal you will see 39040.5.
November 21, 2006 at 2:11 pm
This explains the "why" of what you're seeing:
http://vyaskn.tripod.com/searching_date_time_values.htm
November 21, 2006 at 2:26 pm
November 21, 2006 at 2:28 pm
The real question now... why did he design the code that way (business need)?
November 21, 2006 at 2:51 pm
>>why did he design the code that way
I usually see this alternative time stripping method coded using Floor() rather than cast as int. I expect it was a lack of understanding about casting and rounding up.
November 22, 2006 at 6:13 am
From what I can gather he was just dropping the time portion off so that when he displayed it on the page he could just show the date. Unfortunately, since he's no longer with the company I can't really tell for sure. I asked the users and they had never really noticed it until today... imagine that... The data is displayed correctly in another portion of the appliation, so I imagine it just something they've dealt with for the past 4 years the system has been in production.
anyhow, the fix is simple I'll change it to the dateadd(datediff)) method, improve the speed and accuracy of the code and be done with it. I was just not remembering the decimal, and lack of decimal value for an int. I knew it had to be something with rounding and whatnot, I just couldn't rememeber why.
Thanks again guys!
November 22, 2006 at 1:03 pm
I'm woundering why if you just want to strip off the time you just can't use the convert function with the optional style argument. In this case 101 would be the prefered style. Such as the following:
DECLARE @mydate datetime,
@mydate2 datetime
SELECT @mydate = '2006-11-21 11:00', @mydate2 = '2006-11-21 12:00'
SELECT Convert(datetime,(convert(char(12),@mydate,101))) as correctMydateMinusTime
SELECT Convert(datetime,(convert(char(12),@mydate2,101))) as correctMydateMinusTime
November 22, 2006 at 1:36 pm
The issues are:
- performance
- locale safety
Testing over large data volumes will show that SELECT DATEADD(dd, DATEDIFF(dd,0,@mydate), 0) is the fastest way to strip off time.
Use of string converts can lead you into problems with localization and countries/regions with differing date formats.
November 24, 2006 at 4:48 pm
Actually, there is one method that's a few milliseconds faster over a million or so rows...
SELECT CAST(CAST(datecolumn-.5) AS INT) AS DATETIME)
As usual, please don't take my word for it... I have a million row test table called "BigTest" and I ran the following code against it...
--===== Declare a couple of operating variables for the test
DECLARE @MyDate DATETIME --Holds the result of a conversion to bypass display times
DECLARE @StartTime DATETIME --For measuring duration of each snippet
PRINT '===== Rounding method 2 ======'
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
SET @StartTime = GETDATE()
SELECT @MyDate=CAST(CAST((ADate - 0.5 ) AS INTEGER) AS DATETIME) FROM dbo.BigTest
PRINT STR(DATEDIFF(ms,@StartTime,GETDATE()),10) + ' Milliseconds'
PRINT ' '
PRINT '===== DateDiff/DateAdd method ======'
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
SET @StartTime = GETDATE()
SELECT @MyDate=DATEADD(dd,DATEDIFF(dd,0,ADate),0) FROM dbo.BigTest
PRINT STR(DATEDIFF(ms,@StartTime,GETDATE()),10) + ' Milliseconds'
PRINT ' '
PRINT '===== Rounding method 1 ======'
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
SET @StartTime = GETDATE()
SELECT @MyDate=CAST(ROUND(CAST(ADate AS FLOAT),0,1) AS DATETIME) FROM dbo.BigTest
PRINT STR(DATEDIFF(ms,@StartTime,GETDATE()),10) + ' Milliseconds'
PRINT ' '
PRINT '===== Convert method ================'
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
SET @StartTime = GETDATE()
SELECT @MyDate=CAST(CONVERT(CHAR(8),ADate,112) AS DATETIME) FROM dbo.BigTest
PRINT STR(DATEDIFF(ms,@StartTime,GETDATE()),10) + ' Milliseconds'
PRINT ' '
PRINT '===== Wrack''s Integer function ====='
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
SET @StartTime = GETDATE()
SELECT @MyDate=CAST(CAST(dbo.DateToDay(Adate) AS CHAR(8)) AS DATETIME) FROM dbo.BigTest
PRINT STR(DATEDIFF(ms,@StartTime,GETDATE()),10) + ' Milliseconds'
PRINT ' '
...and here's the run results...
===== Rounding method 2 ======
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
2390 Milliseconds
===== DateDiff/DateAdd method ======
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
2436 Milliseconds
===== Rounding method 1 ======
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
3360 Milliseconds
===== Convert method ================
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
5673 Milliseconds
===== Wrack's Integer function =====
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
14983 Milliseconds
--Jeff Moden
Change is inevitable... Change for the better is not.
Viewing 10 posts - 1 through 9 (of 9 total)
You must be logged in to reply to this topic. Login to reply