Dấu thời gian Unix là số giây nguyên kể từ ngày 1 tháng 1 năm 1970 theo giờ UTC.
Giả sử ý bạn là bạn có một cột số nguyên trong cơ sở dữ liệu của mình với số này, thì múi giờ của máy chủ cơ sở dữ liệu của bạn không liên quan.
Đầu tiên chuyển đổi dấu thời gian thành datetime
loại:
SELECT DATEADD(second, yourTimeStamp, '1970-01-01')
Đây sẽ là UTC datetime
tương ứng với dấu thời gian của bạn.
Sau đó, bạn cần biết cách điều chỉnh giá trị này theo múi giờ mục tiêu của mình. Ở hầu hết các quốc gia trên thế giới, một khu vực duy nhất có thể có nhiều hiệu số, do Giờ tiết kiệm ánh sáng ban ngày.
Thật không may, SQL Server không có khả năng làm việc trực tiếp múi giờ làm việc. Vì vậy, nếu bạn đang sử dụng giờ Thái Bình Dương của Hoa Kỳ, chẳng hạn, bạn sẽ không có cách nào để biết liệu bạn nên trừ đi 7 giờ hay 8 giờ. Các cơ sở dữ liệu khác (Oracle, Postgres, MySql, v.v.) có các cách tích hợp để xử lý điều này, nhưng than ôi, SQL Server thì không. Vì vậy, nếu bạn đang tìm kiếm một giải pháp cho mục đích chung, bạn sẽ cần thực hiện một trong những điều sau:
-
Nhập dữ liệu múi giờ vào một bảng và duy trì bảng đó khi các quy tắc về múi giờ thay đổi. Sử dụng bảng đó với một loạt logic tùy chỉnh để giải quyết sự chênh lệch cho một ngày cụ thể.
-
Sử dụng
xp_regread
để truy cập các khóa đăng ký Windows có chứa dữ liệu múi giờ và một lần nữa sử dụng một loạt logic tùy chỉnh để giải quyết phần bù cho một ngày cụ thể. Tất nhiên,xp_regread
là một điều tồi tệ để làm, yêu cầu một số quyền nhất định được cấp và không được hỗ trợ hoặc tài liệu. -
Viết hàm SQLCLR sử dụng
TimeZoneInfo
lớp trong .Net. Rất tiếc, này yêu cầu lắp ráp SQLCLR "không an toàn" và có thể khiến những điều tồi tệ xảy ra.
IMHO, không có phương pháp nào trong số này là rất tốt và không có giải pháp nào tốt để thực hiện điều này trực tiếp trong SQL. Giải pháp tốt nhất sẽ là trả về giá trị UTC (số nguyên ban đầu hoặc datetime
tại UTC) sang mã ứng dụng gọi điện của bạn và thực hiện chuyển đổi múi giờ ở đó (ví dụ:với TimeZoneInfo
trong .Net hoặc các cơ chế tương tự trong các nền tảng khác).
TUY NHIÊN - bạn đã may mắn khi Kuwait (và luôn luôn) nằm trong khu vực không thay đổi đối với Giờ tiết kiệm ánh sáng ban ngày. Nó luôn là UTC + 03:00. Vì vậy, bạn có thể chỉ cần thêm ba giờ và trả về kết quả:
SELECT DATEADD(hour, 3, DATEADD(second, yourTimeStamp, '1970-01-01'))
Nhưng hãy lưu ý rằng đây không phải là một giải pháp có mục đích chung sẽ hoạt động ở bất kỳ múi giờ nào.
Nếu muốn, bạn có thể trả về một trong các kiểu dữ liệu SQL khác, chẳng hạn như datetimeoffset
, nhưng điều này sẽ chỉ giúp bạn phản ánh rằng giá trị này bù lại ba giờ cho bất kỳ ai có thể nhìn vào nó. Nó sẽ không làm cho quá trình chuyển đổi khác đi hoặc tốt hơn.
Câu trả lời được cập nhật
Tôi đã tạo một dự án để hỗ trợ múi giờ trong SQL Server. Bạn có thể cài đặt nó từ đây . Sau đó, bạn có thể chỉ cần chuyển đổi như vậy:
SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'Asia/Kuwait')
Bạn có thể sử dụng bất kỳ múi giờ nào từ cơ sở dữ liệu IANA tz , bao gồm cả những nơi sử dụng thời gian tiết kiệm ánh sáng ban ngày.
Bạn vẫn có thể sử dụng phương pháp tôi đã trình bày ở trên để chuyển đổi từ dấu thời gian unix. Đặt cả hai lại với nhau:
SELECT Tzdb.UtcToLocal(DATEADD(second, yourTimeStamp, '1970-01-01'), 'Asia/Kuwait')
Đã cập nhật lại
Với SQL Server 2016, hiện đã có hỗ trợ tích hợp cho múi giờ với AT TIME ZONE
bản tường trình. Điều này cũng có sẵn trong Cơ sở dữ liệu Azure SQL (v12).
SELECT DATEADD(second, yourTimeStamp, '1970-01-01') AT TIME ZONE 'Arab Standard Time'
Các ví dụ khác trong thông báo này.