sql >> Databasteknik >  >> RDS >> Sqlserver

Konvertering av datum och tid från tidszon till tidszon i sql-server

Unix tidsstämplar är heltal antal sekunder sedan 1 januari 1970 UTC.

Om du antar att du menar att du har en heltalskolumn i din databas med detta nummer, så är tidszonen för din databasserver irrelevant.

Konvertera först tidsstämpeln till en datetime typ:

SELECT DATEADD(second, yourTimeStamp, '1970-01-01')

Detta kommer att vara UTC datetime som motsvarar din tidsstämpel.

Då måste du veta hur du justerar detta värde till din måltidszon. I stora delar av världen kan en enda zon ha flera förskjutningar, på grund av sommartid.

Tyvärr har SQL Server ingen möjlighet att arbeta direkt med arbetstidszoner. Så om du till exempel använde amerikansk Stillahavstid, skulle du inte ha något sätt att veta om du skulle subtrahera 7 timmar eller 8 timmar. Andra databaser (Oracle, Postgres, MySql, etc.) har inbyggda sätt att hantera detta, men tyvärr gör inte SQL Server det. Så om du letar efter en allmän lösning måste du göra något av följande:

  • Importera tidszonsdata till en tabell och underhåll den tabellen när tidszonsreglerna ändras. Använd den tabellen med en massa anpassad logik för att lösa offset för ett visst datum.

  • Använd xp_regread för att komma till Windows-registernycklarna som innehåller tidszonsdata, och återigen använda en massa anpassad logik för att lösa offset för ett visst datum. Naturligtvis xp_regread är en dålig sak att göra, kräver vissa beviljade behörigheter och stöds inte eller dokument.

  • Skriv en SQLCLR-funktion som använder TimeZoneInfo klass i .Net. Tyvärr kräver denna en "osäker" SQLCLR-sammansättning , och kan få dåliga saker att hända.

IMHO, ingen av dessa metoder är särskilt bra, och det finns ingen bra lösning för att göra detta direkt i SQL. Den bästa lösningen skulle vara att returnera UTC-värdet (antingen det ursprungliga heltal eller datetime vid UTC) till din uppringande applikationskod och gör tidszonskonverteringen där istället (med t.ex. TimeZoneInfo i .Net eller liknande mekanismer på andra plattformar).

MEN - du har haft tur att Kuwait är (och alltid har varit) i en zon som inte förändras för sommartid. Det har alltid varit UTC+03:00. Så du kan helt enkelt lägga till tre timmar och returnera resultatet:

SELECT DATEADD(hour, 3, DATEADD(second, yourTimeStamp, '1970-01-01'))

Men inse att detta inte är en generell lösning som fungerar i vilken tidszon som helst.

Om du vill kan du returnera en av de andra SQL-datatyperna, till exempel datetimeoffset , men det här hjälper dig bara att återspegla att värdet är tre timmars förskjutning till den som kan titta på det. Det kommer inte att göra omvandlingsprocessen annorlunda eller bättre.

Uppdaterat svar

Jag har skapat ett projekt för att stödja tidszoner i SQL Server. Du kan installera det härifrån . Sedan kan du helt enkelt konvertera så här:

SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'Asia/Kuwait')

Du kan använda valfri tidszon från IANA tz-databasen , inklusive de som använder sommartid.

Du kan fortfarande använda metoden jag visade ovan för att konvertera från en unix-tidsstämpel. Att sätta ihop dem båda:

SELECT Tzdb.UtcToLocal(DATEADD(second, yourTimeStamp, '1970-01-01'), 'Asia/Kuwait')

Uppdaterat igen

Med SQL Server 2016 finns det nu inbyggt stöd för tidszoner med AT TIME ZONE påstående. Detta är också tillgängligt i Azure SQL Database (v12).

SELECT DATEADD(second, yourTimeStamp, '1970-01-01') AT TIME ZONE 'Arab Standard Time'

Fler exempel i detta tillkännagivande.




  1. Kontrollera hur många postförsändelser som finns i kön i Databas Mail i SQL Server (T-SQL)

  2. Hur skapar man en pivottabell i Transact/SQL?

  3. Ansluter till Oracle-databas med Node.js Windows

  4. Lägg till kolumner i en befintlig tabell i SQL Server Database