Answered by:
How to change date to End of Day?

Question
-
I want to convert a date value to the end of the day. For instance, '9/1/2010 3:45pm' --> '9/1/2010 11:59:59pm'. Is there a way to do that without a messy bunch of casts on individual date parts?Friday, September 3, 2010 1:12 PM
Answers
-
declare @mydate datetime set @mydate = '9/1/2010 3:59:59pm' select DATEADD(second,-1,datediff(dd,0,@mydate)+1)
- Marked as answer by Mantros Group Friday, September 3, 2010 1:37 PM
- Unmarked as answer by Kalman Toth Friday, September 3, 2010 2:26 PM
- Marked as answer by Mantros Group Friday, September 3, 2010 2:41 PM
Friday, September 3, 2010 1:29 PM -
You didn't read the blogs.
The solution for time related problems is to never use between, but rather
set @StartDate =getdate()
set @Tomorrow = dateadd(day,1+datediff(day,'19000101',@StartDate),'19000101') -- Tomorrow midnight
select * from myTable where DateField>=@StartDate and DateField <@Tomorrow
Premature optimization is the root of all evil in programming. (c) by Donald Knuth
Naomi Nosonovsky, Sr. Programmer-Analyst
My blog
EDITORIAL FOR THOSE THAT READ THIS POST IN THE FUTURE:Please pay attention to what Naomi has discussed. For general solutions I would not choose nor recommend the solution chosen by the person that posted the question. First, the date/time chosen is technically not the highest date/time possible which therefore means that it is not "End of Day". This is splitting hairs but it frequently does matter. I understand that this might not matter for this particular problem and therefore the solution chosen might work 100% of the time for the circumstance of this particular user.
I am also a believer in using the WHERE clause that is composed of inequalities as suggested by Naomi. Again, I would not choose nor recommend using a BETWEEN comparator for this purpose rather than inequalities for the current state of the SQL Server Query Optimizer.
where DateField>=@StartDate and DateField <@Tomorrow
This where clause outlines a good approach for date ranges using the datetime datatype when the range is for whole days:
+ This is intended for the datetime datatype and not for the date datatype
+ Use a greater than or less than comparator for the start date/time
+ Use the start date as the lower bound
+ Use a strictly less than comparator for the end date/time
+ Use the beginning of the NEXT DATE as the upper boundEDIT:
If you absolute MUST set a datetime datatype to the highest time possible on a particular date a good way of doing it is something like:
select dateadd(ms, -3, dateadd(day, datediff(day, 0, getdate()), 1) ) as End_Of_Day, dateadd(ms, -1, dateadd(day, datediff(day, 0, getdate()), 1) ) as Wrong_End_Of_Day /* -------- Output: -------- End_Of_Day End_Of_Day ----------------------- ----------------------- 2010-09-03 23:59:59.997 2010-09-04 00:00:00.000 */
Notice that you cannot decrement "tomorrow" by a millisecond to get the highest time of a given date because SQL Server stores time in the datetime datatype accurate only to the 1/300th of a second.
- Proposed as answer by Naomi N Friday, September 3, 2010 2:13 PM
- Marked as answer by Kalman Toth Friday, September 3, 2010 2:26 PM
Friday, September 3, 2010 2:05 PM
All replies
-
You need to use either cast, convert or one or more of the date handling functions.
Friday, September 3, 2010 1:18 PM -
Is this the cleanest its going to get?
CONVERT(Varchar,YEAR(@date)) +'/' + CONVERT(Varchar,MONTH(@date)) + '/' + CONVERT(Varchar,DAY(@date)) + ' 23:59'
Friday, September 3, 2010 1:25 PM -
We do have such function, but if you want to use it in Date between @Start and @EndOfDate, then it's an incorrect approach as you will miss records that happen close to midnight.
Take a look at these two blog posts
The ultimate guide to the datetime datatypes
Bad habits to kick : mis-handling date / range queries
and if you still would like to have such function after reading them, let me know and I'll dig for the code.
Premature optimization is the root of all evil in programming. (c) by Donald Knuth
Naomi Nosonovsky, Sr. Programmer-Analyst
My blogFriday, September 3, 2010 1:27 PM -
declare @mydate datetime set @mydate = '9/1/2010 3:59:59pm' select DATEADD(second,-1,datediff(dd,0,@mydate)+1)
- Marked as answer by Mantros Group Friday, September 3, 2010 1:37 PM
- Unmarked as answer by Kalman Toth Friday, September 3, 2010 2:26 PM
- Marked as answer by Mantros Group Friday, September 3, 2010 2:41 PM
Friday, September 3, 2010 1:29 PM -
Thanks Naom. In this particular case, the resolution of input records is 15 minutes, so range queries won't cause a problem. For elegance, I suppose I should BETWEEN it against the start of the next day, but wouldn't that be an even messier conversion?
SET @next = DATEADD(dd,1,@date)
SET @start_of_next_day = CONVERT(Varchar,YEAR(@next)) +'/' + CONVERT(Varchar,MONTH(@next)) + '/' + CONVERT(Varchar,DAY(@next))
Or is there an easier way?
Friday, September 3, 2010 1:32 PM -
I like it, thanks!Friday, September 3, 2010 1:37 PM
-
You didn't read the blogs.
The solution for time related problems is to never use between, but rather
set @StartDate =getdate()
set @Tomorrow = dateadd(day,1+datediff(day,'19000101',@StartDate),'19000101') -- Tomorrow midnight
select * from myTable where DateField>=@StartDate and DateField <@Tomorrow
Premature optimization is the root of all evil in programming. (c) by Donald Knuth
Naomi Nosonovsky, Sr. Programmer-Analyst
My blogFriday, September 3, 2010 1:40 PM -
You didn't read the blogs.
The solution for time related problems is to never use between, but rather
set @StartDate =getdate()
set @Tomorrow = dateadd(day,1+datediff(day,'19000101',@StartDate),'19000101') -- Tomorrow midnight
select * from myTable where DateField>=@StartDate and DateField <@Tomorrow
Premature optimization is the root of all evil in programming. (c) by Donald Knuth
Naomi Nosonovsky, Sr. Programmer-Analyst
My blog
EDITORIAL FOR THOSE THAT READ THIS POST IN THE FUTURE:Please pay attention to what Naomi has discussed. For general solutions I would not choose nor recommend the solution chosen by the person that posted the question. First, the date/time chosen is technically not the highest date/time possible which therefore means that it is not "End of Day". This is splitting hairs but it frequently does matter. I understand that this might not matter for this particular problem and therefore the solution chosen might work 100% of the time for the circumstance of this particular user.
I am also a believer in using the WHERE clause that is composed of inequalities as suggested by Naomi. Again, I would not choose nor recommend using a BETWEEN comparator for this purpose rather than inequalities for the current state of the SQL Server Query Optimizer.
where DateField>=@StartDate and DateField <@Tomorrow
This where clause outlines a good approach for date ranges using the datetime datatype when the range is for whole days:
+ This is intended for the datetime datatype and not for the date datatype
+ Use a greater than or less than comparator for the start date/time
+ Use the start date as the lower bound
+ Use a strictly less than comparator for the end date/time
+ Use the beginning of the NEXT DATE as the upper boundEDIT:
If you absolute MUST set a datetime datatype to the highest time possible on a particular date a good way of doing it is something like:
select dateadd(ms, -3, dateadd(day, datediff(day, 0, getdate()), 1) ) as End_Of_Day, dateadd(ms, -1, dateadd(day, datediff(day, 0, getdate()), 1) ) as Wrong_End_Of_Day /* -------- Output: -------- End_Of_Day End_Of_Day ----------------------- ----------------------- 2010-09-03 23:59:59.997 2010-09-04 00:00:00.000 */
Notice that you cannot decrement "tomorrow" by a millisecond to get the highest time of a given date because SQL Server stores time in the datetime datatype accurate only to the 1/300th of a second.
- Proposed as answer by Naomi N Friday, September 3, 2010 2:13 PM
- Marked as answer by Kalman Toth Friday, September 3, 2010 2:26 PM
Friday, September 3, 2010 2:05 PM -
You didn't read the blogs.
I already know the issues with BETWEEN. But as I already explained, in this particular case, its not a problem due to the time resolution on the dates involved. The original solution is therefore better.
Also, I believe Kent is wrong when he says the QO doesn't handle BETWEEN as well as inequalities, since last time I checked, BETWEENs were internally converted to inequalities before being fed to the QO.
Friday, September 3, 2010 2:41 PM -
You didn't read the blogs.
I already know the issues with BETWEEN. But as I already explained, in this particular case, its not a problem due to the time resolution on the dates involved. The original solution is therefore better.
Also, I believe Kent is wrong when he says the QO doesn't handle BETWEEN as well as inequalities, since last time I checked, BETWEENs were internally converted to inequalities before being fed to the QO.
The QO handles between just fine. Really, what I was getting at has more to do with older versions of the DB2 query optimizer rathern than the SQL server optimizer. I was advised several times that there might have been a time in DB2 in which the DB2 query optimizer gave preference to the BETWEEN comparator over inequalties. I did not mean that inequalties optimze better than between in MS SQL Server.Sorry that if that is what I conveyed. It was not intended that way.
Friday, September 3, 2010 2:46 PM -
What is the difference between the solution I posted and Rami's solution? Rami's solution uses + for adding 1 day to the date and that's also not advisable (it does work correctly with datetime, will not work with dates, so it's better to always use dateadd function when working with dates/datetimes). I don't see why would that solution be better if it has several holes in it even if it works for the particular case.
Premature optimization is the root of all evil in programming. (c) by Donald Knuth
Naomi Nosonovsky, Sr. Programmer-Analyst
My blogFriday, September 3, 2010 2:59 PM -
Thanks Naomi. Rami's solution is better in this particular case because it allows me to add one line to legacy code and fix the issue, rather than wading through nearly a hundred SPs of someone else's code changing BETWEENs to inequalities.
For new development, I always use inequalities. Your solution is better in the general case, I agree.
Friday, September 3, 2010 3:10 PM