I debated whether to post this because it depends on how dates are stored at the binary level in SQL Server, and so it is a very brittle solution. For anything other than a one-off conversion, I would use something like the answer that @Solution Evangelist posted. Still, you might find this interesting in an academic sort of way, so I'll post it anyway.
Making use of the fact that the accuracy of DateTime2
matches up with the tick duration in .NET and that both are based on starting dates of 01-01-0001 00:00:00.0000000
, you can cast the DateTime
to DateTime2
, and then cast it to binary(9)
: 0x07F06C999F3CB7340B
The datetime information is stored RTL, so reversing, we'll get 0x0B34B73C9F996CF007
.
The first three bytes store the number of days since 01-01-0001
and the next 5 bytes store the 100ns ticks since midnight of that day, so we can take the number of days, multiply by the ticks in a day and add the ticks representing the time elapsed for the day.
Executing the following code:
set @date = getdate()
set @ticksPerDay = 864000000000
declare @date2 datetime2 = @date
declare @dateBinary binary(9) = cast(reverse(cast(@date2 as binary(9))) as binary(9))
declare @days bigint = cast(substring(@dateBinary, 1, 3) as bigint)
declare @time bigint = cast(substring(@dateBinary, 4, 5) as bigint)
select @date as [DateTime], @date2 as [DateTime2], @days * @ticksPerDay + @time as [Ticks]
returns the following results:
DateTime DateTime2 Ticks
----------------------- ---------------------- --------------------
2011-09-12 07:20:32.587 2011-09-12 07:20:32.58 634514088325870000
Taking the returned number of Ticks and converting back to a DateTime in .NET:
DateTime dt = new DateTime(634514088325870000);
dt.ToString("yyyy-MM-dd HH:mm:ss.fffffff").Dump();
Gets us back the date from sql server:
2011-09-12 07:20:32.5870000