I know this is a old post but wanted to share my answer. This builds on @hbrowser response. Here is what I've come up with. This will round up or down to the nearest 15 minutes.
SELECT DATEADD(MINUTE, ROUND(DATEDIFF(MINUTE, 0, GETDATE()) / 15.0, 0) * 15, 0);
By doing this logic inline, rather than inside a user defined function, over large recordsets you should experience greater performance.
You can change the way rounding occurs by swapping the ROUND
function to use FLOOR
or CAST expr AS INT
to always round down or use CEILING
to always round up.
Your individual use case will determine what style of rounding you may need to use.
The following script can be used to observe the differences offered by the different rounding techniques:
NOTE: to simplify the output each result has been casted to TIME(0), this is only done to simplify the output for this particular example.
DECLARE @SequenceStart SmallDateTime = CAST(GETDATE() AS Date);
DECLARE @SequenceEnd SmallDateTime = DateAdd(HOUR, 2, @SequenceStart); -- Recursive CTEs should always have an upper limit
DECLARE @SequenceIntMins INT = 5; -- increment by 5 to show the difference with rounding
WITH TimeSequence([Time]) as
(
SELECT @SequenceStart as [Time]
UNION ALL
SELECT DateAdd(MINUTE, 5, [Time]) FROM TimeSequence
WHERE [Time] <= @SequenceEnd
)
SELECT [Time] = Cast([Time] as TIME(0))
, Rounded = CAST(DATEADD(MINUTE, ROUND(DATEDIFF(MINUTE, 0, [Time]) / 15.0, 0) * 15, 0) as TIME(0))
, Casted = CAST(DATEADD(MINUTE, CAST(DATEDIFF(MINUTE, 0, [Time]) / 15.0 AS INT) * 15, 0) as TIME(0))
, Floored = CAST(DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, [Time]) / 15.0) * 15, 0) as TIME(0))
, Ceilinged = CAST(DATEADD(MINUTE, CEILING(DATEDIFF(MINUTE, 0, [Time]) / 15.0) * 15, 0) as TIME(0))
FROM TimeSequence OPTION ( MaxRecursion 1000);
-- MaxRecursion may be neccessary if you change the interval or end of the sequence
Time Rounded Casted Floored Ceilinged
00:00:00 00:00:00 00:00:00 00:00:00 00:00:00
00:05:00 00:00:00 00:00:00 00:00:00 00:15:00
00:10:00 00:15:00 00:00:00 00:00:00 00:15:00
00:15:00 00:15:00 00:15:00 00:15:00 00:15:00
00:20:00 00:15:00 00:15:00 00:15:00 00:30:00
00:25:00 00:30:00 00:15:00 00:15:00 00:30:00
00:30:00 00:30:00 00:30:00 00:30:00 00:30:00
00:35:00 00:30:00 00:30:00 00:30:00 00:45:00
00:40:00 00:45:00 00:30:00 00:30:00 00:45:00
00:45:00 00:45:00 00:45:00 00:45:00 00:45:00
00:50:00 00:45:00 00:45:00 00:45:00 01:00:00
00:55:00 01:00:00 00:45:00 00:45:00 01:00:00
01:00:00 01:00:00 01:00:00 01:00:00 01:00:00
01:05:00 01:00:00 01:00:00 01:00:00 01:15:00