Tôi đã tranh luận về việc có nên đăng bài này hay không vì nó phụ thuộc vào cách lưu trữ ngày tháng ở cấp nhị phân trong SQL Server và vì vậy nó là một giải pháp rất dễ hỏng. Đối với bất kỳ điều gì khác ngoài chuyển đổi một lần, tôi sẽ sử dụng một cái gì đó giống như câu trả lời mà @Solution Evangelist đã đăng. Tuy nhiên, bạn có thể thấy điều này thú vị về mặt học thuật, vì vậy tôi vẫn sẽ đăng nó.
Tận dụng thực tế là độ chính xác của DateTime2
khớp với thời lượng đánh dấu trong .NET và cả hai đều dựa trên ngày bắt đầu của 01-01-0001 00:00:00.0000000
, bạn có thể truyền DateTime
thành DateTime2
, rồi truyền nó sang binary(9)
:0x07F06C999F3CB7340B
Thông tin ngày giờ được lưu trữ RTL, vì vậy khi đảo ngược, chúng ta sẽ nhận được 0x0B34B73C9F996CF007
.
Ba byte đầu tiên lưu trữ số ngày kể từ 01-01-0001
và 5 byte tiếp theo lưu trữ 100ns tích kể từ nửa đêm của ngày hôm đó, vì vậy chúng tôi có thể lấy số ngày, nhân với số tích tắc trong một ngày và thêm các dấu tích biểu thị thời gian trôi qua trong ngày.
Đang thực thi đoạn mã sau:
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]
trả về các kết quả sau:
DateTime DateTime2 Ticks
----------------------- ---------------------- --------------------
2011-09-12 07:20:32.587 2011-09-12 07:20:32.58 634514088325870000
Lấy số lượng Ve đã trả lại và chuyển đổi trở lại DateTime trong .NET:
DateTime dt = new DateTime(634514088325870000);
dt.ToString("yyyy-MM-dd HH:mm:ss.fffffff").Dump();
Cho chúng tôi quay lại ngày từ máy chủ sql:
2011-09-12 07:20:32.5870000