SideBar    The Logical Puzzle
DOWNLOAD THE CODE:
Download the Code 94487.zip

Extracting Time Only
The techniques to extract only the time are based on logic that's similar to the logic used for extracting only the date. You zero the date portion, setting it to the base date. I'll start with a calculation that relies on the logic from the third technique in the previous section:

SELECT DATEADD(
  ms,
  DATEDIFF(
   ms,
   DATEADD(day,
     DATEDIFF(day, 0,
     GETDATE()), 0), --
     date only 
   GETDATE()),
  0);

Notice that the DATEDIFF function calculates the difference in terms of milliseconds between the date-only portion of the input date and the input date. Call it diff. The outer DATEADD function adds diff milliseconds to the base date (represented by the integer 0).

If you want accuracy in terms of seconds instead of milliseconds, simply specify a second datepart instead of millisecond (ms):

SELECT DATEADD(
  second,
  DATEDIFF(
     second, 
     DATEADD(day, DATEDIFF(day,
      0, GETDATE()), 0), -- date
      only 
     GETDATE()), 
  0);

Of course, you also have the option to use logic similar to the logic used in the first technique—except that here you'll convert the input value to CHAR(14) using style 114 (hh:mi:ss:mmm) if you're after an accuracy of milliseconds:

SELECT CAST( 
  CONVERT(CHAR(12), GETDATE(), 
     114) -- 'hh:mi:ss:mmm'
  AS DATETIME);

If you're after an accuracy of seconds, convert to CHAR(8). By doing so, you'll trim the milliseconds portion:

SELECT CAST( 
  CONVERT(CHAR(8), GETDATE(),
    114) -- 'hh:mi:ss:mmm'
  AS DATETIME);

Only the Beginning
I've discussed the storage format that SQL Server uses to store datetime values, focusing on challenges related to the fact that there's no separation between date and time. But this is only the beginning. There are so many more challenges related to datetime manipulation. I'll continue exploring those challenges in the coming months.

End of Article

Prev. page     1 [2]     next page -->



You must log on before posting a comment.

If you don't have a username & password, please register now.

Reader Comments

That is one of the most useful and informative articles that I've read on SQL Server. It provides so much insight into how datetime works that can be applied to solving other datetime/timestamp issues. I'm looking forward to seeing what comes next.

Paul Misoni

Article Rating 5 out of 5

x

jo.piene@siemens.com

Article Rating 5 out of 5

Very relevant information. Working with dates is an frequent need and the recommended code in this article will be put to use.

Gary

macgary12

Article Rating 5 out of 5

Name: Ashley Bryan

In your article "DATETIME Calculations, Part 1" (February 2007, InstantDoc ID 94487), you review three techniques for trimming the date value out of a DATETIME datatype. There is a fourth technique that I believe warrants consideration.

In the proposed fourth technique you start by casting the datetime value to a float. The date and time are now represented as a decimal value with the day to the left of the decimal and time to the right. You then apply the FLOOR function against the float value to get the first whole number less than the datetime decimal value. With the time portion of the datetime value zeroed out, you then cast the float value back to datetime. The result is the midnight datetime entry for the value submitted.

SELECT CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME);

Using the same performance test included with the article, I added this technique to compare the results. In a five run comparison, the fourth technique had performance comparable to the recommended third technique, and posted slightly better results than the that technique overall. I used the results of the worst performing technique (the first one) as the basis for the comparative percentages.

Technique #1 Technique #2 Technique #3 Technique #4 Run #1 2253 1253 1313 1313 Run #2 2207 1297 1317 1300 Run #3 2140 1183 1246 1250 Run #4 2250 1250 1316 1327 Run #5 2140 1220 1297 1264 Average 2198.00 1240.60 1297.80 1290.80 Comparison 100.00% 56.44% 59.04% 58.73% This fourth technique is a bit more intuitive and readable than the others, while maintaining good performance results. In addition, this technique can be used in other areas to help perform date range operations by using the CEILING function to find the next highest whole number from the value submitted.

...WHERE DBDATE >= CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME) AND DBDATE < CAST(CEILING(CAST(GETDATE() AS FLOAT)) AS DATETIME);

DianaMay

Article Rating 5 out of 5

Reply from Itzik: Hi Ashley,

This is a fairly simple and intuitive technique, and seems to perform well. I have to say that I’m usually reluctant to use floats because if their imprecise nature, especially in calculations that require complete accuracy. But I tested it with both midnight values and last possible accuracy unit (23:59:59.999) and it seems to work well.

Thanks for sharing, Itzik

DianaMay

Article Rating 5 out of 5

Itzik-

Inspired by your article, I thought that binary manipulation of a datetime value would offer the best performance when trimming the date or time part. I was unable to find a way to grab the date portion (bitwise operators, reverse function, etc.), but I did discover this statement that keeps the time portion, and which I believe would offer fantastic performance (and its simple!):

SELECT CAST(CAST(@dt AS varbinary(4)) AS datetime);

I also came across an interesting article at http://www.dbazine.com/db2/db2-disarticles/pelzer2 which you might find useful for the next parts of your series on datetime.

I look forward to you visiting Minneapolis! -Mike Smith

DianaMay

Article Rating 5 out of 5

Hi Mike,

Yes, this is a fast technique to extract the time only! You could use similar logic to extract the date only, but it requires some more manipulation, making it a bit cumbersome:

select cast(substring(cast(getdate() as binary(8)), 1, 4) + 0x00000000 as datetime)

Cheers, Itzik

DianaMay

Article Rating 5 out of 5

Quite interresting and useful but I am not getting the same drastic results: technique ms ----------- ----------- Technique 1 1830 Technique 2 1560 Technique 3 1733

2nd time: technique ms ----------- ----------- Technique 1 1747 Technique 2 1640 Technique 3 1547

[Itzik: this may naturally vary, though I tested this code on several machines and got ratios more similar to the ones I reported in the article. Thanks for sharing your stats.]

ericga

Article Rating 5 out of 5

Informative and concise

meklembl

Article Rating 5 out of 5

very useful - I like the third version using an integer value!!

Hughesy

Article Rating 5 out of 5

good examples made this very useful

dkrogers55

Article Rating 4 out of 5

interesting article,

Based on your technique to get the time part I 've made a shorter version : select dateadd(dd,-datediff(dd,0,getdate()),getdate()) Using your performance test script it seems to have the same performance as the original.

franky.piferoen@sde.Be

Article Rating 5 out of 5

Great!!! A real life-saver! THANKS!

kyris

Article Rating 5 out of 5

Easier TIME ONLY extraction

SELECT GETDATE() AS theFullDateTime, DATEADD(DAY, DATEDIFF(DAY, '19000101', GETDATE()), '19000101') AS theDateOnly, DATEADD(DAY, DATEDIFF(DAY, GETDATE(), '19000101'), GETDATE()) AS theTimeOnly

Pesomannen

Article Rating 4 out of 5

 
 

ADS BY GOOGLE