set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
/*
Function fn_DatePart
Written by Casey Hart
Use, edit, alter, or share at will, but do so at your own risk.
I built this because I hate doing the datepart dance to make strings.
This returns a table of dateparts that correspond to the the datetime
parameter passed to it, or for getdate() if null is passed. It returns all
date parts in their native data types, as well as their string equivalents.
I also added month, month abbr., day, ampm, day of week, suffix
(st, nd, rd, th), and a couple common variations of the complete time for good
measure.
One gotcha:
Since UDFs won't accept a system function as a default parameter, and you can't
call a system function (i.e. getdate()) within a UDF, getting this to return
the current date without @indate=getdate() before the function call required a
little trickery.
UDFs CAN reference views, and views CAN call system functions, so it does the
semantic ring-around-the-rosy when a null is passed to fn_Datepart as the
@indate parameter. In such cases, it uses a simple view called v_getdate in
the current database to get its date. If you want this behavior, you will need
to create the view.
e.g. create view v_getdate as select getdate() as indate
Usage with a datetime variable:
DECLARE @indate datetime
SET @indate='Dec 3 2001'
SELECT day_s + ' ' + month_s + ' the ' + dw_s + ' ' + yyyy_s as dstr
FROM dbo.fn_DatePart( @indate )
dstr
----
Monday December the 3rd 2001
As a correlated subquery:
SELECT email, (select dd_s + hh_s + mi_s FROM dbo.fn_datepart(join_dt))
FROM members
*/
CREATE FUNCTION [dbo].[fn_DatePart]( @indate datetime = null)
RETURNS @dateparts TABLE
(
yyyy int
, yyyy_s varchar(4)
, qq tinyint
, qq_s varchar(2)
, mm tinyint
, mm_s varchar(2)
, monthabbr_s varchar(4)
, dy int
, dy_s varchar(3)
, dd tinyint
, dd_s varchar(2)
, wk int
, wk_s varchar(2)
, dw tinyint
, dw_s varchar(2)
, hh tinyint
, hh_s varchar(2)
, hh24 tinyint
, hh24_s varchar(2)
, mi tinyint
, mi_s varchar(2)
, ss tinyint
, ss_s varchar(2)
, ms int
, ms_s varchar(3)
, ampm_s varchar(2)
, time24_s varchar(12)
, time_s varchar(14)
, month_s varchar(9)
, dw_suffix varchar(2)
, day_s varchar(9)
)
AS
BEGIN
IF @indate IS NULL
SELECT @indate = indate FROM v_getdate
INSERT INTO @dateparts
SELECT datepart( yyyy, @indate) yyyy
, convert( varchar(4), datepart( yyyy, @indate )) yyyy_s
, datepart( qq, @indate) qq
, convert( varchar(2), datepart( qq, @indate) ) qq_s
, datepart( mm, @indate) mm
, right('0' + convert( varchar(2), datepart( mm, @indate)), 2) mm_s
, convert( varchar(3), @indate, 100) monthabbr_s
, datepart( dy, @indate) dy
, convert( varchar(3), datepart( dy, @indate) ) dy_s
, datepart( dd, @indate) dd
, right('0' + convert( varchar(2), datepart( dd, @indate)), 2) dd_s
, datepart( wk, @indate) wk
, convert( varchar(2), datepart( wk, @indate) ) wk_s
, datepart( dw, @indate) dw
, convert( varchar(2), datepart( dw, @indate) ) dw_s
, convert( int, left( right(convert( varchar(40), dateadd(hh, -1, @indate), 109), 14), 2)) hh
, right(replace(left( right(convert( varchar(40), dateadd(hh, -1, @indate), 109), 14), 2), ' ', '0'), 2) hh_s
, convert(tinyint, convert( varchar(2), @indate, 14)) hh24
, right( '0' + convert( varchar(2), @indate, 14), 2) hh24_s
, datepart( mi, @indate) mi
, right( '0' + ltrim( convert( varchar(2), datepart( mi, @indate) )), 2) mi_s
, datepart( ss, @indate) ss
, right( '0' + ltrim( convert( varchar(2), datepart( ss, @indate) )), 2) ss_s
, datepart( ms, @indate) ms
, right( '00' + ltrim( convert( varchar(3), datepart( ms, @indate) )), 3) ms_s
, Right(RTrim(convert(varchar(40), @indate, 100)), 2) ampm_s
, left( convert( varchar(20), @indate, 14), 12) time24_s
, right( '0' + ltrim( reverse( left( reverse( convert( varchar(40), @indate, 109)), 14) )), 14) time_s
, CASE datepart( mm, @indate)
When 1 THEN 'January'
When 2 THEN 'February'
When 3 THEN 'March'
When 4 THEN 'April'
When 5 THEN 'May'
When 6 THEN 'June'
When 7 THEN 'July'
When 8 THEN 'August'
When 9 THEN 'September'
When 10 THEN 'October'
When 11 THEN 'November'
When 12 THEN 'December'
END month_s
, CASE datepart( dd, @indate)
When 1 Then 'st'
When 21 Then 'st'
When 31 Then 'st'
When 2 Then 'nd'
When 22 Then 'nd'
When 3 Then 'rd'
When 23 Then 'rd'
Else 'th'
END dw_suffix
, CASE ( datepart( dw, @indate ) + @@datefirst) % 7
When 1 THEN 'Sunday'
When 2 THEN 'Monday'
When 3 THEN 'Tuesday'
When 4 THEN 'Wednesday'
When 5 THEN 'Thursday'
When 6 THEN 'Friday'
When 7 THEN 'Saturday'
END day_s
RETURN
END