Korrekt arbete med datum och tid. Avlägsna tidszon Offset från DateTimeOffset med nolldatum Förskjutning

Problemet har inget att göra med databasen. Om du ställer in en stopppunkt eller anger utgången någonstans, måste du kunna se att offset ska fästas kort efter den här koden:

TestDateandTime \u003d TestDateandTime.Datetime.date;

Låt oss bryta ner det:

  • Du började med DateTimeOffset-värde 2008-05-01T08: 06: 32 + 01: 00
  • Då kallas du.dateTime, vilket ledde till värdet av DateTime 2008-05-01T08: 06: 32 med DateTimeKind.unspecified.
  • Då kallas du.date, vilket ledde till värdet av DateTime 2008-05-01T00: 00: 00 med DateTimeKind.unspecified.
  • Du tilldelar resultatet på TestDateandTime, som har en DateTimeOffset-typ. Det orsakar ett implicit cast från datetime till DateTimeOffset - som använder lokal Tidszon. I ditt fall verkar det som omfördelningen för detta värde i din lokala tidszon är -04: 00, så det erhållna värdet är DateTimeOffset från 2008-05-01T00: 00: 00-04: 00, som du beskrivit.

Du sa:

Det ultimata målet är att helt enkelt ha ett datum utan tid eller tidszonförskjutning.

Tja, det finns för närvarande Inte infödd C # Datatyp, som bara är ett datum utan tid. Det finns en ren datum typ i System tid. Paket i CorefxLab, men det är inte helt klart för en typisk tillverkningsapplikation. Det finns lokaldatum i Noda Time-biblioteket, som du kan använda idag, men innan du sparar till databasen måste du fortfarande konvertera tillbaka till din egen typ. Således är det bästa du kan göra:

  • Ändra din SQL Server Om användningen av typdatum i fältet.
  • I din kod.net, använd DateTime med tid 00:00:00 och DateTimeKind.unspecified. Du måste komma ihåg att ignorera den tillfälliga delen (eftersom det verkligen är datum utan en lokal midnatt i vissa tidszoner).
  • Ändra teststöd för att vara DateTime, inte DateTimeOffset.

I allmänhet, medan DateTimeOffset passar ett stort antal scenarier (till exempel, tidsetiketter Händelser), det passar inte bra för datum som bara betyder.

Jag vill ha det aktuella datumet med nollförskjutning.

Om du vill verkligen Det är som DateTimeOffset, du kan göra:

TestDateandTime \u003d Ny DateTimeOffset (TestDataandTime.date, Timepan.Zero);

Men jag rekommenderar inte detta. Genom att göra det tar du lokal Datumet för det ursprungliga värdet och hävdar att det är i UTC. Om den ursprungliga förskjutningen är inget annat än noll, blir det ett falskt uttalande. Det kommer senare att leda till andra misstag, eftersom du faktiskt pratar om den andra tiden (med ett potentiellt annorlunda datum) än den du skapade.

Handla om ytterligare frågaspecificerad i din styrelse. Notering DataTimeKind.utc ändrar beteendet hos implicita lösningar. I stället för att använda den lokala tidszonen används UTC-tid, vilket alltid har nollförskjutning. Resultatet är detsamma som den mer tydliga vyn jag gav ovan. Jag rekommenderar fortfarande det av samma skäl.

Tänk på ett exempel som börjar med 2016-12-31T22: 00: 00-04: 00. Vid ditt tillvägagångssätt måste du spara i databasen från 2016-12-31T00: 00: 00 + 00: 00. Men det här är två olika punkter i tid. Den första normaliserade till UTC kommer att vara 2017-01-01T02: 00: 00 + 00: 00, och den andra omvandlad till en annan tidszon kommer att vara 2016-12-30T20: 00: 00-04: 00. Var uppmärksam på förändringen i datumen i omvandlingen. Förmodligen är det inte det beteende som du vill använda i din ansökan.

DateTimeOffset TestDateandTime \u003d Ny DateTimeOffset (2008, 5, 1, 8, 6, 32, Ny Timpanel (1, 0, 0)); // Rengör tid och datum TestDataandTime \u003d TestDataandTime.Datetime.date; VAR DataSableentry \u003d dB.DateStable.first (dt \u003d\u003e dt.id \u003d\u003d Sometestid); DataStableentry.Test \u003d TestDateandTime; db.savechangesasync ();

Resultat i databasen: 2008-05-01 00: 00: 00.0000000 -04: 00

Hur aktiveras -4: 00 på +00: 00 (från kod innan du sparar)?

Jag har provat:

Offentlig uppgift. SettimeZoneOffsettozero (DateTimeOffsettCozero) (TimesPan ZeroOffsettimespan \u003d Ny Timespan (0, 0, 0, 0, 0); Retur DateTimeOffsetObj.ToOffset (Zerooffsettimespan);)

Han gör ingenting.

Det ultimata målet är att helt enkelt ha ett datum utan tidsförskjutning eller tidszon. Jag vill inte konvertera tiden på en annan tidszon (T. 00: 00: 00.0000000 Jag vill inte att den ska läsa 4 timmar från 00: 00: 00.0000000 Tid och 00: 00: 00.0000000 Ställ in den inställda tiden med +00: 00 Jag vill bara att han ska sätta offset till +00: 00). Jag vill ha det aktuella datumet med nollförskjutning.

Redigera:

Här är vad du kan erbjuda någon annanstans:

DateTimeOffset TestDateandTime \u003d Ny DateTimeOffset (2008, 5, 1, 8, 6, 32, Ny Timpanel (1, 0, 0)); TestDateandTime \u003d TestDateandTime.Datetime.date; // Zero Out Time Portion TestDateandTime \u003d DateTime.Specifyykind (TestDataandTime.date, DateTimeKind.utc); // "noll ut" offset parti

Jag var säker på att specifikkind skulle specificera min DateTimeOffset, till exempel, ändra båda tid och offset av tidszonen, men vid testning verkar det helt enkelt ändra tidszonens skifte, vilket är vad jag vill ha. Finns det ett problem med det här?

1 svar

Problemet har inget att göra med databasen. Om du installerade brytpunkten eller registrerade produktionen någonstans, bör du se hur offsetet kommer att vara knutet strax efter den här koden:

TestDateandTime \u003d TestDateandTime.Datetime.date;

Låt mig bryta det:

  • Du började med DateTimeOffset 2008-05-01T08: 06: 32 + 01: 00: 00
  • Då kallas du. Datetime, vilket resulterade i värdet av DateTime 2008-05-01T08: 06: 32 med DateTimeKind.unspecified.
  • Då kallas du.date, vilket ledde till värdet av DateTime 2008-05-01T00: 00: 00 med DateTimeKind.unspecified.
  • Du returnerar resultatet i TestDateandTime, som har typ DateTimeOffset. Detta medför en implicit omvandling från DateTime i DateTimeOffset som tillämpar lokal tidszon. I ditt fall verkar det som som kompenseras för detta värde i din lokala tidszon - -04: 00, så det slutliga värdet är DateTimeOffset 2008-05-01T00: 00: 00-04: 00, som du beskrivit,

Du sa:

Det ultimata målet är att helt enkelt ha ett datum utan tidsförskjutning eller tidszon.

Tja, för närvarande finns det ingen egen typ av data c #, vilket är bara ett datum utan tid. Det finns en ren datumtyp i systemet. Time-paketet i Corefxlab, men det är inte helt klart för en typisk tillverkningsapplikation. Det finns en lokaldata i Noda Time-biblioteket, som du kan använda idag, men du måste fortfarande konvertera tillbaka till din ursprungliga typ innan du sparar i databasen. Således är det bästa du kan göra:

  • Ändra din SQL Server för att använda datumtypen i det här fältet.
  • I din kod.net, använd DateTime med tid 00:00:00 och DateTimeKind.unspecified. Du måste komma ihåg att ignorera den tillfälliga delen (eftersom det verkligen är datum utan en lokal midnatt i vissa tidszoner).
  • Ändra testvarning som DateTime, inte DateTimeOffset.

I det allmänna fallet, medan DateTimeOffset är lämplig för ett stort antal skript (till exempel tidsstämpelhändelser), är det inte lämpligt för värden endast datum.

Jag vill ha det aktuella datumet med nollförskjutning.

Om du verkligen vill ha det till dotimeoffset, skulle du göra:

TestDateandTime \u003d Ny DateTimeOffset (TestDataandTime.date, Timepan.Zero);

Jag rekommenderar dock det här. Genom att göra det tar du det lokala datumet för det ursprungliga värdet och hävdar att det är i UTC. Om den ursprungliga förskjutningen är inget annat än noll, blir det ett falskt uttalande. Det kommer senare att leda till andra misstag, eftersom du faktiskt pratar om den andra tiden (med ett potentiellt annorlunda datum) än den du skapade.

När det gäller den extra frågan som anges i din redigering - ändrar DateTimeKind.utc beteende beteendet av implicita lösningar. I stället för att använda en lokal tidszon används UTC-tid, vilket alltid har nollförskjutning. Resultatet är detsamma som den mer tydliga vyn jag gav ovan. Jag rekommenderar fortfarande det av samma skäl.

Tänk på exemplet på början från 2016-12-31T22: 00: 00-04: 00. Vid ditt tillvägagångssätt måste du spara i databasen från 2016-12-31T00: 00: 00 + 00: 00. Men det här är två olika punkter i tid. Den första normaliserade till UTC kommer att vara 2017-01-01T02: 00: 00 + 00: 00, och den andra omvandlad till en annan tidszon kommer att vara 2016-12-30T20: 00: 00-04: 00. Var uppmärksam på förändringen i datumen i omvandlingen. Förmodligen är det inte det beteende som du vill använda i din ansökan.

Nästan alla projekt står inför problem som orsakas av felaktig bearbetning och lagring av datum och tid. Även om projektet används i en tidszon, ändå, efter övergången till vinter / sommartid, kan du få obehagliga överraskningar. Samtidigt är få människor förbryllade av genomförandet av rätt mekanism från början, för det verkar som om det inte finns något problem med detta, eftersom allt är trivialt. Tyvärr visar reality att det inte är det.

Du kan logiskt välja följande typer av värden relaterade till datum och tid:


Tänk på varje objekt separat, inte glömma.

datum och tid

Antag att laboratoriet som samlat analysmaterialet är i tidszonen +2 och den centrala filialen där det aktuella utförandet av analyser följs - i bältet +1. Den tid som ges i exemplet noterades när man samlade materialet i det första laboratoriet. Frågan uppstår - vilket antal tid ska vara centrala kontoret? Självklart bör programvaran från Central Office visa den 15 januari 2014 12:17:15 - en timme mindre, sedan klockan inträffade för tillfället.

Tänk på en av de möjliga handlingskedjorna genom vilka data från klienten på servern och tillbaka, så att du alltid kan visa datum / tid enligt det aktuella klienttidsbältet:

  1. Värdet skapas på kunden, till exempel den 2 mars 2016 15 : 13: 36, Klienten är i tidszon +2.
  2. Värdet omvandlas till en strängvy för överföring till servern - "2016-03-02T 15 :13:36+02:00”.
  3. Serialiserade data sänds till servern.
  4. Serveren deserialiserar tiden till datum / tidsobjektet, vilket leder det till sitt nuvarande himelbälte. Till exempel, om servern fungerar i +1, kommer objektet att innehålla 2 mars 2016 14 :13:36.
  5. Servern sparar data till databasen, medan den inte innehåller någon information om tidszonen - de vanligaste datumen / tidstyperna vet inte något om det. Således kommer basen att sparas den 2 mars 2016 14 : 13: 36 I den "okända" tidszonen.
  6. Servern läser data från databasen och skapar lämpligt objekt med värdet 2 mars 2016 14 : 13: 36. Och eftersom servern fungerar i tidszon +1, kommer detta värde att behandlas som en del av samma tidszon.
  7. Värdet omvandlas till en strängvy för överföring till kunden - "2016-03-02t 14 :13:36+01:00”.
  8. Serialiserade data skickas till klienten.
  9. Klienten deserialiserar det resulterande värdet i datum / tidsobjektet, medan det leder det till sitt nuvarande himelbälte. Till exempel, om det är -5, ska det visade värdet vara lika med 2 mars 2016 09 :13:36.
Det verkar som om allt är holistiskt, men låt oss tänka att det i den här processen kan gå fel. Faktum är att problemen här kan hända nästan vid varje steg.
  • Tiden på klienten kan bildas alls utan en tidszon - till exempel DateTime Type V.net med DateTimeKind.unspecified.
  • Serialiseringsmekanismen kan använda ett format som inte innehåller en tidszonförskjutning.
  • Vid deserialisering kan ett objekt ignoreras med en tidszonförskjutning, särskilt i "självgjorda" deserializers - både på servern och på klienten.
  • När du läser från databasen kan datum / tidsobjektet bildas alls utan en tidszon - till exempel DateTime Type V.Net med DateTimeKind.unspecified. Dessutom är det med DateTime v.net i praktiken exakt det om omedelbart efter avdraget inte är att ange en annan DateTimeCind.
  • Om applikationsservrarna som körs med en gemensam databas är i olika tidszoner - kommer det att bli en allvarlig förvirring i tidsförskjutningar. Datum / tidvärdet som är inspelat i databasen av servern A och användarläsaren läsbart skiljer sig märkbart från samma källvärde som registrerats av servern som används av servern A.
  • Översättningen av applikationsservrarna från ett bälte till en annan leder till en felaktig tolkning av redan sparade datum / tidvärden.
Men den allvarligaste nackdelen i kedjan som beskrivs ovan är användningen av en lokal tidszon på servern. Om det inte finns någon sommar / vinterövergång i den, kommer det inte att finnas några ytterligare problem. Men annars kan du få mycket obehagliga överraskningar.

Översättningsregler för sommar / vintertid är en sak, strängt talande, variabel. Olika länder kan ibland ändra sina regler, och dessa förändringar måste i förskott läggas i systemuppdateringarna. I praktiken har situationen för felaktigt arbete av denna mekanism upprepade gånger uppfyllt, vilket enligt summan löstes genom att installera snabbkorrigeringar eller operativ systemeller använda bibliotek från tredje part. Sannolikheten att upprepa samma problem är inte noll, så det är bättre att ha ett sätt att garanteras att undvika dem.

Med tanke på de ovan beskrivna övervägandena formuleras vi som ett tillförlitligt och enkelt tillvägagångssätt för överförings- och tidsförvaring som möjligt: på servern och i databasen måste alla värden visas till UTC-tidszonen.

Tänk på vad regeln ger oss:

  • När du skickar data till servern måste klienten passera tidszonens offset så att servern kan konvertera tid till UTC. Alternativt alternativ - förplikta en kund att göra denna konvertering, men det första alternativet är flexibelt. När du får data tillbaka från servern, kommer klienten att översätta datumet och tiden till sin lokala tidszon, vilket vet att tiden kommer att komma till UTC.
  • I UTC finns det inga övergångar för sommar och vintertid, de tillhörande problemen kommer att vara irrelevanta.
  • På servern, när du läser från databasen behöver inte konvertera tidsvärdena, är det tillräckligt att det uttryckligen indikerar att det matchar UTC. V.net, till exempel, du kan uppnå DateTimeKind-inställningen för tidsobjektet i DateTimeKind.utc.
  • Skillnaden i tidszoner mellan servrar som arbetar med en gemensam databas, liksom översättningen av servrar från ett bälte till ett annat, kommer inte att påverka korrektheten hos de erhållna data.
För att genomföra en sådan regel är det tillräckligt att ta hand om tre saker:
  1. Gör en mekanism för serialisering och deserialisering så att datum / tidvärdena är korrekt översatta från UTC till den lokala tidszonen och baksidan.
  2. Se till att reeserializer på serverns sida skapar datum / tidsobjekt i UTC.
  3. Se till att när databasen är datum / tidsobjekten skapade i UTC. Denna artikel tillhandahålls ibland utan kodändringar - bara systemtidszonen på alla servrar är installerad i UTC.
Ovanstående överväganden och rekommendationer fungerar perfekt med en kombination av två förhållanden:
  • I systemkraven är det inte nödvändigt att visa lokal tid och / eller förändringen av tidszonen är exakt i den form i vilken den sparades. Till exempel måste i flygbiljetter, avgång och ankomsttid skrivas ut i den tidszon som motsvarar flygplatsens läge. Eller om servern skickar fakturor skapade i olika länder, Var och en bör så småningom stå en lokal tid, och inte servern omvandlas till tidszonen.
  • Alla datum och tidvärden i systemet är "absolut" - dvs Beskriv tidpunkten i framtiden eller förflutet, vilket motsvarar det enda värdet i UTC. Till exempel, "start av bärraketen ägde rum klockan 23:00 i Kiev tid," eller "mötet kommer att gå från 1/11: 30 till 14:30 på Minsk tid." I olika tidszoner kommer siffrorna för dessa händelser att vara annorlunda, men de kommer att beskriva samma tid. Men det kan hända att kraven på programvara Meddelande "relativ" lokal tid i vissa fall. Till exempel, "Denna överföring på tv kommer att gå från 9:00 till 10:00 på morgonen i varje land där det finns en tv-kanal." Det visar sig att överföringsdisplayen inte är en händelse, men flera, och potentiellt kan alla förekomma i olika segment av tid på "absolut" skalaen.
För fall där det första tillståndet är trasigt, kan uppgiften lösas med hjälp av datatyperna som innehåller tidszonen - både på servern och i databasen. Nedan är en liten lista med exempel på olika plattformar och DBMS.
.Netto DateTimeOffset.
Java. org.joda.time.datetime, java.time.zoneddateTime
Ms sql. dateTimeOffset.
Oracle, PostgreSQL Timestamp med tidszon
Mysql

Överträdelse av det andra villkoret - mer svåra fall. Om denna "relativa" tid måste lagras helt enkelt för att visa, och det finns ingen uppgift att bestämma det "absoluta" ögonblicket när händelsen har kommit eller inträffat för en viss tidszon - det räcker för att helt enkelt förbjuda tidskonvertering. Till exempel har användaren infört början av överföringen för alla filialer i tv-bolaget den 25 mars 2016 klockan 9:00, och det kommer att överföras i detta formulär, lagrat och visas. Men det kan hända att vissa schemaläggare automatiskt måste utföra speciella åtgärder per timme före varje överföring (skickade meddelanden eller kontrollera eventuella data i tv-stationen). Tillförlitlig implementering av en sådan planerare är en nontrivial uppgift. Antag att planeraren är medveten om vilken tidszon som finns i varje grenar. Och ett av de länder där det finns en filial, efter ett tag beslutar att ändra tidszonen. Ärendet är inte så sällsynt, eftersom det kan tyckas - för den här och de två tidigare åren räknade jag mer än 10 sådana händelser (http://www.timeanddate.com/news/time/). Det visar sig att användarna måste behålla bindningar till tidszoner i ett verkligt tillstånd, eller schemaläggaren måste ta denna information från globala källor som Google kartor. Time Zone API. Jag åtar mig inte att erbjuda en universell lösning för sådana fall, jag noterar helt enkelt att sådana situationer kräver en allvarlig studie.

Som framgår av det föregående, det finns inget enda tillvägagångssätt som täcker 100% av fallen. Därför måste du först förstå kraven, vilka av de nämnda situationerna som nämns ovan kommer att vara i ditt system. Med stor sannolikhet kommer allt att vara begränsat till det första föreslagna tillvägagångssättet med lagring i UTC. Tja, de exklusiva situationer som beskrivs är inte avbrutna, men lägger bara till andra lösningar för speciella fall.

Datum utan tid

Antag, med rätt visning av datum och tid, med hänsyn till klientens klockzon. Låt oss vända oss till datum utan tid och det exemplar som anges för det här fallet i början - "Det nya kontraktet träder i kraft den 2 februari 2016." Vad händer om sådana värderingar använder samma typer och samma mekanism som för "vanliga" datum med tiden?

Inte i alla plattformar, språk och DBMS är typer endast för datum. Till exempel är v.net bara typ av datetime, ett separat "just datum" är inte. Även om, när du skapar ett sådant objekt, bara är datumet angivet, är tiden fortfarande närvarande, och det är lika med 00:00:00. Om vi \u200b\u200bmenar "2 februari 2016 00:00:00" från bältet med en förskjutning +2 översätt i +1, så får vi "1 februari 2016 23:00:00." För exemplet ovan kommer detta att motsvara det faktum att det nya kontraktet i en tidszon börjar fungera den 2 februari och i den andra 1 februari. Från en juridisk synvinkel är det absurt och så bör det naturligtvis inte vara. Den allmänna regeln för "rent" datum är extremt enkel - sådana värden bör inte omvandlas på vilket steg som sparas och läser.

Det finns flera sätt att undvika omvandling för datum:

  • Om plattformen stöder den typ som representerar datumet utan tid, måste den användas.
  • Lägg till en speciell funktion i de metadataobjekt som kommer att säga serializer som för detta värde Tidszonen måste ignoreras.
  • Överför ett datum från klienten och tillbaka som en sträng och lagra som datum. Detta tillvägagångssätt är obekvämt om datumet på kunden inte bara behöver visa, utan också att producera vissa operationer på den: jämförelse, subtraktion etc.
  • Överför och lagra som en sträng och konvertera till datum endast för formatering, med hänsyn till de regionala kundinställningarna. Det har ännu mer nackdelar än den tidigare versionen - till exempel, om i den lagrade linjens del av datumet inte är i ordern "år, månad, dag", blir det omöjligt att göra en effektiv indexerad sökning med datumintervallet.
Du kan naturligtvis försöka leda ett motprov och säga att kontraktet endast är meningsfullt inom det land där det ingås, landet är i en tidszon, och därför är det möjligt att entydigt bestämma det ögonblick som träder i kraft . Men även i det här fallet kommer användare från andra tidszoner inte att vara intresserade av vilket ögonblick den här händelsen kommer att hända på sin lokala tid. Och även om det var ett behov av att visa denna tidpunkt, skulle det vara möjligt att visa inte bara datumet utan också den tid som motsäger det ursprungliga tillståndet.

Tidsintervall

Med lagring och bearbetning av tidsintervaller är allt enkelt: deras värde beror inte på tidszonen, så det finns inga speciella rekommendationer här. De kan lagras och överföras som antalet tidsenheter (en heltal eller flytande punkt, beroende på önskad noggrannhet). Om den andra noggrannheten är viktig - då som antalet sekunder, om millisekund, som antalet millisekunder etc.

Men beräkningen av intervallet kan ha fallgropar. Antag att vi har en typisk kod på C #, som anser att tidsintervallet mellan två händelser:

DateTime Start \u003d DateTime.Now; // ... DateTime End \u003d DateTime.Now; Dubbel timmar \u003d (ändstart) .Totalhours;
Vid första anblicken finns det inga problem här, men det är det inte. För det första kan det finnas problem med enhetstestningen av en sådan kod, men vi kommer att prata om det lite senare. För det andra, låt oss föreställa oss att det första ögonblicket kom på vintern, och den sista (till exempel antalet arbetstider mäts, och arbetarna har ett nattskifte).

Antag att koden fungerar i tidszonen, där sommartid i 2016 inträffar på natten den 27 mars, och vi simulerar situationen som beskrivs ovan:

DateTime Start \u003d DateTime.Parse ("2016-03-26T20: 00: 15 + 02"); DateTime End \u003d DateTime.Parse ("2016-03-27T05: 00: 15 + 03"); Dubbel timmar \u003d (ändstart) .Totalhours;
Denna kod kommer att ge 9 timmar som ett resultat, men i själva verket passerade 8 timmar mellan dessa stunder. Detta är lätt verifierat genom att ändra koden på så sätt:

DateTime Start \u003d DateTime.Parse ("2016-03-26T20: 00: 15 + 02"). Touniversaltime (); DateTime End \u003d DateTime.Parse ("2016-03-27T05: 00: 15 + 03"). Touniversaltime (); Dubbel timmar \u003d (ändstart) .Totalhours;
Därför måste utgången - alla aritmetiska operationer med datum och tid göras med antingen UTC-värden eller typer som lagrar information om tidszonen. Och vänd sedan tillbaka till lokala i händelse av behov. Ur denna synvinkel är det ursprungliga exemplet lätt att fixa genom att ändra DateTime.Now på DateTime.utcnow.

Denna nyans beror inte på en viss plattform eller språk. Här är en liknande kod på Java, med samma nackdel:

LocalDatetime Start \u003d LocalDatetime.Now (); // ... LocalDatetime End \u003d LocalDatetime.Now (); Långa timmar \u003d kronounit.hours.between (start, slut);
Det korrigeras också lätt - till exempel med användning av zoneddateTime istället för localDatetime.

Schema för schemalagda händelser

Schema för schemalagda händelser - en svårare situation. Universell typ som tillåter att lagra scheman, i standardbibliotek inte. Men en sådan uppgift uppstår inte så sällan, så du kan hitta färdiga lösningar utan problem. Bra exempel Det är formatet för Cron Planner, som används i en form eller annat av andra lösningar, till exempel kvarts: http://quartz-scheduler.org/api/2.2.0/org/quartz/cronexpression.html. Det täcker nästan alla schemaläggningsbehov, inklusive de alternativ som "två fredag \u200b\u200bi månaden".

I de flesta fall är det inte nödvändigt att skriva din planerare, eftersom det finns flexibla tidstestade lösningar, men om det av någon anledning är ett behov av att skapa din mekanism, kan åtminstone schemaläggningsformat lånas från Cron.

Förutom ovanstående rekommendationer om lagring och bearbetning av differentialtidsvärden finns det flera andra andra saker som jag också skulle vilja säga.

Först, om användningen av statiska klassmedlemmar för att få den aktuella tiden - DateTime.utcnow, zoneddateTime.Now (), etc. Som det var sagt kan användningen av dem direkt i koden på allvar komplicera enhetstestningen, eftersom det utan särskilda IOC-ramar ersätter den aktuella tiden. Därför, om du planerar att skriva enheter test, bör du ta hand om att genomförandet av sådana metoder kan bytas ut. För att lösa detta problem finns det minst två sätt:

  • Välj IdateTimeProvider-gränssnittet med den enda metoden som returnerar den aktuella tiden. Lägg sedan till ett beroende av detta gränssnitt i alla enheter i koden där du behöver ta emot den aktuella tiden. Med det vanliga genomförandet av programmet kommer alla dessa platser att injiceras av "standard" -implementeringen, som returnerar den reala aktuella tiden och i enhetstestet - någon annan nödvändig implementering. Denna metod är den mest flexibla när det gäller testning.
  • Gör din statiska klass med metoden för den aktuella tiden och förmågan att upprätta någon realisering av denna metod från utsidan. Till exempel, i fallet med C # -koden, kan den här klassen lägga ut utflödesegenskapen för UTCNow-egenskapen och setimplentationsmetoden (FUNC imc). Användningen av statiska egenskaper eller metod för att erhålla den aktuella tiden eliminerar behovet av att uttryckligen föreskriva beroende av det extra gränssnittet, men med avseende på OOP: s principer är det inte den perfekta lösningen. Men om den tidigare versionen inte passar, kan du använda den.
Ett ytterligare problem som bör lösas under övergången till dess genomförande av den aktuella tidsleverantören kontrollerar att ingen "gammaldags" fortsätter att använda standardklasser. Den här uppgiften är lätt att lösa i de flesta kodkvalitetskontrollsystem. Faktum är att det kommer att finna den "oönskade" substringen i alla filer, utom där "standard" -implementeringen meddelas.

Den andra nyansen med mottagandet av den aktuella tiden är det det är omöjligt att lita på kunden. Den aktuella tiden på datorer av användare kan vara väldigt annorlunda än verkliga, och om det finns logik knutet till det, kan denna skillnad förstöra allt. Alla platser där det är nödvändigt att ta emot den aktuella tiden, ska utföras på serverns sida om möjligt. Och som tidigare nämnts tidigare bör alla aritmetiska operationer med tiden utföras antingen i UTC-värden eller använda de typer som lagrar tidszonens offset.

Och en sak som jag ville nämna är ISO 8601-standarden som beskriver datum och tidsformat för utbyte av information. I synnerhet måste strängrepresentationen av det datum och tid som används i serialisering överensstämma med denna standard för att förhindra eventuella kompatibilitetsfrågor. I praktiken är det extremt sällsynt att genomföra formatering, därför kan standarden i sig vara användbar för informationsändamål.

Taggar: Lägg till taggar

Alternativet är humant ([Du måste registrera dig för visningslänk]).

Kärnan i problemet är i vad .. Om du av misstag utvecklat basen på SQL-servern med "datumförskjutningen" 0 var det ett problem när databasen inträffar med typen av tid, dvs den här erforderligheten är inställd 01.01.0001 10:30:00 eller datum låst tomt 01.01.0001 00:00:00. Vid inspelning av sådana uppgifter registrerar det inte.
På Internet föreslås det att skapa en ny bas med Offset 2000.
Men den nya databasen ville verkligen inte skapa. Och att ändra alla användare sökvägen till databasen.
Sedan gick jag längs vägen, och där det är lagrat detta värde i SQL. Jag hittade och ändrats till 2000 och allt blev ok ..
Och nu steg för steg, var du ska ändra.

Avgas alla användare.

UPPMÄRKSAMHET!!!

1. Gör först säkerhetskopiering Betyder 1c d.v.s. Lossa det i * .dt
Det måste göras innan du ändrar "offset"
Om detta inte är gjort i hela din SPR., DOC, etc.
där det finns några detaljer om datumet kommer att vara erkänna 02.10.0009
Vad är inte tillåtet ...
Så du gjorde lossning i * .dt

2. Gå till SQL Server Management Studio
Vi hittar din databas i listan Click Plus.
Jag hittar en mapp "tabeller" och avslöjar det.
En massa tabeller öppnas, gå till botten, vi hittar bordet
_Yearoffset, bli på den och höger nyckel Välj objektet "Open Table", se Fig. 1
Ändra värdet 0 till 2000
Stäng SQL Server Management Studio

3. Gå till konfiguratorn och ladda en tidigare sparad bas.

Om inte att göra det, kommer alla datum att vara med ett år 0009.
Efter basstarten ... kan du gå till 1c och se till att datumen är normala.
Resultat Vi ändrade "Offset Datum från 0 till 2000"

Ibland händer det att det här alternativet inte använder av en eller annan anledning. Då finns det ett mer hardcore-alternativ ([du behöver registrera för att visa länken]):

Förklara tabellerandsfält markör foror för

Välj objekt. Namn som tablename, kolumner.Name som kolumnnamn
Från dbo.sysObjects. somföremål.
vänster med dbo.syscolumns som kolumner på objekt.id \u003d kolumns.id
där objekt.xtype \u003d "u" och kolumns.xtype \u003d 61

Öppna bordandfält.

Medan @@ fetch_status \u003d 0
Börja exec (" uppdatering " + @TableName + "
uppsättning " + @ColumnName + " = ""2000- 01- 01 00:00:00" "
vAR " + @ColumnName + " > ""3999- 12- 31 23:59:59" "")

Detta exekveras så länge som den tidigare hämtningen lyckas.
Hämta nästa från TABLEANDFields till @tableName, @ColumnName
Slutet.

stäng tabellerandsfält.
fördela tabellerandsfält
gå.

Före några manipuleringar, glöm inte att kopiera databaser!

Dela med sig