2012-12-05 13 views
5

La mia situazione è che memorizziamo dati in un database SQL Server, supportando il 2005 in su. Quando un valore DateTime è memorizzato, è nell'ora locale del client. Devo essere in grado di riportare quella data su qualsiasi altro client, ovunque, senza rispettare il fuso orario in cui potrebbe trovarsi l'altro client.Come posso ottenere dati DateTime da SQL Server ignorando i problemi relativi al fuso orario?

Quindi, ad esempio, quando un utente di New York immette un valore DateTime di " 2012-12-20 00:00 ", voglio che l'utente in California visualizzi lo stesso valore DateTime. Questi valori DateTime non dovrebbero rispettare la differenza nei fusi orari, ma è quello che vedo accadere. Attualmente, SQL Server consegnerà tale DateTime all'utente California come "2012-12-19 21:00". Si noti come è ora il giorno precedente a causa del rollback di -3 ore a causa del passaggio da EST a PST (dimenticare i problemi di ora legale per gli scopi di questa conversazione).

Ripristinare i dati restituiti alla lettera e non tradotti dal fuso orario, è ciò che devo realizzare. Quindi quale consiglio puoi offrire?

Alcuni codice da considerare:

Ecco la tabella:

CREATE TABLE [dbo].[tblMeterReadings](
[fldMeterReadingsID] [int] IDENTITY(1,1) NOT NULL, 
[fldMeterID] [int] NOT NULL, 
[fldUser] [varchar](50) NULL, 
[fldBy] [varchar](50) NULL, 
[fldDateOfReading] [datetime] NULL, 
[fldReading] [float] NULL, 
[fldIsArchived] [bit] NULL DEFAULT ((0)), 

Abbiamo una classe di SQL che fa il lavoro, e nel seguente esempio "sql" è un oggetto di tale classe. La chiamata viene effettuata utilizzando una query con parametri dove @ data0 è l'oggetto DateTime per memorizzare in un campo DateTime SQL:

sql.Execute(@"INSERT INTO tblMeterReadings (fldMeterID, fldDateOfReading) VALUES (" + MeterID + ", @data0)", Date); 

definitiva, questo configura uno SqlCommand, assegna parametri e spara una chiamata command.ExecuteNonQuery() .

Ora, per recuperare la data, ho semplicemente selezionare in un DataTable (ancora una volta, utilizzando la nostra classe Sql helper):

DataTable myTable = sql.readDataTable(@"SELECT fldMeterID, fldDateOfReading FROM tblMeterReadings"); 

Quindi quello che vedo è che nel database stesso, la data è " 2012-12-20 00:00 "come mi aspetto, ma quando controllo i contenuti di myTable in debug, vedo che la data in quella tabella è" 2012-12-19 21:00 ".

Il database è stato creato su un server SQL eseguito su una macchina in uno stato EST. La mia macchina, tuttavia, è impostata su PST. Da qui la differenza nel modo in cui il valore DateTime mi viene consegnato nella SELECT.

Cosa mi manca?

+0

Correlati: http://stackoverflow.com/q/2532729/1583 – Oded

+0

Come si scrive la data nel database? Il problema dovrebbe essere risolto semplicemente eliminando le informazioni sul fuso orario dal datetime prima di salvarlo nel database. –

+0

@DanielHilgarth - E se con questo intendi memorizzarlo come UTC, allora sarei d'accordo. Ma ci sono già molti dati e fino a quando non riusciremo a superare una conversione massiccia, mi lascerò tentare di massaggiarlo come ho fatto io. – DonBoitnott

risposta

2

Grazie all'input da parte di voi persone gentili, e qualche ricerca lungo le linee dei vostri suggerimenti, abbiamo risolto il nostro problema.

Un ringraziamento speciale a ebyrob per l'assistenza e questo link: http://support.microsoft.com/kb/842545

Tale nesso in ultima analisi, si è rivelata la pallottola d'argento.

Il problema fondamentale è che quando si costruisce un DataTable o un DataSet, le informazioni sul fuso orario in cui viene creato sono codificate con esso. Quindi, se si passa quell'oggetto attraverso una connessione a una macchina che esiste all'interno di un fuso orario diverso, qualsiasi valore di DateTime in esso verrà regolato in base alla differenza di fuso orario.

Alla luce di ciò, la correzione consiste nell'impostare la proprietà DateTimeMode di tutte le DateColumns DateTime su DataSetDateTime.Unspecified. Ciò impedisce le rettifiche delle date successive alla serializzazione, invece di fornire i valori DateTime testualmente.

Voglio anche sottolineare che l'articolo specifica DataSet, ma abbiamo dimostrato che DataTable è anche vulnerabile. In effetti, sono abbastanza certo che si tratta della DataColumn stessa (quelli con un tipo di DateTime, comunque). Penso che l'articolo lo dichiari pure.

Quindi grazie ancora; Penso che ce l'abbiamo ora!

+0

Grazie per aver pubblicato i risultati dell'indagine. –

2

Memorizza la data UTC nel database. Convertilo solo all'ora locale quando lo visualizzi in un client.

Lato server, utilizzare getutcdate() anziché getdate().

+1

Sono assolutamente d'accordo. Sfortunatamente, questo non è possibile nel breve periodo. In effetti, alcuni clienti hanno già più di 20 anni di dati. Proviene davvero dal fatto che abbiamo sempre "fatto franca" in un database di Access e un recente passaggio a SQL Server ha rivelato questa debolezza. – DonBoitnott

1

ovunque si desidera visualizzare le date in un certo fuso orario si può fare:

DateTime dtDateOfReading = TimeZoneInfo.ConvertTime(
    Convert.ToDateTime(myTables.Rows[i]["fldDateOfReading"]), 
    dtTimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time") 
    ); 

Se si dispone di più di un fuso orario che si desidera visualizzare le cose in, è necessario memorizzare il tempo- zona con la data o con quale sito del cliente.

Nota: Prestare attenzione ai valori di DateTime convertiti perché avranno un tipo di Non specificato che può essere assunto (in modo non corretto) come locale in alcuni casi.

EDIT: Potrebbe essere più facile da impostare solo il fuso orario per la connessione SQL per abbinare il fuso orario del server SQL, ma questo articolo: http://support.microsoft.com/kb/842545 sembra indicare che la configurazione fuso orario potrebbe non essere supportata da almeno SqlDataAdapter.

+0

Ho considerato questo. Ma questo approccio non presuppone che io sappia qualcosa sul fuso orario per cui è stato creato il valore DateTime? Il mio esempio potrebbe suggerire questo, ma non è vero. Ho semplicemente un DateTime, ma bisogna presumere che non ne sappia nulla. In realtà, non mi interessa nemmeno. Se è nel database come "2012-12-20 00:00" è così che lo voglio, come se i fusi orari non esistessero affatto. – DonBoitnott

+0

Si sa che il fuso orario del server SQL è EST. Potresti anche sapere che tutti i tempi del cliente NYSEG sono in EST, ad esempio. (Penso che tu stia davvero guardando una differenza nei fusi orari del server non i singoli fusi orari dei record qui ...) –

+0

Mi sono guardato intorno un po 'per come "impostare il fuso orario per la connessione SQL", come hai affermato nella tua modifica, ma Non ho idea di come. Puoi indicarmi una pagina o fornire una linea di codice di esempio? A proposito: quell'articolo della KB è una buona lettura, e penso, proprio il problema di fondo che sto affrontando. – DonBoitnott

Problemi correlati