SQL Server Forums
Profile | Register | Active Topics | Members | Search | Forum FAQ
 
Register Now and get your question answered!
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 General SQL Server Forums
 Script Library
 Start of Time Period Functions
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic  

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

USA
7020 Posts

Posted - 04/15/2006 :  14:28:46  Show Profile  Reply with Quote
There are a lot of questions posted on SQLTEAM asking how to find the beginning of various time periods. The script will create and demo 14 functions that return a datetime for the beginning of a time period relative to the datetime value passed in parameter @DAY.

I put together this script to create these functions for several reasons:
1. To allow people to find them on their own without having to post a question.
2. To allow posted questions to be answered with a reference to this script.
3. To document algorithms that work for the widest possible range of datetime values. All except for the Century and Decade functions work for any datetime value from 1753/01/01 00:00:00.000 through 9999/12/31 23:59:59.997. The Century is limited to datetimes from 1800/01/01 forward, because 1700/01/01 is not valid in SQL Server. The Decade function is limited to datetimes from 1760/01/01 forward, because 1750/01/01 is not valid in SQL Server.
4. And last, you can actually use them on your application.

The function names created by this script are:
dbo.F_START_OF_CENTURY( @DAY )
dbo.F_START_OF_DECADE( @DAY )
dbo.F_START_OF_YEAR( @DAY )
dbo.F_START_OF_QUARTER( @DAY )
dbo.F_START_OF_MONTH( @DAY )
dbo.F_START_OF_DAY( @DAY )
dbo.F_START_OF_HOUR( @DAY )
dbo.F_START_OF_30_MIN( @DAY )
dbo.F_START_OF_20_MIN( @DAY )
dbo.F_START_OF_15_MIN( @DAY )
dbo.F_START_OF_10_MIN( @DAY )
dbo.F_START_OF_05_MIN( @DAY )
dbo.F_START_OF_X_MIN( @DAY )
dbo.F_START_OF_MINUTE( @DAY )
dbo.F_START_OF_SECOND( @DAY )

There is a separate post for function dbo.F_START_OF_WEEK to find the first day of the week at this link:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47307

This script was tested with SQL Server 2000 only.


I posted a script for End Date of Time Period Functions here:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=64759


Other Date/Time Info and Script Links:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=64762


Edit 2006-11-01:
Added dbo.F_START_OF_X_MIN( @DAY ) at the suggestion of Peter.


Edit 2007-02-24:
Modified the following functions to use a simpler algorithm, that is shorter, runs faster, and is more suited for use with in-line code:
dbo.F_START_OF_30_MIN( @DAY )
dbo.F_START_OF_20_MIN( @DAY )
dbo.F_START_OF_15_MIN( @DAY )
dbo.F_START_OF_10_MIN( @DAY )
dbo.F_START_OF_05_MIN( @DAY )


Edit 2009-03-24:
Added script at end to demo start of time period methods using in-line code, along with output from sample script.









/*
Functions created by this script:
	dbo.F_START_OF_CENTURY( @DAY )
	dbo.F_START_OF_DECADE( @DAY )
	dbo.F_START_OF_YEAR( @DAY )
	dbo.F_START_OF_QUARTER( @DAY )
	dbo.F_START_OF_MONTH( @DAY )
	dbo.F_START_OF_DAY( @DAY )
	dbo.F_START_OF_HOUR( @DAY )
	dbo.F_START_OF_30_MIN( @DAY )
	dbo.F_START_OF_20_MIN( @DAY )
	dbo.F_START_OF_15_MIN( @DAY )
	dbo.F_START_OF_10_MIN( @DAY )
	dbo.F_START_OF_05_MIN( @DAY )
	dbo.F_START_OF_MINUTE( @DAY )
	dbo.F_START_OF_SECOND( @DAY )

*/
go
if objectproperty(object_id('dbo.F_START_OF_CENTURY'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_CENTURY end
go
create function dbo.F_START_OF_CENTURY
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_CENTURY
	Finds start of first day of century at 00:00:00.000
	for input datetime, @DAY.
	Valid for all SQL Server datetimes >= 1800-01-01 00:00:00.000
	Returns null if @DAY < 1800-01-01 00:00:00.000
*/
begin

declare @BASE_DAY datetime
select  @BASE_DAY = '18000101'

IF @DAY < @BASE_DAY return null 

return   dateadd(yy,(datediff(yy,@BASE_DAY,@DAY)/100)*100,@BASE_DAY)	

end
go
if objectproperty(object_id('dbo.F_START_OF_DECADE'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_DECADE end
go
create function dbo.F_START_OF_DECADE
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_DECADE
	Finds start of first day of decade at 00:00:00.000
	for input datetime, @DAY.
	Valid for all SQL Server datetimes >= 1760-01-01 00:00:00.000
	Returns null if @DAY < 1760-01-01 00:00:00.000
*/
begin

declare @BASE_DAY datetime
select  @BASE_DAY = '17600101'

IF @DAY < @BASE_DAY return null 

return   dateadd(yy,(datediff(yy,@BASE_DAY,@DAY)/10)*10,@BASE_DAY)	

end
go
if objectproperty(object_id('dbo.F_START_OF_YEAR'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_YEAR end
go
create function dbo.F_START_OF_YEAR
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_YEAR
	Finds start of first day of year at 00:00:00.000
	for input datetime, @DAY.
	Valid for all SQL Server datetimes.
*/
begin

return  dateadd(yy,datediff(yy,0,@DAY),0)

end
go
if objectproperty(object_id('dbo.F_START_OF_QUARTER'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_QUARTER end
go
create function dbo.F_START_OF_QUARTER
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_QUARTER
	Finds start of first day of quarter at 00:00:00.000
	for input datetime, @DAY.
	Valid for all SQL Server datetimes.
*/
begin

return   dateadd(qq,datediff(qq,0,@DAY),0)

end
go
if objectproperty(object_id('dbo.F_START_OF_MONTH'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_MONTH end
go
create function dbo.F_START_OF_MONTH
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_MONTH
	Finds start of first day of month at 00:00:00.000
	for input datetime, @DAY.
	Valid for all SQL Server datetimes.
*/
begin

return  dateadd(mm,datediff(mm,0,@DAY),0)

end
go
if objectproperty(object_id('dbo.F_START_OF_DAY'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_DAY end
go
create function dbo.F_START_OF_DAY
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_DAY
	Finds start of day at 00:00:00.000
	for input datetime, @DAY.
	Valid for all SQL Server datetimes
*/
begin

return  dateadd(dd,datediff(dd,0,@DAY),0)

end
go
if objectproperty(object_id('dbo.F_START_OF_HOUR'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_HOUR end
go
create function dbo.F_START_OF_HOUR
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_HOUR
	Finds beginning of hour
	for input datetime, @DAY.
	Valid for all SQL Server datetimes.
*/
begin

return   dateadd(hh,datediff(hh,0,@DAY),0)

end
go
if objectproperty(object_id('dbo.F_START_OF_30_MIN'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_30_MIN end
go
create function dbo.F_START_OF_30_MIN
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_30_MIN
	Finds beginning of 30 minute period
	for input datetime, @DAY.
	Valid for all SQL Server datetimes.
*/
begin

return  dateadd(mi,(datepart(mi,@Day)/30)*30,dateadd(hh,datediff(hh,0,@Day),0))

end
go
if objectproperty(object_id('dbo.F_START_OF_20_MIN'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_20_MIN end
go
create function dbo.F_START_OF_20_MIN
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_20_MIN
	Finds beginning of 20 minute period
	for input datetime, @DAY.
	Valid for all SQL Server datetimes.
*/
begin

return  dateadd(mi,(datepart(mi,@Day)/20)*20,dateadd(hh,datediff(hh,0,@Day),0))

end
go
if objectproperty(object_id('dbo.F_START_OF_15_MIN'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_15_MIN end
go
create function dbo.F_START_OF_15_MIN
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_15_MIN
	Finds beginning of 15 minute period
	for input datetime, @DAY.
	Valid for all SQL Server datetimes.
*/
begin

return  dateadd(mi,(datepart(mi,@Day)/15)*15,dateadd(hh,datediff(hh,0,@Day),0))

end
go
if objectproperty(object_id('dbo.F_START_OF_10_MIN'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_10_MIN end
go
create function dbo.F_START_OF_10_MIN
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_10_MIN
	Finds beginning of 10 minute period
	for input datetime, @DAY.
	Valid for all SQL Server datetimes.
*/
begin

return  dateadd(mi,(datepart(mi,@Day)/10)*10,dateadd(hh,datediff(hh,0,@Day),0))

end
go
if objectproperty(object_id('dbo.F_START_OF_05_MIN'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_05_MIN end
go
create function dbo.F_START_OF_05_MIN
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_05_MIN
	Finds beginning of 5 minute period
	for input datetime, @DAY.
	Valid for all SQL Server datetimes.
*/
begin

return  dateadd(mi,(datepart(mi,@Day)/5)*5,dateadd(hh,datediff(hh,0,@Day),0))

end
go
if objectproperty(object_id('dbo.F_START_OF_X_MIN'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_X_MIN end
go
create function dbo.F_START_OF_X_MIN
	(
	@DAY datetime,
	@INTERVAL int
	)
returns  datetime
as
/*
Function: F_START_OF_X_MIN
	Finds beginning of @INTERVAL minute period
	for input datetime, @DAY.
	If @INTERVAL = zero, returns @DAY.
	Valid for all SQL Server datetimes.
*/
begin

-- Prevent divide by zero error
if @INTERVAL = 0 return @DAY

declare @BASE_DAY datetime
set  @BASE_DAY = dateadd(dd,datediff(dd,0,@Day),0)

return  dateadd(mi,(datediff(mi,@BASE_DAY,@Day)/@INTERVAL)*@INTERVAL,@BASE_DAY)

end
go
if objectproperty(object_id('dbo.F_START_OF_MINUTE'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_MINUTE end
go
create function dbo.F_START_OF_MINUTE
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_MINUTE
	Finds beginning of minute
	for input datetime, @DAY.
	Valid for all SQL Server datetimes.
*/
begin

return   dateadd(ms,-(datepart(ss,@DAY)*1000)-datepart(ms,@DAY),@DAY)

end
go
if objectproperty(object_id('dbo.F_START_OF_SECOND'),'IsScalarFunction') = 1
	begin drop function dbo.F_START_OF_SECOND end
go
create function dbo.F_START_OF_SECOND
	( @DAY datetime )
returns  datetime
as
/*
Function: F_START_OF_SECOND
	Finds beginning of second
	for input datetime, @DAY.
	Valid for all SQL Server datetimes.
*/
begin

return   dateadd(ms,-datepart(ms,@DAY),@DAY)

end
go

/*
Start of test script

Load dates to test F_START_OF functions

*/

declare @test_dates table ( DT datetime not null primary key clustered )
declare @today varchar(10)
select @today = convert(varchar(10),getdate(),112)
declare @year varchar(4)
select @year = convert(varchar(4),year(getdate()))
declare @lyear varchar(10)
select @lyear = convert(varchar(10),getdate()-345,112)

insert into @test_dates (DT)
select DT = getdate()	union all
select  '17530101 00:00:00.000'	union all
-- Test start of Decade cutoff
select  '17591231 23:59:59.997'	union all
select  '17600101 23:04:59.997'	union all
-- Test start of Century cutoff
select  '17991231 23:59:59.997'	union all
select  '18000101 00:00:00.000'	union all
-- Test start of Decade and Century
select  '19000101 00:00:00.000'	union all
select  '19001231 23:59:59.997'	union all
select  '19400101 00:00:00.000'	union all
select  '19491231 23:59:59.997'	union all
select  '19900101 00:00:00.000'	union all
select  '19991231 23:59:59.997'	union all
-- For start of Hour testing
select  @lyear+' 00:00:00.000'	union all
select  @lyear+' 00:59:59.997'	union all
select  @lyear+' 01:00:00.000'	union all
select  @lyear+' 01:59:59.997'	union all
select  @lyear+' 12:00:00.000'	union all
select  @lyear+' 12:59:59.997'	union all
select  @lyear+' 17:00:00.000'	union all
select  @lyear+' 17:59:59.997'	union all
select  @lyear+' 23:00:00.000'	union all
select  @lyear+' 23:59:59.997'	union all
-- For start of Month, Quarter, and Year testing
select @year+'0101 00:00:00.000'	union all
select @year+'0131 23:59:59.997'	union all
select @year+'0201 00:00:00.000'	union all
select @year+'0228 23:59:59.997'	union all
select @year+'0301 00:00:00.000'	union all
select @year+'0331 23:59:59.997'	union all
select @year+'0401 00:00:00.000'	union all
select @year+'0430 23:59:59.997'	union all
select @year+'0501 00:00:00.000'	union all
select @year+'0531 23:59:59.997'	union all
select @year+'0601 00:00:00.000'	union all
select @year+'0630 23:59:59.997'	union all
select @year+'0701 00:00:00.000'	union all
select @year+'0731 23:59:59.997'	union all
select @year+'0801 00:00:00.000'	union all
select @year+'0831 23:59:59.997'	union all
select @year+'0901 00:00:00.000'	union all
select @year+'0930 23:59:59.997'	union all
select @year+'1001 00:00:00.000'	union all
select @year+'1031 23:59:59.997'	union all
select @year+'1101 00:00:00.000'	union all
select @year+'1130 23:59:59.997'	union all
select @year+'1201 00:00:00.000'	union all
select @year+'1231 23:59:59.997'	union all
-- Test start of 5, 10, 15, 20, and 30 min testing 
select  @today+' 23:04:59.997'	union all
select  @today+' 23:09:59.997'	union all
select  @today+' 23:14:59.997'	union all
select  @today+' 23:19:59.997'	union all
select  @today+' 23:24:59.997'	union all
select  @today+' 23:29:59.997'	union all
select  @today+' 23:34:59.997'	union all
select  @today+' 23:39:59.997'	union all
select  @today+' 23:44:59.997'	union all
select  @today+' 23:49:59.997'	union all
select  @today+' 23:54:59.997'	union all
select  @today+' 23:59:59.997'	union all
select   '99991231 23:59:59.997'
order by
	1

-- Convert dates in @test_dates table to test F_START_OF functions

select
	TYPE = 'CENTURY' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_CENTURY( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = 'DECADE' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_DECADE( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = 'YEAR' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_YEAR( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = 'QUARTER' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_QUARTER( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = 'MONTH' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_MONTH( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = 'DAY' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_DAY( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = 'HOUR' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_HOUR( DT ),121)
from
	 @test_dates
order by
	DT


select
	TYPE = '30_MIN' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_30_MIN( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = '20_MIN' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_20_MIN( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = '15_MIN' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_15_MIN( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = '10_MIN' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_10_MIN( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = '05_MIN' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_05_MIN( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = 'MINUTE' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_MINUTE( DT ),121)
from
	 @test_dates
order by
	DT

select
	TYPE = 'SECOND' ,
	DT = convert(varchar(23),DT,121),
	FUNCTION_RESULT =
		convert(varchar(23),dbo.F_START_OF_SECOND( DT ),121)
from
	 @test_dates
order by
	DT
/*
End of test script
*/




/*
Script to demo Start of Time period methods in-line for various types of time periods.
All methods will run with no error for any valid datetime value
*/

set nocount on
declare @day table (DT datetime not null primary key clustered)

-- Load Test Dates
insert into @day (DT)
select DT = getdate()
union all
select '2014-05-24 16:56:27.667'
union all
select '17530101 00:00:00.000'
union all
select '17591231 23:59:59.997'
union all
select '17600101 00:00:00.000'
union all
select '17991231 23:59:59.997'
union all
select '18000101 00:00:00.000'
union all
select '99991231 23:59:59.997'
order by 1

select Test_Dates = DT  from @day order by 1

select	START_OF_CENTURY = 
	case
	when a.DT < '18000101'
	then convert(datetime,null)
	else dateadd(yy,(datediff(yy,'18000101',a.DT)/100)*100,'18000101')
	end
from @day a

select	START_OF_DECADE = 
	case
	when a.DT < '17600101'
	then convert(datetime,null)
	else dateadd(yy,(datediff(yy,'17600101',a.DT)/10)*10,'17600101')
	end
from @day a

select START_OF_YEAR = dateadd(yy,datediff(yy,0,a.DT),0) from @day a

select START_OF_QUARTER = dateadd(qq,datediff(qq,0,a.DT),0) from @day a

select START_OF_MONTH = dateadd(mm,datediff(mm,0,a.DT),0) from @day a

select START_OF_DAY  = dateadd(dd,datediff(dd,0,a.DT),0) from @day a

select START_OF_HOUR = dateadd(hh,datediff(hh,0,a.DT),0) from @day a

select START_OF_30_MIN = dateadd(mi,(datepart(mi,a.DT)/30)*30,dateadd(hh,datediff(hh,0,a.DT),0)) from @day a

select START_OF_20_MIN = dateadd(mi,(datepart(mi,a.DT)/20)*20,dateadd(hh,datediff(hh,0,a.DT),0)) from @day a

select START_OF_15_MIN = dateadd(mi,(datepart(mi,a.DT)/15)*15,dateadd(hh,datediff(hh,0,a.DT),0)) from @day a

select START_OF_10_MIN = dateadd(mi,(datepart(mi,a.DT)/10)*10,dateadd(hh,datediff(hh,0,a.DT),0)) from @day a

select START_OF_05_MIN = dateadd(mi,(datepart(mi,a.DT)/5)*5,dateadd(hh,datediff(hh,0,a.DT),0)) from @day a

select START_OF_MINUTE = dateadd(ms,-(datepart(ss,a.DT)*1000)-datepart(ms,a.DT),a.DT) from @day a

select START_OF_SECOND = dateadd(ms,-datepart(ms,a.DT),a.DT) from @day a

Results for in-line code demo:

Test_Dates                                             
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-12-31 23:59:59.997
1760-01-01 00:00:00.000
1799-12-31 23:59:59.997
1800-01-01 00:00:00.000
2009-03-24 17:03:53.717
2014-05-24 16:56:27.667
9999-12-31 23:59:59.997

START_OF_CENTURY                                       
------------------------------------------------------ 
NULL
NULL
NULL
NULL
1800-01-01 00:00:00.000
2000-01-01 00:00:00.000
2000-01-01 00:00:00.000
9900-01-01 00:00:00.000

START_OF_DECADE                                        
------------------------------------------------------ 
NULL
NULL
1760-01-01 00:00:00.000
1790-01-01 00:00:00.000
1800-01-01 00:00:00.000
2000-01-01 00:00:00.000
2010-01-01 00:00:00.000
9990-01-01 00:00:00.000

START_OF_YEAR                                          
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-01-01 00:00:00.000
1760-01-01 00:00:00.000
1799-01-01 00:00:00.000
1800-01-01 00:00:00.000
2009-01-01 00:00:00.000
2014-01-01 00:00:00.000
9999-01-01 00:00:00.000

START_OF_QUARTER                                       
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-10-01 00:00:00.000
1760-01-01 00:00:00.000
1799-10-01 00:00:00.000
1800-01-01 00:00:00.000
2009-01-01 00:00:00.000
2014-04-01 00:00:00.000
9999-10-01 00:00:00.000

START_OF_MONTH                                         
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-12-01 00:00:00.000
1760-01-01 00:00:00.000
1799-12-01 00:00:00.000
1800-01-01 00:00:00.000
2009-03-01 00:00:00.000
2014-05-01 00:00:00.000
9999-12-01 00:00:00.000

START_OF_DAY                                           
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-12-31 00:00:00.000
1760-01-01 00:00:00.000
1799-12-31 00:00:00.000
1800-01-01 00:00:00.000
2009-03-24 00:00:00.000
2014-05-24 00:00:00.000
9999-12-31 00:00:00.000

START_OF_HOUR                                          
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-12-31 23:00:00.000
1760-01-01 00:00:00.000
1799-12-31 23:00:00.000
1800-01-01 00:00:00.000
2009-03-24 17:00:00.000
2014-05-24 16:00:00.000
9999-12-31 23:00:00.000

START_OF_30_MIN                                        
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-12-31 23:30:00.000
1760-01-01 00:00:00.000
1799-12-31 23:30:00.000
1800-01-01 00:00:00.000
2009-03-24 17:00:00.000
2014-05-24 16:30:00.000
9999-12-31 23:30:00.000

START_OF_20_MIN                                        
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-12-31 23:40:00.000
1760-01-01 00:00:00.000
1799-12-31 23:40:00.000
1800-01-01 00:00:00.000
2009-03-24 17:00:00.000
2014-05-24 16:40:00.000
9999-12-31 23:40:00.000

START_OF_15_MIN                                        
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-12-31 23:45:00.000
1760-01-01 00:00:00.000
1799-12-31 23:45:00.000
1800-01-01 00:00:00.000
2009-03-24 17:00:00.000
2014-05-24 16:45:00.000
9999-12-31 23:45:00.000

START_OF_10_MIN                                        
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-12-31 23:50:00.000
1760-01-01 00:00:00.000
1799-12-31 23:50:00.000
1800-01-01 00:00:00.000
2009-03-24 17:00:00.000
2014-05-24 16:50:00.000
9999-12-31 23:50:00.000

START_OF_05_MIN                                        
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-12-31 23:55:00.000
1760-01-01 00:00:00.000
1799-12-31 23:55:00.000
1800-01-01 00:00:00.000
2009-03-24 17:00:00.000
2014-05-24 16:55:00.000
9999-12-31 23:55:00.000

START_OF_MINUTE                                        
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-12-31 23:59:00.000
1760-01-01 00:00:00.000
1799-12-31 23:59:00.000
1800-01-01 00:00:00.000
2009-03-24 17:03:00.000
2014-05-24 16:56:00.000
9999-12-31 23:59:00.000

START_OF_SECOND                                        
------------------------------------------------------ 
1753-01-01 00:00:00.000
1759-12-31 23:59:59.000
1760-01-01 00:00:00.000
1799-12-31 23:59:59.000
1800-01-01 00:00:00.000
2009-03-24 17:03:53.000
2014-05-24 16:56:27.000
9999-12-31 23:59:59.000







CODO ERGO SUM

Edited by - Michael Valentine Jones on 03/24/2009 17:09:34

CLages
Posting Yak Master

Brazil
116 Posts

Posted - 10/24/2006 :  15:11:05  Show Profile  Reply with Quote
The main problem is that
Always i convert to SMALLDATETIME, the CONVERT round the Date, I need
to Truncate.

I can not Now change the Column from smalldatetime to datetime

tks
Clages
Go to Top of Page

rockmoose
SQL Natt Alfen

Sweden
3279 Posts

Posted - 10/24/2006 :  15:28:46  Show Profile  Reply with Quote
I only miss:

F_DANCERS_AT_THE_END_OF_TIME()

rockmoose
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

Sweden
29910 Posts

Posted - 11/01/2006 :  07:54:21  Show Profile  Visit SwePeso's Homepage  Reply with Quote
What about dbo.F_START_OF_X_MIN( @DAY, @Interval ) ? Then divide and multiply with @Interval?
I needed this function, today, so I took the liberty to write the function as F_START_OF_6_MIN, because I needed to calculate to a 1/10th of an hour.
Then I realized the function could accept this interval as a parameter.


Peter Larsson
Helsingborg, Sweden

Edited by - SwePeso on 11/01/2006 08:00:21
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

USA
7020 Posts

Posted - 11/01/2006 :  16:25:21  Show Profile  Reply with Quote
quote:
Originally posted by Peso

What about dbo.F_START_OF_X_MIN( @DAY, @Interval ) ? Then divide and multiply with @Interval?
I needed this function, today, so I took the liberty to write the function as F_START_OF_6_MIN, because I needed to calculate to a 1/10th of an hour.
Then I realized the function could accept this interval as a parameter.


Peter Larsson
Helsingborg, Sweden



Added F_START_OF_X_MIN to script.



CODO ERGO SUM
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

USA
7020 Posts

Posted - 02/24/2007 :  19:03:55  Show Profile  Reply with Quote
Modified the following functions to use a simpler algorithm, that is shorter, runs faster, and is more suited for use with in-line code:
dbo.F_START_OF_30_MIN( @DAY )
dbo.F_START_OF_20_MIN( @DAY )
dbo.F_START_OF_15_MIN( @DAY )
dbo.F_START_OF_10_MIN( @DAY )
dbo.F_START_OF_05_MIN( @DAY )



CODO ERGO SUM
Go to Top of Page

rockmoose
SQL Natt Alfen

Sweden
3279 Posts

Posted - 02/25/2007 :  16:58:08  Show Profile  Reply with Quote
quote:
Originally posted by Michael Valentine Jones

Modified the following functions to use a simpler algorithm, that is shorter, runs faster, and is more suited for use with in-line code:
dbo.F_START_OF_30_MIN( @DAY )
dbo.F_START_OF_20_MIN( @DAY )
dbo.F_START_OF_15_MIN( @DAY )
dbo.F_START_OF_10_MIN( @DAY )
dbo.F_START_OF_05_MIN( @DAY )



CODO ERGO SUM



I don't know what the change was, but this seems even simpler?:

declare @Day datetime; set @Day = getdate()


select	@day
	,dateadd(mi,(datepart(mi,@Day)/15)*15,dateadd(hh,datediff(hh,0,@Day),0))	as mvj
	,dateadd(mi,datediff(mi,0,@Day)-datepart(mi,@day)%15,0)				as rockmoose
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

USA
7020 Posts

Posted - 02/25/2007 :  18:13:29  Show Profile  Reply with Quote
quote:
Originally posted by rockmoose
I don't know what the change was, but this seems even simpler?:

declare @Day datetime; set @Day = getdate()


select	@day
	,dateadd(mi,(datepart(mi,@Day)/15)*15,dateadd(hh,datediff(hh,0,@Day),0))	as mvj
	,dateadd(mi,datediff(mi,0,@Day)-datepart(mi,@day)%15,0)				as rockmoose



The second method does work most of the time, but it doesn't meet my design objective to "work for any datetime value from 1753/01/01 00:00:00.000 through 9999/12/31 23:59:59.997"



declare @day datetime
set @day = '99991231 23:59:59'

print 'Method 1'
select M1 = dateadd(mi,(datepart(mi,@Day)/15)*15,dateadd(hh,datediff(hh,0,@Day),0))

print 'Method 2'
select M2 = dateadd(mi,datediff(mi,0,@Day)-datepart(mi,@day)%15,0)

Results:

Method 1
M1                                                     
------------------------------------------------------ 
9999-12-31 23:45:00.000

(1 row(s) affected)

Method 2
Server: Msg 535, Level 16, State 1, Line 8
Difference of two datetime columns caused overflow at runtime.



CODO ERGO SUM
Go to Top of Page

rockmoose
SQL Natt Alfen

Sweden
3279 Posts

Posted - 02/26/2007 :  03:24:10  Show Profile  Reply with Quote
hmm, yes, it only works up to '5983-01-24 02:07:59.997'

rockmoose
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

USA
7020 Posts

Posted - 02/26/2007 :  09:41:03  Show Profile  Reply with Quote
quote:
Originally posted by rockmoose

hmm, yes, it only works up to '5983-01-24 02:07:59.997'

rockmoose


The method you posted would work for the vast majority of applications, but I wanted an algorithm that would work with any datetime. My method is a little more complicated, but still possible to use with in-line code instead of in the function, and that is also something I wanted.

The previous method was the one used in F_START_OF_X_MIN. I didn't change that function, because it would change the results it produces when 60%@INTERVAL <> 0.




CODO ERGO SUM
Go to Top of Page

X002548
Not Just a Number

15586 Posts

Posted - 02/26/2007 :  10:19:21  Show Profile  Reply with Quote
quote:
Originally posted by rockmoose

I only miss:

F_DANCERS_AT_THE_END_OF_TIME()

rockmoose



Or

F_LENGTH_OF_LAP_DANCE



Brett

8-)

Hint: Want your questions answered fast? Follow the direction in this link
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx

Add yourself!
http://www.frappr.com/sqlteam



Go to Top of Page

rockmoose
SQL Natt Alfen

Sweden
3279 Posts

Posted - 02/26/2007 :  14:12:40  Show Profile  Reply with Quote
Good design goal, and for a "library" function I would expect no less.


If I need to store year 6000AD, chances are that I also would need 60000AD or 600000AD, so another datatype altogether might make sense

Reminds me of the Y2K bug, I't hate to leave an inbuilt Y5983 bug! <- Pun

> F_LENGTH_OF_LAP_DANCE
That's great...

Now we need:
F_TIME_OF_MARGERITA()
Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

USA
7020 Posts

Posted - 02/26/2007 :  14:18:14  Show Profile  Reply with Quote
quote:
Originally posted by rockmoose

Good design goal, and for a "library" function I would expect no less.


If I need to store year 6000AD, chances are that I also would need 60000AD or 600000AD, so another datatype altogether might make sense

Reminds me of the Y2K bug, I't hate to leave an inbuilt Y5983 bug! <- Pun

> F_LENGTH_OF_LAP_DANCE
That's great...

Now we need:
F_TIME_OF_MARGERITA()



Nobody seems too worried about the SQL Server Y10K bug.


I'm more interested in the F_START_OF_LAP_DANCE.



CODO ERGO SUM

Edited by - Michael Valentine Jones on 02/26/2007 14:19:50
Go to Top of Page

rockmoose
SQL Natt Alfen

Sweden
3279 Posts

Posted - 02/26/2007 :  14:40:18  Show Profile  Reply with Quote
> Nobody seems too worried about the SQL Server Y10K bug.
M$ has an army of consultants ready to tackle that one, and they are not the lea$t worried.

F_START_OF_LAP_DANCE, hmm yeah, I'd like to see an optimal implementation
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
SQL Server Forums © 2000-2009 SQLTeam Publishing, LLC Go To Top Of Page
This page was generated in 0.19 seconds. Powered By: Snitz Forums 2000