Odebírání posunu časového pásma z DateTimeOffset. Odebrání posunu časového pásma ze serveru DateTimeOffset Posun data s nulovým datem SQL

DateTimeOffset testDateAndTime = new DateTimeOffset(2008, 5, 1, 8, 6, 32, new TimeSpan(1, 0, 0)); //VYČISTIT ČAS A DATUM testDateAndTime = testDateAndTime.DateTime.Date; var dateTableEntry = db.DatesTable.First(dt => dt.Id == someTestId); dateTableEntry.test= testDateAndTime; db.SaveChangesAsync();

VÝSLEDEK V DATABÁZI: 2008-05-01 00:00:00.0000000 -04:00

Jak povolit -4:00 až +00:00 (z kódu před uložením)?

Zkusil jsem:

Veřejný úkol SetTimeZoneOffsetToZero(DateTimeOffset dateTimeOffSetObj) (TimeSpan zeroOffsetTimeSpan = new TimeSpan(0, 0, 0, 0, 0); return dateTimeOffSetObj.ToOffset(zeroOffsetTimeSpan); )

Nedělá nic.

Konečným cílem je jednoduše mít datum bez posunu času nebo časového pásma. NECHCI převádět čas na jiné časové pásmo (tj. nechci, aby 00:00:00.0000000 odečítalo 4 hodiny od času 00:00:00.0000000 a 00:00:00.0000000 posunulo nastavený čas o +00 :00, jen chci, aby nastavil posun na +00:00). Chci aktuální datum s nulovým posunem.

Upravit:

Zde je to, co můžete nabídnout jinde:

DateTimeOffset testDateAndTime = new DateTimeOffset(2008, 5, 1, 8, 6, 32, new TimeSpan(1, 0, 0)); testDateAndTime = testDateAndTime.DateTime.Date; //Vynulování časové části testDateAndTime = DateTime.SpecifyKind(testDateAndTime.Date, DateTimeKind.Utc); //"Vynulovat" část offsetu

Byl jsem si jistý, že SpecifyKind by specifikoval můj dateTimeOffset, jako by změnil JAK posun času a časového pásma, ale při testování se zdá, že jen mění posun časového pásma, což je to, co chci. Je s tím problém?

1 odpověď

Problém nemá nic společného s databází. Pokud nastavíte bod přerušení nebo někde zaregistrujete výstup, měli byste vidět, že offset je vázán krátce po tomto kódu:

TestDateAndTime = testDateAndTime.DateTime.Date;

Pojďme si to rozebrat:

  • Začali jste s DateTimeOffset 2008-05-01T08:06:32+01:00
  • Potom jste zavolali .DateTime, což vedlo k hodnotě DateTime 2008-05-01T08:06:32 s DateTimeKind.Unspecified.
  • Potom jste zavolali .Date, což vedlo k hodnotě DateTime 2008-05-01T00:00:00 s DateTimeKind.Unspecified.
  • Výsledek vrátíte v testDateAndTime, který je typu DateTimeOffset . To způsobí implicitní převod z DateTime na DateTimeOffset který používá místní časové pásmo. Ve vašem případě se zdá, že posun pro tuto hodnotu ve vašem místním časovém pásmu je -04:00 , takže výsledná hodnota je DateTimeOffset 2008-05-01T00:00:00-04:00, jak jste popsali,

Řekl jsi:

Konečným cílem je jednoduše mít datum bez posunu času nebo časového pásma.

No, v současné době neexistuje žádný nativní datový typ C#, který je pouze datem bez času. V balíku System.Time v corefxlab je čistý typ Date, ale není zcela připraven pro typickou produkční aplikaci. V časové knihovně Noda je LocalDate, který můžete používat již dnes, ale před uložením do databáze budete muset převést zpět na nativní typ. Takže mezitím to nejlepší, co můžete udělat, je:

  • Změňte svůj SQL Server tak, aby v tomto poli používal typ data.
  • V kódu .NET použijte DateTime s časem 00:00:00 a DateTimeKind.Unspecified. Nezapomeňte ignorovat časovou část (protože v určitých časových pásmech skutečně existují data bez místní půlnoci).
  • Změňte testovací upozornění na DateTime spíše než DateTimeOffset.

Obecně platí, že zatímco DateTimeOffset je vhodný pro velké množství scénářů (jako jsou události s časovým razítkem), není vhodný pro hodnoty pouze pro datum.

Chci aktuální datum s nulovým posunem.

Pokud to opravdu chcete jako DateTimeOffset, udělali byste:

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

To však nedoporučuji. Tímto způsobem berete místní datum původní hodnoty a tvrdíte, že je v UTC. Pokud je původní offset něco jiného než nula, bude to nepravdivé tvrzení. Následně to povede k dalším chybám, protože ve skutečnosti mluvíte o jiném časovém okamžiku (s potenciálně jiným datem), než který jste vytvořili.

Pokud jde o další otázku položenou ve vaší úpravě - zadání DateTimeKind.Utc změní chování implicitního přetypování. Místo použití místního časového pásma se používá čas UTC, který má vždy nulový posun. Výsledek je stejný jako názornější pohled, který jsem uvedl výše. Stále to doporučuji ze stejných důvodů.

Podívejme se na příklad začátku od 2016-12-31T22:00:00-04:00. Podle vašeho přístupu byste měli uložit 2016-12-31T00:00:00+00:00 do databáze. Jedná se však o dva různé časové body. První, normalizovaný na UTC, by byl 2017-01-01T02:00:00+00:00 a druhý, převedený na jiné časové pásmo, by byl 2016-12-30T20:00:00-04:00. Vezměte prosím na vědomí změnu dat v převodu. Toto pravděpodobně není chování, které byste ve své aplikaci chtěli.

Humánní možnost ([pro zobrazení odkazu se musíte zaregistrovat]).

Podstata problému je v tomto.. Pokud jste omylem nasadili databázi na SQL server s „datovým offsetem“ 0, pak nastává problém, když databáze obsahuje atribut s typem TIME, tedy tento atribut je nastaven na 01 /01/0001 10:30:00 nebo datum registrace prázdné 01.01.0001 00:00:00. Při záznamu takových detailů se nezaznamenávají.
Na internetu navrhují vytvoření nové databáze s offsetem 2000.
Ale ve skutečnosti jsem nechtěl vytvářet novou základnu. A změnit cestu k databázi pro všechny uživatele.
Pak jsem sledoval cestu, kde je tato hodnota uložena v SQL. Našel jsem to a změnil na 2000 a vše bylo v pořádku.
A teď krok za krokem, kde se změnit.

Vykopněte všechny uživatele.

POZORNOST!!!

1. Nejprve vytvořte záložní kopii pomocí nástrojů 1C, tzn. nahrajte jej do *.dt
Toto je nutné provést před změnou „offsetu“
Pokud tak neučiníte, pak v celé vaší databázi budou odkazy, dokumenty atd.
kde je požadavek, datum bude řekněme 02.10.0009
CO NENÍ POVOLENO...
Takže jste nahráli do *.dt

2. Přejděte do SQL Server Management Studio
Najděte svou základnu v seznamu a stiskněte znaménko plus.
Najděte tam složku „Tabulky“ a otevřete ji.
Otevře se hromada stolů, jděte až úplně dole, najděte stůl
_YearOffset, postavte se na něj a pravým tlačítkem vyberte položku „Otevřít tabulku“, viz obr. 1
Změňte hodnotu 0 na 2000
Zavřete SQL Server Management Studio

3. Přejděte do konfigurátoru a načtěte dříve uloženou databázi.

Pokud tak neučiníte, všechna data budou s rokem 0009.
Po načtení databáze... Můžete přejít na 1C a ujistit se, že data jsou normální.
Výsledkem je, že jsme změnili „posun data z 0 na 2000“

Někdy se stane, že tuto možnost nelze z toho či onoho důvodu využít. Pak je tu tvrdší možnost ([pro zobrazení odkazu se musíte zaregistrovat]):

Deklarujte kurzor TablesAndFields pro

SELECT Objects.name jako Tablename, columns.name jako columnname
Z dbo.sysobjects tak jako objektů
levé spojení dbo.syscolumns jako sloupce na objects.id = columns.id
kde objects.xtype = "U" a columns.xtype = 61

otevřete TablesAndFields

WHILE @@FETCH_STATUS = 0
BEGIN Exec(" Aktualizace"+ @TableName + "
nastavit " + @ColumnName + " = ""2000- 01- 01 00:00:00" "
kde" + @ColumnName + " > ""3999- 12- 31 23:59:59" "")

To se provádí, dokud je předchozí načtení úspěšné.
NAČÍST NEXT Z TablesAndFields do @TableName, @ColumnName
KONEC

zavřete TablesAndFields
deallocateTablesAndFields
jít

Před jakoukoliv manipulací si nezapomeňte pořídit kopie databází!

Problém nemá nic společného s databází. Pokud nastavíte bod přerušení nebo někde zadáte výstup, měli byste vidět, jak se offset zachytí krátce po tomto kódu:

TestDateAndTime = testDateAndTime.DateTime.Date;

Pojďme si to rozebrat:

  • Začali jste s hodnotou DateTimeOffset 2008-05-01T08:06:32+01:00
  • Potom jste zavolali .DateTime, což vedlo k hodnotě DateTime 2008-05-01T08:06:32 s DateTimeKind.Unspecified.
  • Potom jste zavolali .Date, což vedlo k hodnotě DateTime 2008-05-01T00:00:00 s DateTimeKind.Unspecified.
  • Výsledek přiřadíte k testDateAndTime , což je typ DateTimeOffset . To způsobí implicitní přetypování z DateTime na DateTimeOffset - , která platí místníČasové pásmo. Ve vašem případě se zdá, že posun pro tuto hodnotu ve vašem místním časovém pásmu je -04:00 , takže výsledná hodnota je DateTimeOffset z 2008-05-01T00:00:00-04:00, jak jste popsali.

Řekl jsi:

Konečným cílem je jednoduše mít datum bez posunu času nebo časového pásma.

No, je v současné době není nativní datový typ C#, což je pouze datum bez času. Existuje čistý typ Date Systémový čas balíček v corefxlabu, ale ještě není zcela připraven pro typickou produkční aplikaci. V knihovně Noda Time je LocalDate, které můžete použít dnes, ale před uložením do databáze budete muset převést zpět na nativní typ. Takže mezitím to nejlepší, co můžete udělat, je:

  • Změňte svůj SQL Server tak, aby v poli používal typ data.
  • V kódu .NET použijte DateTime s časem 00:00:00 a DateTimeKind.Unspecified. Nezapomeňte ignorovat časovou část (protože v určitých časových pásmech skutečně existují data bez místní půlnoci).
  • Změňte testovací prop tak, aby byl DateTime spíše než DateTimeOffset.

Obecně platí, že zatímco DateTimeOffset je vhodný pro velké množství scénářů (např časová razítka události), nehodí se pro hodnoty pouze pro datum.

Chci aktuální datum s nulovým posunem.

jestli ty opravdu chci je to jako DateTimeOffset , můžete udělat:

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

Nicméně nedoporučuji to dělat. Tím si vezmete místní datum původní hodnoty a tvrzení, že je v UTC. Pokud je původní offset něco jiného než nula, bude to nepravdivé tvrzení. Následně to povede k dalším chybám, protože ve skutečnosti mluvíte o jiném časovém okamžiku (s potenciálně jiným datem), než který jste vytvořili.

Ohledně dodatečné otázky položené vaší radě. Zadáním DateTimeKind.Utc se změní chování implicitního přetypování. Místo použití místního časového pásma se používá čas UTC, který má vždy nulový posun. Výsledek je stejný jako názornější pohled, který jsem uvedl výše. Stále to nedoporučuji ze stejných důvodů.

Zvažte příklad začínající 2016-12-31T22:00:00-04:00. Podle vašeho přístupu byste měli uložit 2016-12-31T00:00:00+00:00 do databáze. Jedná se však o dva různé časové body. První, normalizovaný na UTC, by byl 2017-01-01T02:00:00+00:00 a druhý, převedený na jiné časové pásmo, by byl 2016-12-30T20:00:00-04:00. Vezměte prosím na vědomí změnu dat v převodu. Toto pravděpodobně není chování, které byste ve své aplikaci chtěli.

Publikace na dané téma