Rimozione dell'offset del fuso orario da DateTimeOffset. Rimozione dell'offset del fuso orario dal server SQL con offset della data nullo DateTimeOffset

DateTimeOffset testDateAndTime = nuovo DateTimeOffset(2008, 5, 1, 8, 6, 32, nuovo TimeSpan(1, 0, 0)); //PULIRE ORA E DATA testDateAndTime = testDateAndTime.DateTime.Date; var dateTableEntry = db.DatesTable.First(dt => dt.Id == someTestId); dateTableEntry.test=testDateAndTime; db.SaveChangesAsync();

RISULTATO NEL DATABASE: 2008-05-01 00:00:00.0000000 -04:00

Come abilitare da -4:00 a +00:00 (dal codice prima del salvataggio)?

Ho provato:

Compito pubblico SetTimeZoneOffsetToZero(DateTimeOffset dateTimeOffSetObj) ( TimeSpan zeroOffsetTimeSpan = new TimeSpan(0, 0, 0, 0, 0); return dateTimeOffSetObj.ToOffset(zeroOffsetTimeSpan); )

Non fa nulla.

L'obiettivo finale è semplicemente avere una data senza differenza di ora o fuso orario. NON voglio convertire l'ora in un altro fuso orario (ad esempio 00:00:00.0000000 non voglio che sottragga 4 ore dall'ora 00:00:00.0000000 e 00:00:00.0000000 sfasamenti l'ora impostata di +00 :00, voglio solo che imposti l'offset su +00:00). Voglio la data corrente con zero offset.

Modificare:

Ecco cosa puoi offrire altrove:

DateTimeOffset testDateAndTime = nuovo DateTimeOffset(2008, 5, 1, 8, 6, 32, nuovo TimeSpan(1, 0, 0)); testDateAndTime = testDateAndTime.DateTime.Date; //Azzera la porzione di tempo testDateAndTime = DateTime.SpecifyKind(testDateAndTime.Date, DateTimeKind.Utc); //Porzione di offset "Azzerato".

Ero sicuro che SpecificaKind SpecificaKind my dateTimeOffset, ad esempio modifica SIA l'ora che l'offset del fuso orario, ma una volta testato, sembra cambiare semplicemente l'offset del fuso orario, che è ciò che voglio. C'è un problema con questo?

1 risposta

Il problema non ha nulla a che fare con il database. Se imposti un punto di interruzione o registri un output da qualche parte, dovresti vedere l'offset associato poco dopo questo codice:

TestDateAndTime = testDateAndTime.DateTime.Date;

Analizziamolo:

  • Hai iniziato con DateTimeOffset 2008-05-01T08:06:32+01:00
  • Hai quindi chiamato .DateTime , ottenendo un valore DateTime pari a 2008-05-01T08:06:32 con DateTimeKind.Unspecified .
  • Hai quindi chiamato .Date , che ha prodotto un valore DateTime di 2008-05-01T00:00:00 con DateTimeKind.Unspecified .
  • Restituisci il risultato in testDateAndTime che è di tipo DateTimeOffset . Ciò provoca una conversione implicita da DateTime a DateTimeOffset che applica il fuso orario locale. Nel tuo caso, sembra che l'offset per questo valore nel fuso orario locale sia -04:00 , quindi il valore risultante è DateTimeOffset 2008-05-01T00:00:00-04:00 come hai descritto,

Hai detto:

L'obiettivo finale è semplicemente avere una data senza differenza di ora o fuso orario.

Bene, attualmente non esiste un tipo di dati C# nativo che sia solo una data senza ora. Esiste un tipo Date puro nel pacchetto System.Time in corefxlab, ma non è del tutto pronto per una tipica applicazione di produzione. C'è LocalDate nella libreria temporale di Noda, che puoi utilizzare oggi, ma dovrai comunque riconvertirlo in un tipo nativo prima di salvare nel database. Quindi nel frattempo la cosa migliore che puoi fare è:

  • Modifica il tuo SQL Server per utilizzare il tipo di data in questo campo.
  • Nel codice .NET utilizzare DateTime con l'ora 00:00:00 e DateTimeKind.Unspecified. Devi ricordarti di ignorare la parte relativa all'orario (poiché in alcuni fusi orari ci sono effettivamente date senza mezzanotte locale).
  • Modifica l'avviso di prova in DateTime anziché in DateTimeOffset.

In generale, sebbene DateTimeOffset sia adatto per un numero elevato di scenari (ad esempio eventi di timestamp), non è adatto per valori di sola data.

Voglio la data corrente con zero offset.

Se lo vuoi davvero come DateTimeOffset, faresti:

TestDateAndTime = nuovo DateTimeOffset(testDateAndTime.Date, TimeSpan.Zero);

Tuttavia lo sconsiglio. In questo modo stai prendendo la data locale del valore originale e affermi che è in UTC. Se l'offset originale è diverso da zero, questa sarà un'affermazione falsa. Successivamente porterà ad altri errori poiché in realtà stai parlando di un momento diverso (con potenzialmente una data diversa) rispetto a quello che hai creato.

Per quanto riguarda la domanda aggiuntiva posta nella tua modifica, specificare DateTimeKind.Utc modifica il comportamento del cast implicito. Invece di utilizzare il fuso orario locale, viene utilizzata l'ora UTC, che ha sempre uno spostamento zero. Il risultato è lo stesso della visione più esplicita che ho fornito sopra. Lo sconsiglio comunque per gli stessi motivi.

Diamo un'occhiata all'esempio di inizio dal 2016-12-31T22:00:00-04:00. Secondo il tuo approccio dovresti salvare 2016-12-31T00:00:00+00:00 nel database. Tuttavia, questi sono due momenti diversi nel tempo. Il primo, normalizzato in UTC, sarebbe 2017-01-01T02:00:00+00:00 e il secondo, convertito in un altro fuso orario, sarebbe 2016-12-30T20:00:00-04:00. Si prega di notare il cambiamento delle date nella conversione. Questo probabilmente non è il comportamento che vorresti nella tua applicazione.

L'opzione umana ([è necessario registrarsi per visualizzare il collegamento]).

L'essenza del problema è questa... Se hai accidentalmente distribuito un database su un server SQL con un "date offset" pari a 0, si verifica un problema quando il database contiene un attributo con il tipo TIME, ovvero questo attributo è impostato su 01 /01/0001 10:30:00 o data di registrazione vuota 01.01.0001 00:00:00. Quando si registrano tali dettagli, non vengono registrati.
Su Internet suggeriscono di creare un nuovo database con un offset di 2000.
Ma non volevo davvero creare una nuova base. E cambia il percorso del database per tutti gli utenti.
Quindi ho seguito il percorso in cui è memorizzato questo valore in SQL. L'ho trovato e l'ho cambiato in 2000 e tutto era ok..
E ora passo dopo passo dove cambiare.

Caccia tutti gli utenti.

ATTENZIONE!!!

1. Innanzitutto, crea una copia di backup utilizzando gli strumenti 1C, ad es. caricalo in *.dt
Questo deve essere fatto prima di modificare l’“offset”
Se ciò non viene fatto, nell'intero database ci saranno riferimenti, documenti, ecc.
dove c'è un requisito la data sarà diciamo 02.10.0009
COSA NON È CONSENTITO...
Quindi hai caricato in *.dt

2. Vai a SQL Server Management Studio
Trova la tua base nell'elenco e premi il segno più.
Trova lì la cartella "Tabelle" e aprila.
Si aprirà un gruppo di tavoli, vai in fondo, trova il tavolo
_YearOffset, posizionarsi su di esso e selezionare la voce “Apri tabella” con il tasto destro, vedi Fig. 1
Modificare il valore da 0 a 2000
Chiudere SQL Server Management Studio

3. Vai al configuratore e carica il database precedentemente salvato.

Se ciò non viene fatto, tutte le date avranno l'anno 0009.
Dopo che il database è stato caricato... Puoi andare a 1C e assicurarti che le date siano normali.
Il risultato è che abbiamo modificato l’“offset della data da 0 a 2000”

A volte capita che questa opzione non possa essere utilizzata per un motivo o per l'altro. Poi c'è un'opzione più hardcore ([è necessario registrarsi per visualizzare il collegamento]):

Dichiara il cursore TablesAndFields per

SELEZIONA oggetti.nome come nometabella, colonne.nome come nomecolonna
DA dbo.sysobjects COME oggetti
a sinistra unisci dbo.syscolumns come colonne su object.id = columns.id
dove oggetti.xtype = "U" e colonne.xtype = 61

aprire TablesAndFields

WHILE @@FETCH_STATUS = 0
INIZIO Esegui(" aggiornamento"+ @NomeTabella + "
impostato " + @NomeColonna + " = ""2000- 01- 01 00:00:00" "
Dove " + @NomeColonna + " > ""3999- 12- 31 23:59:59" "")

Questo viene eseguito finché il recupero precedente ha esito positivo.
RECUPERA SUCCESSIVO DA TablesAndFields in @TableName, @ColumnName
FINE

chiudi TabelleECampi
deallocateTablesAndFields
andare

Prima di qualsiasi manipolazione, non dimenticare di fare copie dei database!

Il problema non ha nulla a che fare con il database. Se imposti un punto di interruzione o inserisci un output da qualche parte, dovresti essere in grado di vedere l'offset scattare poco dopo questo codice:

TestDateAndTime = testDateAndTime.DateTime.Date;

Analizziamolo:

  • Hai iniziato con il valore DateTimeOffset 2008-05-01T08:06:32+01:00
  • Hai quindi chiamato .DateTime , che ha prodotto il valore DateTime 2008-05-01T08:06:32 con DateTimeKind.Unspecified .
  • Hai quindi chiamato .Date , che ha prodotto un valore DateTime di 2008-05-01T00:00:00 con DateTimeKind.Unspecified .
  • Assegni il risultato a testDateAndTime , che è di tipo DateTimeOffset . Ciò provoca un cast implicito da DateTime a DateTimeOffset - , che si applica Locale Fuso orario. Nel tuo caso, sembra che l'offset per questo valore nel fuso orario locale sia -04:00 , quindi il valore risultante è DateTimeOffset di 2008-05-01T00:00:00-04:00 come hai descritto.

Hai detto:

L'obiettivo finale è semplicemente avere una data senza differenza di ora o fuso orario.

Bene, c'è attualmente non un tipo di dati C# nativo, che è solo una data senza ora. È presente un tipo Date puro System.Time pacchetto in corefxlab, ma non è ancora del tutto pronto per una tipica applicazione di produzione. C'è un LocalDate nella libreria Noda Time che puoi utilizzare oggi, ma dovrai comunque riconvertirlo in un tipo nativo prima di salvare nel database. Quindi nel frattempo la cosa migliore che puoi fare è:

  • Modifica il tuo SQL Server per utilizzare il tipo di data nel campo.
  • Nel codice .NET utilizzare DateTime con l'ora 00:00:00 e DateTimeKind.Unspecified. Devi ricordarti di ignorare la parte relativa all'orario (poiché in alcuni fusi orari ci sono effettivamente date senza mezzanotte locale).
  • Modificare la prop del test in modo che sia DateTime anziché DateTimeOffset.

In generale, mentre DateTimeOffset è adatto a un gran numero di scenari (es timestamp events), non si adatta bene ai valori di sola data.

Voglio la data corrente con zero offset.

Se tu vorrei davveroè come DateTimeOffset , potresti fare:

TestDateAndTime = nuovo DateTimeOffset(testDateAndTime.Date, TimeSpan.Zero);

Tuttavia, non consiglio di farlo. Facendo questo prendi Locale la data del valore originale e affermare che è in UTC. Se l'offset originale è diverso da zero, questa sarà un'affermazione falsa. Successivamente porterà ad altri errori poiché in realtà stai parlando di un momento diverso (con potenzialmente una data diversa) rispetto a quello che hai creato.

Per quanto riguarda la domanda aggiuntiva posta al vostro consiglio. La specifica di DateTimeKind.Utc modifica il comportamento del cast implicito. Invece di utilizzare il fuso orario locale, viene utilizzata l'ora UTC, che ha sempre uno spostamento zero. Il risultato è lo stesso della visione più esplicita che ho fornito sopra. Lo sconsiglio comunque per gli stessi motivi.

Considera un esempio che inizia con 2016-12-31T22:00:00-04:00. Secondo il tuo approccio dovresti salvare 2016-12-31T00:00:00+00:00 nel database. Tuttavia, questi sono due momenti diversi nel tempo. Il primo, normalizzato in UTC, sarebbe 2017-01-01T02:00:00+00:00 e il secondo, convertito in un altro fuso orario, sarebbe 2016-12-30T20:00:00-04:00. Si prega di notare il cambiamento delle date nella conversione. Questo probabilmente non è il comportamento che vorresti nella tua applicazione.

Pubblicazioni sull'argomento