How to combine date and time to datetime2 in SQL Server?
This seems to work and keep the precision as well:
SELECT DATEADD(day, DATEDIFF(day,'19000101',@D), CAST(@T AS DATETIME2(7)))
The CAST
to DATETIME2(7)
converts the TIME(7)
value (@T
) to a DATETIME2
where the date part is '1900-01-01'
, which is the default value of date and datetime types (see datetime2
and the comment* at CAST
and CONVERT
page at MSDN.)
* ... When character data that represents only date or only time components is cast to the datetime or smalldatetime data types, the unspecified time component is set to 00:00:00.000, and the unspecified date component is set to 1900-01-01.
The DATEADD()
and DATEDIFF()
function take care of the rest, i.e. adding the difference in days between the 1900-01-01
and the DATE
value (@D
).
Test at: SQL-Fiddle
As noticed by @Quandary, the above expression is considered not-determninistic by SQL Server. If we want a deterministic expression, say because it is to be used for a PERSISTED
column, the '19000101'
** needs to be replaced by 0
or CONVERT(DATE, '19000101', 112)
:
CREATE TABLE date_time
( d DATE NOT NULL,
t TIME(7) NOT NULL,
dt AS DATEADD(day,
DATEDIFF(day, CONVERT(DATE, '19000101', 112), d),
CAST(t AS DATETIME2(7))
) PERSISTED
) ;
**: DATEDIFF(day, '19000101', d)
isn't deterministic as it does an implicit conversion of the string to DATETIME
and conversions from strings to datetime are deterministic only when specific styles are used.
I'm late to the party but this approach, while similar to @ypercube's answer, avoids the need to use any string conversion (which can be more expensive than date conversions), is deterministic, and should continue to work if MS ever change the default date value from 1900-01-01 (even though they probably wont change this):
DECLARE @D DATE = SYSUTCDATETIME()
, @T TIME = SYSUTCDATETIME();
SELECT DATEADD(DAY, DATEDIFF(DAY, @T, @D), CONVERT(DATETIME2, @T));
The principle is that by converting the time value to datetime2 and then to date, it strips the time out and assigns the default date, you then datediff this with your date value to get the days to add, cast your time to datetime2 and add the days on.
For SQL Server 2012 and above there is the DATETIME2FROMPARTS function. It has this form:
DATETIME2FROMPARTS(year, month, day, hour, minute, seconds, fractions, precision)
For the given sample data this becomes
select Answer = DATETIME2FROMPARTS(2013, 10, 13, 23, 59, 59, 9999999, 7);
which results in
Answer
---------------------------
2013-10-13 23:59:59.9999999
The parts can be obtained using DATEPART() if starting from temporal datatypes, or from the text used to construct the sample values in the question.