Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Conversione di data e ora da fuso orario a fuso orario nel server sql

I timestamp Unix sono numeri interi di secondi dal 1 gennaio 1970 UTC.

Supponendo che tu intenda dire che hai una colonna intera nel tuo database con questo numero, il fuso orario del tuo server di database è irrilevante.

Per prima cosa converti il ​​timestamp in un datetime digita:

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

Questo sarà il datetime UTC che corrisponde al tuo timestamp.

Quindi devi sapere come adattare questo valore al tuo fuso orario target. In gran parte del mondo, una singola zona può avere più offset, a causa dell'ora legale.

Sfortunatamente, SQL Server non è in grado di lavorare direttamente con i fusi orari di lavoro. Quindi, se, ad esempio, utilizzassi l'ora del Pacifico degli Stati Uniti, non avresti modo di sapere se devi sottrarre 7 o 8 ore. Altri database (Oracle, Postgres, MySql, ecc.) hanno modi integrati per gestirlo, ma purtroppo SQL Server non lo fa. Quindi, se stai cercando una soluzione generica, dovrai eseguire una delle seguenti operazioni:

  • Importa i dati del fuso orario in una tabella e mantieni tale tabella quando le regole del fuso orario cambiano. Usa quella tabella con una serie di logica personalizzata per risolvere l'offset per una data particolare.

  • Usa xp_regread per ottenere le chiavi del registro di Windows che contengono dati sul fuso orario e utilizzare ancora una volta una serie di logica personalizzata per risolvere l'offset per una data particolare. Naturalmente, xp_regread è una brutta cosa da fare, richiede determinate autorizzazioni concesse e non è supportato o documentato.

  • Scrivete una funzione SQLCLR che utilizzi TimeZoneInfo classe in .Net. Sfortunatamente, questo richiede un assembly SQLCLR "non sicuro" , e potrebbe causare il verificarsi di cose brutte.

IMHO, nessuno di questi approcci è molto buono e non esiste una buona soluzione per farlo direttamente in SQL. La soluzione migliore sarebbe restituire il valore UTC (o il numero intero originale o il datetime a UTC) al codice dell'applicazione chiamante ed eseguire invece la conversione del fuso orario lì (con, ad esempio, TimeZoneInfo in .Net o meccanismi simili in altre piattaforme).

TUTTAVIA - sei stato fortunato perché il Kuwait è (ed è sempre stato) in una zona che non cambia per l'ora legale. È sempre stato UTC+03:00. Quindi puoi semplicemente aggiungere tre ore e restituire il risultato:

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

Ma riconosci che questa non è una soluzione generica che funzionerà in qualsiasi fuso orario.

Se lo desideri, puoi restituire uno degli altri tipi di dati SQL, come datetimeoffset , ma questo ti aiuterà solo a riflettere sul fatto che il valore è sfalsato di tre ore rispetto a chiunque lo guardi. Non renderà il processo di conversione diverso o migliore.

Risposta aggiornata

Ho creato un progetto per supportare i fusi orari in SQL Server. Puoi installarlo da qui . Quindi puoi semplicemente convertire in questo modo:

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

Puoi utilizzare qualsiasi fuso orario dal database IANA tz , compresi quelli che utilizzano l'ora legale.

Puoi ancora usare il metodo che ho mostrato sopra per convertire da un timestamp unix. Mettendoli entrambi insieme:

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

Aggiornato di nuovo

Con SQL Server 2016 è ora disponibile il supporto integrato per i fusi orari con AT TIME ZONE dichiarazione. Questo è disponibile anche nel database SQL di Azure (v12).

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

Altri esempi in questo annuncio.