Uniksowe znaczniki czasu to całkowita liczba sekund od 1 stycznia 1970 UTC.
Zakładając, że masz na myśli, że masz w bazie danych kolumnę liczb całkowitych o tym numerze, strefa czasowa serwera bazy danych jest nieistotna.
Najpierw przekonwertuj znacznik czasu na datetime
typ:
SELECT DATEADD(second, yourTimeStamp, '1970-01-01')
To będzie czas UTC datetime
który odpowiada Twojej sygnaturze czasowej.
Następnie musisz wiedzieć, jak dostosować tę wartość do docelowej strefy czasowej. W dużej części świata pojedyncza strefa może mieć wiele przesunięć ze względu na czas letni.
Niestety SQL Server nie ma możliwości bezpośredniej pracy w strefach czasowych. Jeśli więc używałbyś na przykład czasu pacyficznego, nie miałbyś możliwości sprawdzenia, czy należy odjąć 7 godzin, czy 8 godzin. Inne bazy danych (Oracle, Postgres, MySql itp.) mają wbudowane sposoby obsługi tego, ale niestety SQL Server nie. Jeśli więc szukasz rozwiązania ogólnego przeznaczenia, musisz wykonać jedną z następujących czynności:
-
Importuj dane stref czasowych do tabeli i utrzymuj tę tabelę w miarę zmiany reguł dotyczących stref czasowych. Użyj tej tabeli z mnóstwem niestandardowej logiki, aby rozwiązać przesunięcie dla określonej daty.
-
Użyj
xp_regread
aby uzyskać dostęp do kluczy rejestru systemu Windows, które zawierają dane strefy czasowej, i ponownie użyć kilku niestandardowej logiki, aby rozwiązać przesunięcie dla określonej daty. Oczywiściexp_regread
jest złą rzeczą, wymaga przyznania pewnych uprawnień i nie jest obsługiwana ani dokumentowana. -
Napisz funkcję SQLCLR, która używa
TimeZoneInfo
klasa w .Net. Niestety, ten wymaga „niebezpiecznego” zestawu SQLCLR i może spowodować złe rzeczy.
IMHO, żadne z tych podejść nie jest bardzo dobre i nie ma dobrego rozwiązania, aby zrobić to bezpośrednio w SQL. Najlepszym rozwiązaniem byłoby zwrócenie wartości UTC (albo oryginalnej liczby całkowitej, albo datetime
w UTC) do kodu aplikacji wywołującej i zamiast tego wykonaj konwersję strefy czasowej (na przykład za pomocą TimeZoneInfo
w .Net lub podobnych mechanizmach na innych platformach).
JEDNAK - masz szczęście, że Kuwejt jest (i zawsze był) w strefie, która nie zmienia się na czas letni. Zawsze było UTC+03:00. Możesz więc po prostu dodać trzy godziny i zwrócić wynik:
SELECT DATEADD(hour, 3, DATEADD(second, yourTimeStamp, '1970-01-01'))
Pamiętaj jednak, że nie jest to rozwiązanie ogólnego przeznaczenia, które będzie działać w dowolnej strefie czasowej.
Jeśli chcesz, możesz zwrócić jeden z pozostałych typów danych SQL, taki jak datetimeoffset
, ale pomoże to tylko zauważyć, że wartość jest przesunięta o trzy godziny dla każdego, kto może na nią spojrzeć. Nie zmieni to procesu konwersji ani nie zmieni go.
Zaktualizowana odpowiedź
Stworzyłem projekt do obsługi stref czasowych w SQL Server. Możesz go zainstalować tutaj . Następnie możesz po prostu przekonwertować w ten sposób:
SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'Asia/Kuwait')
Możesz użyć dowolnej strefy czasowej z bazy danych IANA tz , w tym te, które korzystają z czasu letniego.
Nadal możesz użyć metody, którą pokazałem powyżej, aby przekonwertować ze znacznika czasu uniksowego. Łącząc je razem:
SELECT Tzdb.UtcToLocal(DATEADD(second, yourTimeStamp, '1970-01-01'), 'Asia/Kuwait')
Ponowna aktualizacja
W SQL Server 2016 jest teraz wbudowana obsługa stref czasowych z AT TIME ZONE
oświadczenie. Jest to również dostępne w Azure SQL Database (v12).
SELECT DATEADD(second, yourTimeStamp, '1970-01-01') AT TIME ZONE 'Arab Standard Time'
Więcej przykładów w tym ogłoszeniu.