views:

284

answers:

6

Hello,

When I select from SQL Server, I want to get a date, but omit the millisecond value, and I want it to be as a date type. So if I have a value 1/1/2009 1:23:11.923, I want to omit the millisecond but retain the date type, so that it will be the value 1/1/2009 1:23:11.000 (I know you really can't omit the millisecond value with a date, just want it to be zero).

Is there a function in SQL Server to do this? Or do I have to write my own function? Again, I don't want it as a varchar type, but a datetime type.

Thanks.

+3  A: 
SELECT  GETDATE(),
        CONVERT(DATETIME, CONVERT(VARCHAR(MAX), GETDATE(), 120), 120)
Quassnoi
Isn't the `, 120` on the outermost CONVERT redundant?
OMG Ponies
@OMGPonies: let's just upvote each other :)
Quassnoi
the CONVERT format style (120) is ignored when converting from string to datetime. BOL says: _the style of the date format used to convert datetime or smalldatetime data to character data (nchar, nvarchar, char, varchar, nchar, or nvarchar data types); or the string format used to convert float, real, money, or smallmoney data to character data (nchar, nvarchar, char, varchar, nchar, or nvarchar data types). When style is NULL, the result returned is also NULL._
KM
@KM: in this very case, the argument is redundant indeed since this very format leaves no chance for ambiguity. However, it's not always the case. Just run this: `SELECT CONVERT(DATETIME, '01/02/2010', 101), CONVERT(DATETIME, '01/02/2010', 103)`.
Quassnoi
@KM: I think you have a very outdated version of Books Online (possibly 2000 or 2005 RTM)? There have been several updates since then, you should make sure your local copy is up to date. Observe the changed wording in the CAST and CONVERT topic: http://msdn.microsoft.com/en-us/library/ms187928%28SQL.90%29.aspx - @Quassnoi is absolutely correct, in fact I was going to post the exact same example he did.
Aaron Bertrand
@Quassnoi: VARCHAR(MAX) might be a little much, no? :-)
Aaron Bertrand
Converting number to string, and then back again is highly inefficient. Use the datetime functions provided within SQL
TFD
+7  A: 

Use:

SELECT CONVERT(DATETIME, CONVERT(VARCHAR(19), GETDATE(), 120))

This:

CONVERT(VARCHAR(19), GETDATE(), 120)

...omits the milliseconds, returning a VARCHAR. So you CAST/CONVERT that into a DATETIME in order to work with the desired data type.

See this link for a list of various date/time formats you can work with.

OMG Ponies
Converting number to string, and then back again is highly inefficient. Use the datetime functions provided within SQL
TFD
+3  A: 

try this

 declare @DATE datetime
 select @DATE = '1/1/2009 1:23:11.923'



 SELECT convert(datetime,CONVERT(char(35),@DATE,120))

or with date functions only

DECLARE @DATE DATETIME
SELECT @DATE = '1/1/2009 1:23:11.923'

SELECT DATEADD(SECOND, DATEDIFF(SECOND, 39000, @DATE), 39000)
SQLMenace
Converting number to string, and then back again is highly inefficient. Use the datetime functions provided within SQL
TFD
you will get an overflow with with milliseconds
SQLMenace
All you have to do is subtract the milliseconds w/ DATEADD(). No adding from 0 required.
Peter
Added a date function method
SQLMenace
+2  A: 
DATEADD(SECOND, DATEDIFF(SECOND, 0, < your datetime column >), 0)

May need to change the 0 to something else to prevent an overflow error. Don't have a SQL Server at hand right now to verify.

While this method does not appear to be intuitive at first sight, have a look here for the rationale behind it: http://www.karaszi.com/SQLServer/info_datetime.asp#GettingRidOfTimePortion

EDIT:see comments

Frank Kalis
Frank, I think you want SECOND, not MILLISECOND.
Aaron Bertrand
Lol. Good catch, Aaron. Changed it.
Frank Kalis
+3  A: 

If you don't want to use string conversions, here's a solution:

DECLARE @TheDate datetime, @Today datetime
SET @TheDate = GetDate()

SET @Today = DateAdd(dd, DateDiff(dd, 0, @TheDate), 0)
SELECT DateAdd(s, DateDiff(s, @Today, @TheDate), @Today)
David B
+2  A: 

Use DATETIME2, a new datatype in SQL Server 2008 that supports fractional precision:

SELECT
  CONVERT(DATETIME2(0),GETDATE()) [yyyy-mm-dd hh:mm:ss]
, CONVERT(DATETIME2(1),GETDATE()) [yyyy-mm-dd hh:mm:ss.f]
, CONVERT(DATETIME2(2),GETDATE()) [yyyy-mm-dd hh:mm:ss.ff]
, CONVERT(DATETIME2(3),GETDATE()) [yyyy-mm-dd hh:mm:ss.fff]
, CONVERT(DATETIME2(4),GETDATE()) [yyyy-mm-dd hh:mm:ss.ffff]
, CONVERT(DATETIME2(5),GETDATE()) [yyyy-mm-dd hh:mm:ss.fffff]
, CONVERT(DATETIME2(6),GETDATE()) [yyyy-mm-dd hh:mm:ss.ffffff]
, CONVERT(DATETIME2(7),GETDATE()) [yyyy-mm-dd hh:mm:ss.fffffff]

Alternatively, on SQL 2005 and eariler:

SELECT
  original  = GETDATE()
, [floor]   = DATEADD(ms,-DATEPART(ms,GETDATE()),GETDATE())
, [ceiling] = DATEADD(ms,1000-DATEPART(ms,GETDATE()),GETDATE())
, [rounded] = DATEADD(ms,CASE WHEN DATEPART(ms,GETDATE()) < 500 THEN 0 ELSE 1000 END-DATEPART(ms,GETDATE()),GETDATE())

This is a bit faster than converting to and from a string representation.

Peter
Wow, that's great, but unfortunately, SQL Server 2005 :-(
Brian
Added a SQL 2005 version.
Peter
Brian, I removed the SQL Server 2008 tag. If you need a solution that only works on 2005, you shouldn't tag with a version that is not correct.
Aaron Bertrand