Autor Téma: Funkce Now nevrací správný čas.  (Přečteno 1309 krát)

Offline age.new

  • Plnoletý
  • ***
  • Příspěvků: 115
  • Karma: 0
Funkce Now nevrací správný čas.
« kdy: 04-12-2017, 15:34:20 »
Vážená komunito,
již delší dobu mám podezření na funkci Now (z SysUtils) vracející TDateTime hodnotu aktuálního času. Do databáze se mi čas od času ukládají chybné časy. Kód je jednoduchý a přímočarý. Momentálně pracuji na nějakém logovacím mechanismu, abych měl důkaz. Dnes jsem narazil na další chybu této funkce: Vytvářím si kopiie souborů ve speciální složce. Po kopii využívám FileSetDate(soubor, DateTimeToFileDate(Now)) aby měl soubor nejaktuálnější datum. Toto však dopadne tak jednou z dvaceti případů. Čas od času se stane, že soubor má změněný datum (funkce vrací 0), ale čas je chybný. To znamená, že soubor nemá ani aktuální čas, ani čas původního, kopírovaného souboru. Ten čas je prostě náhodný (ale né nesmyslný). Setkal se někdo s něčím podobným?

... nenapadá někoho spolehlivější funkce jak zjistit aktuální čas?

Děkuji.
« Poslední změna: 04-12-2017, 15:37:52 od age.new »

Offline zdenek

  • Plnoletý
  • ***
  • Příspěvků: 123
  • Karma: 8
Re:Funkce Now nevrací správný čas.
« Odpověď #1 kdy: 04-12-2017, 17:15:32 »
To by mohlo ovlivnit třeba nastavení FPU. Jen rychlý nápad. Předpokládám, že v GetLocalTime ve windows asi problém nebude.

Offline vandrovnik

  • Hrdina
  • ****
  • Příspěvků: 401
  • Karma: 29
    • Verze Delphi: 10.2
Re:Funkce Now nevrací správný čas.
« Odpověď #2 kdy: 04-12-2017, 18:56:03 »
Pro zápis časových značek raději používám 'now' přímo na databázovém serveru, protože čas na stanicích může být dost mimo (na serveru se nám to nestává). Na serveru to navíc jde automaticky plnit v nějakém triggeru before insert, before update apod. a člověk na to nemusí myslet na x místech aplikace.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2059
  • Karma: 104
    • Verze Delphi: D2007, XE3, DX10
Re:Funkce Now nevrací správný čas.
« Odpověď #3 kdy: 04-12-2017, 19:09:52 »
Pro zápis časových značek raději používám 'now' přímo na databázovém serveru
Ja to tak vetsinou taky delavam, ale treba ted mam singleton, ktery spravuje cas v aplikaci, takze vsude se bere AppTime.Now. Tim jsem schopen zadat na cmdline cas, pro zpracovani dat notBefore ev. notAfter a spustit to a treba ladit chybu, ke ktere doslo pred 2 dny, jako kdybych byl v realnem case. Kdyz na cmdline nic nezadam, tak to bere aktualni cas.

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 571
  • Karma: 23
Re:Funkce Now nevrací správný čas.
« Odpověď #4 kdy: 04-12-2017, 19:38:33 »
... nenapadá někoho spolehlivější funkce jak zjistit aktuální čas?
Děkuji.

Že by byla chyba v tomhle mi přijde celkem nepravděpodobné, spíš bude blbě něco jiného, třeba nesynchronizovaný přístup ke společným proměnným atd. Zkusil bych logování do souboru a psát si tam, jaký je aktuálně čas a jaký je čas souboru atd. Pak se dá zpětně dohledávat, kdy se soubor vyrobil s jakými parametry.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 1940
  • Karma: 79
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Re:Funkce Now nevrací správný čas.
« Odpověď #5 kdy: 04-12-2017, 20:15:48 »
Upřímně moc nevěřím, že Now má chybu. Díval jsem se na implementaci v Delphi 5, XE a Tokio a všude je stejná. Pochybuji, že by během 20 let na tu chybu někdo nenarazil.

Spíše si myslím, že někdo do toho souboru zapíše, nebo ho nějak zavřeš později, nebo je zamknutý někým jiným.

Měl jsem podobný problém, a nakonec z toho vylezto, že inkriminovaný log byl v adresaáři, na který dával pozor dropbox nebo googledrive a způsobovalo problém.
Embarcadero MVP - Czech republic

Offline age.new

  • Plnoletý
  • ***
  • Příspěvků: 115
  • Karma: 0
Re:Funkce Now nevrací správný čas.
« Odpověď #6 kdy: 05-12-2017, 07:15:28 »
Děkuji za rady. Na Now máme postavený celý logovací systém a nepamatuji se, že bych narazil na špatný časový zápis. Kódem pro změnu času souboru to prochází vždy (zjištěno přes debug režim) a funkce FileSetDate vrátí 0, takže soubor by neměl být "uzamčený". Databázi máme v embeded režimu přímo na stanici, tj. bez serveru. Ještě to budu testovat... 

Offline age.new

  • Plnoletý
  • ***
  • Příspěvků: 115
  • Karma: 0
Re:Funkce Now nevrací správný čas.
« Odpověď #7 kdy: 05-12-2017, 08:59:11 »
Tak problém s datem u souboru vyřešený. V jednom případě se soubor přepisoval jiným (jakousi pracovní zálohou) a tím došlo k vytvoření chybného času. Původně hlavní problém s ukládání času do databáze mi v tomto případě zaslepil oči. Doufám, že řešení bude opět nějaká hloupá chyba. Hodnoty do databáze ukládám jako jednoduchý SQL příkaz s type double (TDateTime).   

Offline martinnr

  • Plnoletý
  • ***
  • Příspěvků: 153
  • Karma: 2
    • Verze Delphi: 7,2009,XE7
Re:Funkce Now nevrací správný čas.
« Odpověď #8 kdy: 06-12-2017, 09:59:02 »
tu by som ešte pripomenul možný nesúlad pri zápise časových značiek, pokiaľ budú na nejaký server prichádzať informácie z viacerých staníc. resp. stačí že z dvoch. pokiaľ záleží na "každej milisekunde", tak v žiadnom prípade sa nespoliehať na to, že by zápisy sedeli v časovom slede.
mám na mysli situáciu, keď niečo do logu pošle jeden počítač a pošle svoju časovú značku a potom niečo pošle iný počítač, alebo sám server niečo zapíše.
rozdiel v nastavenom čase na dvoch počítačoch býva často extrémny (samozrejme pre isté situácie, niekedy na tom nemusí záležať).
len aby sa na to myslelo...

Offline age.new

  • Plnoletý
  • ***
  • Příspěvků: 115
  • Karma: 0
Re:Funkce Now nevrací správný čas.
« Odpověď #9 kdy: 18-12-2017, 11:58:05 »
Tak jsem se opět dostal k řešení tohoto problému. Mám zde něco, co mi hlava nebere. Tipuji na problém s typem proměnné double, tak jak jej reprezentuje Delphi a jak jej bere SQL. Funkce Now totiž vrací čas správně, viz. SQL Query log na přiloženém obrázku. V tabulce se ale ve sloupci objeví chybná hodnota. Nenapadá někoho proč?

Legenda k obrázku:
Ve FlameRobin jsem si nechal zobrazil tabulku, kde je ve sloupci DATUM_CAS_STARTU 3x stejná hodnota, i když v logu Query příkazů je jasně zapsaná hodnota jiná. I sloupec DATUM_CAS_STOPU má chybnou hodnotu než byla poslaná v Query. Vše ostatní je v pořádku. Jinak Query příkaz UPDATE projde v pořádku.

Děkuji.



« Poslední změna: 18-12-2017, 12:01:34 od age.new »

Offline Ján Masaryk

  • Mladík
  • **
  • Příspěvků: 69
  • Karma: 5
    • Verze Delphi: 2010
Re:Funkce Now nevrací správný čas.
« Odpověď #10 kdy: 18-12-2017, 12:45:02 »
Keď sa na to pozerám máš v stlpcoch DATUM_CAS_STARTU a DATUM_CAS_STOPU rovnaké hodnoty, máš dobre napísané QUERY ?

Offline age.new

  • Plnoletý
  • ***
  • Příspěvků: 115
  • Karma: 0
Re:Funkce Now nevrací správný čas.
« Odpověď #11 kdy: 18-12-2017, 13:01:42 »
Jj, Query je napsané dobře. Typ sloupce je double (stejně jako TDateTime). Používám Embeded Firebird.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2059
  • Karma: 104
    • Verze Delphi: D2007, XE3, DX10
Re:Funkce Now nevrací správný čas.
« Odpověď #12 kdy: 18-12-2017, 13:43:49 »
Jj, Query je napsané dobře. Typ sloupce je double (stejně jako TDateTime). Používám Embeded Firebird.
1. Pouzivas parametrizovaný SQL?
2. Cim se na Ptaka Ohnivaka pripojujes?
3. Jak vypada definice tabulky tj. datovy typ sloupce?
« Poslední změna: 18-12-2017, 13:51:32 od pf1957 »

Offline age.new

  • Plnoletý
  • ***
  • Příspěvků: 115
  • Karma: 0
Re:Funkce Now nevrací správný čas.
« Odpověď #13 kdy: 18-12-2017, 14:03:40 »
1) Příklad příkazu:
UPDATE SPUSTENI_PLANU SET DATUM_CAS_STARTU = '43087.4894634259', JMENO_OBSLUHY = '', ... WHERE POCITADLO = 3

2) K FireBirdu se připojuji přes InterBase komponenty viz:
TIBDatabase
TIBTransaction
TIBQuery

3) Tabulka byla vytvořena takto:
CREATE TABLE SPUSTENI_PLANU (POCITADLO INTEGER NOT NULL PRIMARY KEY, ID_PLANU INTEGER NOT NULL REFERENCES NAHRANE_PLANY, ID_SPUSTENI INTEGER NOT NULL REFERENCES SPUSTENI_VIZU, DATUM_CAS_STARTU REAL, JMENO_OBSLUHY VARCHAR(50) .... )
CREATE UNIQUE DESCENDING INDEX SPUSTENI_PLANU_IDX_DESC ON SPUSTENI_PLANU(POCITADLO)

Ukázkové příkazy jsem zkrátil kvůli délce. V databázi je pak sloupec DATUM_CAS_STARTU chybný, viz. předchozí obrázek.

Edit: jinak když sloupec změním na string (VARCHAR), tak se časový údaj uloží správně. Zlobí to jen pokud se jedná o datový typ double (REAL)

Děkuji.
« Poslední změna: 18-12-2017, 14:09:43 od age.new »

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2059
  • Karma: 104
    • Verze Delphi: D2007, XE3, DX10
Re:Funkce Now nevrací správný čas.
« Odpověď #14 kdy: 18-12-2017, 14:11:16 »
DATUM_CAS_STARTU REAL
Ja tedy nevim, ale REAL pouzivam treba na MSSQL, ale Firebird nic takoveho nativne nema viz https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-datatypes-floattypes.html. Tam je jen FLOAT a DOUBLE PRECISION

 

S rychlou odpovědí můžete používat BB kódy a emotikony jako v běžném okně pro odpověď, ale daleko rychleji.

Upozornění: do tohoto tématu bylo naposledy přispěno před 120 dny.
Zvažte prosím založení nového tématu.

Jméno: E-mail:
Ověření:
Kolik je šest plus čtyři (slovem):