Odstraňuje sa posun časového pásma z DateTimeOffset. Odstránenie posunu časového pásma zo servera DateTimeOffset s nulovým posunom dátumu

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

VÝSLEDOK V DATABÁZE: 2008-05-01 00:00:00.0000000 -04:00

Ako povoliť -4:00 až +00:00 (od kódu pred uložením)?

Skúsil som:

Verejná úloha SetTimeZoneOffsetToZero(DateTimeOffset dateTimeOffSetObj) (TimeSpan zeroOffsetTimeSpan = new TimeSpan(0, 0, 0, 0, 0); return dateTimeOffSetObj.ToOffset(zeroOffsetTimeSpan); )

Nerobí nič.

Konečným cieľom je jednoducho mať dátum bez posunu času alebo časového pásma. NECHCEM previesť čas na iné časové pásmo (t. j. 00:00:00.0000000 nechcem, aby odpočítalo 4 hodiny od času 00:00:00.0000000 a 00:00:00,0000000 posunulo nastavený čas o +00 :00, len chcem, aby sa nastavil posun na +00:00). Chcem aktuálny dátum s nulovým posunom.

Upraviť:

Tu je to, čo môžete ponúknuť inde:

DateTimeOffset testDateAndTime = new DateTimeOffset(2008, 5, 1, 8, 6, 32, new TimeSpan(1, 0, 0)); testDateAndTime = testDateAndTime.DateTime.Date; //Vynulovanie časovej časti testDateAndTime = DateTime.SpecifyKind(testDateAndTime.Date, DateTimeKind.Utc); //"Vynulovať" časť posunu

Bol som si istý, že SpecifyKind by špecifikoval môj dátum a čas posunutia, ako keby zmenil posun času aj časového pásma, ale pri testovaní sa zdá, že iba zmenil posun časového pásma, čo chcem. je s tym nejaky problem?

1 odpoveď

Problém nemá nič spoločné s databázou. Ak nastavíte bod prerušenia alebo niekde zaregistrujete výstup, krátko po tomto kóde by ste mali vidieť viazanie posunu:

TestDateAndTime = testDateAndTime.DateTime.Date;

Poďme si to rozobrať:

  • Začali ste s DateTimeOffset 2008-05-01T08:06:32+01:00
  • Potom ste zavolali .DateTime, výsledkom čoho bola hodnota DateTime 2008-05-01T08:06:32 s DateTimeKind.Unspecified.
  • Potom ste zavolali .Date, čo viedlo k hodnote DateTime 2008-05-01T00:00:00 s DateTimeKind.Unspecified.
  • Výsledok vrátite v testDateAndTime, ktorý je typu DateTimeOffset . To spôsobí implicitnú konverziu z DateTime na DateTimeOffset ktorý používa miestne časové pásmo. Vo vašom prípade sa zdá, že posun pre túto hodnotu vo vašom miestnom časovom pásme je -04:00 , takže výsledná hodnota je DateTimeOffset 2008-05-01T00:00:00-04:00, ako ste opísali,

Povedal si:

Konečným cieľom je jednoducho mať dátum bez posunu času alebo časového pásma.

V súčasnosti neexistuje žiadny natívny dátový typ C#, ktorý by bol len dátumom bez času. V balíku System.Time v corefxlab je čistý typ Date, ale nie je celkom pripravený na typickú produkčnú aplikáciu. V časovej knižnici Noda je LocalDate, ktorý môžete použiť už dnes, ale pred uložením do databázy budete musieť previesť späť na natívny typ. Takže medzitým najlepšie, čo môžete urobiť, je:

  • Zmeňte svoj SQL Server tak, aby v tomto poli používal typ dátumu.
  • Vo svojom kóde .NET použite DateTime s časom 00:00:00 a DateTimeKind.Unspecified. Nezabudnite ignorovať časovú časť (pretože v určitých časových pásmach skutočne existujú dátumy bez miestnej polnoci).
  • Zmeňte testovacie upozornenie na DateTime namiesto DateTimeOffset.

Vo všeobecnosti platí, že zatiaľ čo DateTimeOffset je vhodný pre veľký počet scenárov (ako sú udalosti s časovou pečiatkou), nie je vhodný pre hodnoty len s dátumom.

Chcem aktuálny dátum s nulovým posunom.

Ak to naozaj chcete ako DateTimeOffset, urobili by ste:

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

Toto však neodporúčam. Týmto preberáte miestny dátum pôvodnej hodnoty a tvrdíte, že je v UTC. Ak je pôvodný posun iný ako nula, bude to nepravdivé tvrdenie. Následne to povedie k ďalším chybám, pretože v skutočnosti hovoríte o inom časovom bode (s potenciálne iným dátumom), ako je ten, ktorý ste vytvorili.

Čo sa týka dodatočnej otázky položenej vo vašej úprave – zadanie DateTimeKind.Utc zmení správanie implicitného pretypovania. Namiesto použitia miestneho časového pásma sa používa čas UTC, ktorý má vždy nulový posun. Výsledok je rovnaký ako explicitnejší názor, ktorý som uviedol vyššie. Stále to neodporúčam z rovnakých dôvodov.

Pozrime sa na príklad začiatku od 2016-12-31T22:00:00-04:00. Podľa vášho prístupu by ste mali uložiť 2016-12-31T00:00:00+00:00 do databázy. Ide však o dva rozdielne časové body. Prvý, normalizovaný na UTC, by bol 2017-01-01T02:00:00+00:00 a druhý, prevedený na iné časové pásmo, by bol 2016-12-30T20:00:00-04:00. Upozorňujeme na zmenu dátumov v konverzii. Toto pravdepodobne nie je správanie, ktoré by ste vo svojej aplikácii chceli.

Humánna možnosť ([na zobrazenie odkazu sa musíte zaregistrovať]).

Podstata problému je v tomto.. Ak ste omylom nasadili databázu na SQL server s „date offsetom“ 0, potom nastáva problém, keď databáza obsahuje atribút typu TIME, t.j. tento atribút je nastavený na 01 /01/0001 10:30:00 alebo dátum zaregistrovaný prázdny 01.01.0001 00:00:00. Pri nahrávaní takýchto detailov sa to nezaznamenáva.
Na internete navrhujú vytvorenie novej databázy s offsetom 2000.
Ale v skutočnosti som nechcel vytvoriť novú základňu. A zmeniť cestu k databáze pre všetkých používateľov.
Potom som sledoval cestu, kde je táto hodnota uložená v SQL. Našiel som to a zmenil na 2000 a všetko bolo ok..
A teraz krok za krokom kde zmeniť.

Vykopnite všetkých používateľov.

POZOR!!!

1. Najprv vytvorte záložnú kópiu pomocou nástrojov 1C, t.j. nahrajte ho do *.dt
Toto je potrebné urobiť pred zmenou „offsetu“
Ak sa tak nestane, potom v celej vašej databáze budú referencie, dokumenty atď.
kde je požiadavka, dátum bude 02.10.0009
ČO NIE JE POVOLENÉ...
Takže ste nahrali do *.dt

2. Prejdite do SQL Server Management Studio
Nájdite svoju základňu v zozname a stlačte znamienko plus.
Nájdite tam priečinok „Tabuľky“ a otvorte ho.
Otvorí sa hromada stolov, choďte úplne dole, nájdite stôl
_YearOffset, postavte sa naň a pravým tlačidlom vyberte položku „Otvoriť tabuľku“, viď obr.
Zmeňte hodnotu 0 na 2000
Zatvorte SQL Server Management Studio

3. Prejdite do konfigurátora a načítajte predtým uloženú databázu.

Ak sa tak nestane, všetky dátumy budú s rokom 0009.
Po načítaní databázy... Môžete prejsť na 1C a uistiť sa, že dátumy sú normálne.
Výsledkom je, že sme zmenili „posun dátumu z 0 na 2000“

Niekedy sa stáva, že túto možnosť nemožno použiť z jedného alebo druhého dôvodu. Potom je tu tvrdšia možnosť ([na zobrazenie odkazu sa musíte zaregistrovať]):

Deklarovať TablesAndFields kurzor pre

SELECT objects.name ako Tablename, columns.name ako columnname
Z dbo.sysobjects ako predmety
ľavé spojenie dbo.syscolumns ako stĺpce na objects.id = columns.id
kde objects.xtype = "U" a columns.xtype = 61

otvorte TablesAndFields

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

Toto sa vykonáva, pokiaľ je predchádzajúce načítanie úspešné.
FETCH NEXT FROM FROM TablesAndFields do @TableName, @ColumnName
KONIEC

zatvorte TablesAndFields
deallocateTablesAndFields
ísť

Pred akýmikoľvek manipuláciami si nezabudnite urobiť kópie databáz!

Problém nemá nič spoločné s databázou. Ak nastavíte bod prerušenia alebo niekde zadáte výstup, mali by ste vidieť, ako sa offset zachytí krátko po tomto kóde:

TestDateAndTime = testDateAndTime.DateTime.Date;

Poďme si to rozobrať:

  • Začali ste s hodnotou DateTimeOffset 2008-05-01T08:06:32+01:00
  • Potom ste zavolali .DateTime, čo viedlo k hodnote DateTime 2008-05-01T08:06:32 s DateTimeKind.Unspecified.
  • Potom ste zavolali .Date, čo viedlo k hodnote DateTime 2008-05-01T00:00:00 s DateTimeKind.Unspecified.
  • Výsledok priradíte k testDateAndTime, ktorý je typu DateTimeOffset. To spôsobí implicitné pretypovanie z DateTime na DateTimeOffset - , ktorý platí miestneČasové pásmo. Vo vašom prípade sa zdá, že posun pre túto hodnotu vo vašom miestnom časovom pásme je -04:00 , takže výsledná hodnota je DateTimeOffset z 2008-05-01T00:00:00-04:00, ako ste opísali.

Povedal si:

Konečným cieľom je jednoducho mať dátum bez posunu času alebo časového pásma.

No, existuje v súčasnosti nie je to natívny dátový typ C#, čo je len dátum bez času. Existuje čistý typ Date Systémový čas balík v corefxlabe, ale ešte nie je celkom pripravený na typickú produkčnú aplikáciu. V knižnici Noda Time je LocalDate, ktorý môžete použiť už dnes, no pred uložením do databázy budete musieť konvertovať späť na natívny typ. Takže medzitým najlepšie, čo môžete urobiť, je:

  • Zmeňte svoj SQL Server tak, aby v poli používal typ dátumu.
  • Vo svojom kóde .NET použite DateTime s časom 00:00:00 a DateTimeKind.Unspecified. Nezabudnite ignorovať časovú časť (pretože v určitých časových pásmach skutočne existujú dátumy bez miestnej polnoci).
  • Zmeňte testovaciu podperu tak, aby bola DateTime a nie DateTimeOffset.

Vo všeobecnosti, zatiaľ čo DateTimeOffset je vhodný pre veľké množstvo scenárov (napr časové pečiatky udalosti), nehodí sa pre hodnoty iba pre dátum.

Chcem aktuálny dátum s nulovým posunom.

Ak ty naozaj chcem je to ako DateTimeOffset , môžete urobiť:

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

Neodporúčam to však robiť. Týmto beriete miestne dátum pôvodnej hodnoty a tvrdenie, že je v UTC. Ak je pôvodný posun iný ako nula, bude to nepravdivé tvrdenie. Následne to povedie k ďalším chybám, pretože v skutočnosti hovoríte o inom časovom bode (s potenciálne iným dátumom), ako je ten, ktorý ste vytvorili.

Čo sa týka dodatočnej otázky položenej vašej nástenke. Zadanie DateTimeKind.Utc zmení správanie implicitného pretypovania. Namiesto použitia miestneho časového pásma sa používa čas UTC, ktorý má vždy nulový posun. Výsledok je rovnaký ako explicitnejší názor, ktorý som uviedol vyššie. Stále to neodporúčam z rovnakých dôvodov.

Uvažujme o príklade začínajúcom 2016-12-31T22:00:00-04:00. Podľa vášho prístupu by ste mali uložiť 2016-12-31T00:00:00+00:00 do databázy. Ide však o dva rozdielne časové body. Prvý, normalizovaný na UTC, by bol 2017-01-01T02:00:00+00:00 a druhý, prevedený na iné časové pásmo, by bol 2016-12-30T20:00:00-04:00. Upozorňujeme na zmenu dátumov v konverzii. Toto pravdepodobne nie je správanie, ktoré by ste vo svojej aplikácii chceli.

Publikácie na danú tému