Get Date Only Function¶
There are different ways of getting just the date part of a DATETIME data type. In Oracle, there is function called TRUNC that can accept a DATE/TIME parameter and will return just the date part. Unfortunately, there is no such function available for SQL Server. In this article three ways of getting the date part of a DATETIME data type will be discussed.
Values with the DATETIME data type are stored internally by Microsoft SQL Server as two 4-byte integers. The first 4 bytes store the number of days before or after the base date, January 1, 1900. The base date is the system reference date. Values fro DATETIME earlier than January 1, 1753, are not permitted. The other 4 bytes store the time of day represented as the number of milliseconds after midnight.
First Variant¶
One of the possible ways of getting the date part of a DATETIME data type is by retrieving the MONTH, DAY and YEAR part of the DATETIME data type and building a new DATETIME variable containing just these parts as shown in the following user-defined function.
CREATE FUNCTION [dbo].[ufn_GetDateOnly] ( @pInputDate DATETIME )
RETURNS DATETIME
BEGIN
RETURN CAST(CAST(YEAR(@pInputDate) AS VARCHAR(4)) + '/' +
CAST(MONTH(@pInputDate) AS VARCHAR(2)) + '/' +
CAST(DAY(@pInputDate) AS VARCHAR(2)) AS DATETIME)
END
GO
Description¶
The user-defined function simply gets the year, month and day of the input date parameter and concatenates them together in the "YYYY/MM/DD" format. This date format is used because SQL Server can easily convert this to a DATETIME data type without the confusion of determining which part is the day and which part is the month because SQL Server does not support the "YYYY/DD/MM" format, if ever such format exists. On the other hand, if the format used is "MM/DD/YYYY", this function may not perform properly where the default date format is in the "DD/MM/YYYY".
In extracting the different parts of the date, the YEAR, MONTH and DAY functions are used. The output of these functions are integer values that's why it has to be explicitly converted to VARCHAR data type. Otherwise, an error of "Syntax error converting the varchar value '/' to a column of data type int." will be encountered because SQL Server will try to convert the slash ('/') character into INT data type instead of convert the integer year, month and day into VARCHAR data type because INT data types have a higher precedence than VARCHAR data types.
The last step in the user-defined function after concatenating the different parts of the date is to convert it back to DATETIME data type as specified by the outer CAST function. This step is actually not needed since the format of the date is in the "YYYY/MM/DD" and SQL Server can already implicitly convert this to a DATETIME data type. Given this, the user-defined function can be simplified as follows:
CREATE FUNCTION [dbo].[ufn_GetDateOnly] ( @pInputDate DATETIME )
RETURNS DATETIME
BEGIN
RETURN CAST(YEAR(@pInputDate) AS VARCHAR(4)) + '/' +
CAST(MONTH(@pInputDate) AS VARCHAR(2)) + '/' +
CAST(DAY(@pInputDate) AS VARCHAR(2))
END
GO
Second Variant¶
Why bother manually building the output date using the 3 parts as discussed in the first variant above when there is already a built-in function that can perform this. The CONVERT function explicity converts an expression from one data type to another.
CREATE FUNCTION [dbo].[ufn_GetDateOnly] ( @pInputDate DATETIME )
RETURNS DATETIME
BEGIN
RETURN CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME)
END
GO
Description¶
This variant of the user-defined function basically behaves the same way as the first variant discussed above in the sense that it converts the input date into "YYYY/MM/DD" format getting rid of the time. The process of converting the input date into "YYYY/MM/DD" format involves only 1 function, the CONVERT function, compared to the first variant which used 3 functions (YEAR, MONTH and DAY). The "YYYY/MM/DD" format is achieved by the 111 parameter of the CONVERT function, which is the Japanese standard format.
Similar to the first variant, the last step in the user-defined function is to convert the VARCHAR data type back to DATETIME data type, which is achieved by the outer CAST function. Since SQL Server can implicitly convert the "YYYY/MM/DD" date format to a DATETIME data type which is the return type of this function, this last step is actually optional. Given this, the function can further be simplified as follows:
CREATE FUNCTION [dbo].[ufn_GetDateOnly] ( @pInputDate DATETIME )
RETURNS DATETIME
BEGIN
RETURN CONVERT(VARCHAR(10), @pInputDate, 111)
END
GO
Third Variant¶
According to Books Online,
"Values with the datetime data type are stored internally by Microsoft SQL Server as two 4-byte integers. The first 4 bytes store the number of days before or after the base date, January 1, 1900. The base date is the system reference date. Values for datetime earlier than January 1, 1753, are not permitted. The other 4 bytes store the time of day represented as the number of milliseconds after midnight."
The third variant in getting the date part of a DATETIME data type involves the use of the numeric representation of the input date.
CREATE FUNCTION [dbo].[ufn_GetDateOnly] ( @pInputDate DATETIME )
RETURNS DATETIME
BEGIN
RETURN CAST(FLOOR(CAST(@pInputDate AS DECIMAL(12, 5))) AS DATETIME)
END
GO
Description¶
A DATETIME data type can be expressed in DECIMAL format using the CAST or CONVERT function. The integer part of the DECIMAL format represents the date while the decimal value represents the time. By getting rid of the decimal value, the date part of a DATETIME data type can be extracted as demonstrated by the third variant of the user-defined function.
CAST(@pInputDate AS DECIMAL(12, 5)
- The first step is to convert the input date into its DECIMAL format. It is important to use DECIMAL(12, 5) instead of INT or DECIMAL(5, 0) because SQL Server will round the value instead of truncating it. So, any dates with a time of greater than 12:00 PM will be rounded to the next day because the decimal part of the date is already 0.5.FLOOR(DateInDecimal)
- The FLOOR function returns the largest integer less than or equal to the given numeric expression. This step basically converts the DECIMAL format of the input date into an integer value truncating any decimal value. This is similar to using the ROUND function with the third parameter supplied.CAST(DateInInteger AS DATETIME)
- The last step is simply converting the integer representation of the input date back to DATETIME data type.