Keresés

Részletes keresés

NevemTeve Creative Commons License 2015.04.30 0 0 5315

Kieg: semmi bajunk sem lesz, ha (mármint unixról beszélve, és feltéve, hogy nem AIX5-ös kőkorszaki rendszerekről van szó) a TZ-t meg ORA_SDTZ-t is beállítjuk Europe/Budapest-re, de ennek nincs köze a systimestamp-hoz; a LOCALTIMESTAMP-ot meg a CURRENT_TIMESTAMP-ot lehet velük állítani.

NevemTeve Creative Commons License 2015.04.30 0 0 5314

A pillanatnyi állást a következőképpen foglalnám össze:

1. a SYSTIMESTAMP a szerver localtime-ja

2. TZ, ORA_SDTZ, SESSIONTIMEZONE nem befolyásolja

3. (Az én esetemben legalábbis) nincs TZD része, TZR=+02:00

4. Még nem tudom, hogy ha a DBTIMEZONE Europe/Budapest lenne, akkor volna-e nekije.

5. Át lehet alakítani UTC-re (és bármi másra is persze)

6. Az UTC-vel lehet jól matekozni.

7. A megmatekozott UTC-t szeretném arra a localtime-re konvertálni, ami a szerver helyi ideje. Na ehhez is nagyon jó lenne, ha a DBTIMEZONE rendesen lenne töltve.

halaloszto Creative Commons License 2015.04.30 0 0 5313

az a helyzet hogy ezek kőkemény dba kérdések, én meg inkább fejlesztő vagyok.

Előzmény: NevemTeve (5312)
NevemTeve Creative Commons License 2015.04.30 0 0 5312
Igy a héven ülve a következö két kérdés gyötör:
1. ha ALTER DATABASE SET TIMEZONE = 'Europe/Budapest' paranccsal (utána stop+start) meghaxoljuk az adatbázist, az változtat-e a DBTIMEZONE értékén?
2. változtat-e a syslocaltime TZD részén?
3. ha nem, akkor van-e valami, ami változtat?
halaloszto Creative Commons License 2015.04.30 0 0 5311

a systimestamp szerintem egyszerűen a unix systime-ja és tz-je. maga a vekker. ebből ki lehet számolni az aktuális utc-t, abból meg bármit. és a unixod ha megkérdezik mi az időzóna, akkor azt mondja hogy 2, télen meg hogy 1. nem pedig azt hogy europe/budapest. 

 

 

és ez így kevés. ugyanis az hogy 2015 04 30 15:41 +02:00 az lehet europe/budapest és lehet africa/johannesburg is. és nem mindegy melyik, ugyanis délafrikában nincs téli-nyári váltás.

 

 

Vajk

Előzmény: NevemTeve (5309)
halaloszto Creative Commons License 2015.04.30 0 0 5310

K: Mennyi volt a localtime 60 nappal ezelőtt?

V1: SELECT systimestamp + NUMTODSINTERVAL(-60,'DAY') from dual;

Sajnos ez rossz válasz, mert nem veszi figyelmebe, hogy akkor még téli idő (CEST) volt itt. (Az (5302)-es 'kimenet' részében a középső sor.)

 

nem nem veszi figyelembe, hanem nem tudja hogy mi a helyi időzóna. nekem ugy tűnik hogy az időzónád egy fix offsettel van definiálva. a +2:00 nevű időzónában nincs téli-nyári időszámítás.

 

 

V2: SELECT ((systimestamp at time zone '+00:00') + NUMTODSINTERVAL(-60,'DAY')) at time zone 'Europe/Budapest' from dual;

Na ez már jobb (az (5302)-es 'kimenet' részében az utolsó sor.), csak még a belehardkódolt 'Europe/Budapest' helyett kellene valami flexibilis adat.

 

ez azt csinálja, hogy a mostani időt veszi utc-ben, levesz belőle 60 napot, és átszámolja az eredményt magyar időre. 

 

az at time zone '+00:00' ki is hagyható, ugyanazt adja. az adattípus amit használsz az egy olyan valami, ami tárolja az időt mint értéket, és az időzónát is, amiben értelmezni kell. a systimestamp at utc es a systimestamp at budapest értékek ekvivalensek, ugyanazt a pillanatot jelentik az időegyenesen a világ történelmében. attól hogy konvertálgatsz a zónák között nem változik az érték, csak a "mértékegység". átváltod literre, hozzáadsz kétdecit, kiírod pintben. ha nem váltottad volna literre, ugyanaz lenne az eredmény.

 

 

Például van olyan, hogy

ALTER SESSION SET TIME_ZONE = 'Europe/Budapest';
ennek fordítottja:

SELECT sessiontimezone FROM dual;

válasz: Europe/Budapest

Tök jó. De amikor 'csak úgy' elindítom az SqlPlus-t, akkor a SESSIONTIMEZONE is, meg DBTIMEZONE is csak '+02:00', amit én információvesztésnek érzek.

 

Így van. Az europe/budapest az egy kulturalis-politikai fogalmat jelent. Hogy pontosan mit, azt a jogszabályok és bizonyos nemzetközi egyezmények tartalmazzák. A TZDATA nevű kvázistandard formátumban letölthető, az ICANN maintaineli. Ebből generálja mindenki a saját naptár szoftverét. (a linux kernel, az ora adatbázis, a java, az mfc és így tovább) Rendszeresen változik, mint amit írtam Szevasztopolról.

 

Vannak ennél bénább időzóna megadások, pl a +02:00. Ennek az értelmezéséhez nem kell tudni a világ összes országából hogy mit döntött a parlament mikor lesz az óraátállítás, egyszerű matematikai művelettel elvégezhető a "konverzió", műszaki felhasználásra úgy ahogy alkalmas, de inkább buta mint a főd. 

 

Az alter sessionn-el beállíthatod magadnak amit akarsz. A default a kliens oprendszeréből jön. Ha van ORA_STDTZ akkor onnan, ha nincs akkor pl az unixtól kérdezi meg. Esélyes hogy a megfelelő unix rendszerhívás is aktuális offsetet ad vissza, nem pedig rendes időzóna nevet.

 

A dbtimezone annyiban más, hogy installkor kell megadni, és az lesz. Ha egy fix offsetet adtak meg akkor az, ha rendes regionevet, akkor az.

 

 

 

én úgy látom, azt kellene kitaláld, hogy honnan tudod meg mi most a helyi időzóna.

 

Vajk

Előzmény: NevemTeve (5307)
NevemTeve Creative Commons License 2015.04.30 0 0 5309

Mondjuk 'unset TZ'-t csinálok (AIX), és kipróbálom ezt:

select dbtimezone,sessiontimezone,systimestamp,systimestamp at time zone '+00:00',localtimestamp from dual;

 

eredmény:
+00:00
+00:00
20150430.153058.889493 +02:00
20150430.133058.889493 +00:00
20150430.133058.889509

Szóval azért valahol benne van a kis agyában a '+02:00' ilyenkor is... elannyira, hogy ha viszont TZ-t is, meg az ORA_SDTZ-t is beállítom Europe/Kiev-re, akkor meg ezt látom:

 

+00:00
Europe/Kiev
20150430.153004.130357 +02:00
20150430.133004.130357 +00:00
20150430.163004.130370

Szóval a localtimestamp.ot lehet TZ/ORA_SDTZ útján hangolni, a systimestamp viszont valahonnan máshonnan jön, még csak nem is a DBTIMEZONE-ból... esetleg az Oracle szervert futtató gépből?

NevemTeve Creative Commons License 2015.04.30 0 0 5308

Mondjuk van egy olyan NLS_ environment változó, hogy ORA_SDTZ, ha az be van állítva hívás előtt, akkor abból lesz a SESSIONTIMEZONE. Ez is valami, többé-kevésbé.

 

Később: ha TZ=Europe/Kiev, akkor SESSIONTIMEZONE='+03:00', de ha ORA_SDTZ=Europe/Kiev, akkor SESSIONTIMEZONE='Europe/Kiev'

 

A DBTIMEZONE pedig instance-onként különbözik, +00:00, +01:00 és +02:00 fordul elő. Ettől függetlenül a SESSIONTIMEZONE mindenütt '+02:00' (hacsak nem variálok a környezeti változókkal a fentiek szerint)

NevemTeve Creative Commons License 2015.04.30 0 0 5307

K: Mennyi volt a localtime 60 nappal ezelőtt?

V1: SELECT systimestamp + NUMTODSINTERVAL(-60,'DAY') from dual;

Sajnos ez rossz válasz, mert nem veszi figyelmebe, hogy akkor még téli idő (CEST) volt itt. (Az (5302)-es 'kimenet' részében a középső sor.)

 

V2: SELECT ((systimestamp at time zone '+00:00') + NUMTODSINTERVAL(-60,'DAY')) at time zone 'Europe/Budapest' from dual;

Na ez már jobb (az (5302)-es 'kimenet' részében az utolsó sor.), csak még a belehardkódolt 'Europe/Budapest' helyett kellene valami flexibilis adat.

 

Például van olyan, hogy

ALTER SESSION SET TIME_ZONE = 'Europe/Budapest';
ennek fordítottja:

SELECT sessiontimezone FROM dual;

válasz: Europe/Budapest

Tök jó. De amikor 'csak úgy' elindítom az SqlPlus-t, akkor a SESSIONTIMEZONE is, meg DBTIMEZONE is csak '+02:00', amit én információvesztésnek érzek.

Előzmény: halaloszto (5305)
halaloszto Creative Commons License 2015.04.30 0 0 5306

select dbtimezone from dual;

Előzmény: NevemTeve (5303)
halaloszto Creative Commons License 2015.04.30 0 0 5305

mire lenne a helyes megfejtés? 

lehet egyszerűbb lenne ha elárulnád a requirementet :-)

 

Vajk

Előzmény: NevemTeve (5302)
halaloszto Creative Commons License 2015.04.30 0 0 5304

az a kérdés, hogy mi a systimestamp-od időzónája. asszem mindig dbtimezone.

 

select to_char(systimestamp, 'tzr') from dual;

 

namost timezone-t megadni legalabb haromféleképpen lehet. offsettel (+2:00), rövidnévvel amivel csak a szopás van és nem javasolt (CET) és tzregionnal (europe/budapest). nekem erőst úgy tűnik, hogy nálad offsettel van megadva, nem szaroztak. ezért abban soha nem lesz téli-nyári váltás, mindig +2 és kész.

 

én azt mondom, hogy meg kell próbálni minnél függetlenebbül működni a környezettől. 

 - a select systimestamp at time zone 'UTC' from dual; az midnenképp megmondja az aktuális dátumot utc-ben. ha mégsem, az egyértelműen az üzemeltetés problémája, nem a fejlesztőé

 

 - select to_char(from_tz(cast (to_date ('2012 02 02 13:45','yyyy mm dd hh24:mi') as timestamp), 'europe/budapest'),'TZD') from dual; ez mindenképpen megmondja egy magyar idő szerinti dátumról hogy tél vagy nyár.

 

sajnos arra, hogy egy adott zónában melyik a téli és melyik a nyári név, nem tudok tuti megoldást. elég csúnya, de le lehet hardkódolni hogy megkérdezzük a jan-1-et, és amit arra ad, az a télinek a neve.

 

Vajk

Előzmény: NevemTeve (5301)
NevemTeve Creative Commons License 2015.04.30 0 0 5303

(De ha valaki tudja, hogyan lehet az Orából visszanyerni, hogy az instance beállítása 'Europe/Budapest' vagy 'Canade/Central' vagy mi, akkor szóljon, legyen szíves!)

NevemTeve Creative Commons License 2015.04.30 0 0 5302

Majdnem jó.

    DECLARE
    ts_server_lt  TIMESTAMP WITH TIME ZONE;
    ts_server_utc TIMESTAMP WITH TIME ZONE;
    ts_past_lt  TIMESTAMP WITH TIME ZONE;
    ts_past_utc TIMESTAMP WITH TIME ZONE;
    BEGIN
    ts_server_lt  := SYSTIMESTAMP;
/*    ts_server_utc := SYS_EXTRACT_UTC (SYSTIMESTAMP); */
    ts_server_utc := ts_server_lt AT TIME ZONE '+00:00';

    dbms_output.put_line ('lt= ' || ts_server_lt);
    dbms_output.put_line ('utc=' || ts_server_utc);

    ts_past_lt  := ts_server_lt  + NUMTODSINTERVAL(-60,'DAY');
    ts_past_utc := ts_server_utc + NUMTODSINTERVAL(-60,'DAY');

    dbms_output.put_line ('past lt= ' || ts_past_lt);
    dbms_output.put_line ('past utc=' || ts_past_utc);

    dbms_output.put_line ('past lt=' || ts_past_utc at time zone 'Europe/Budapest');
    END;
/

Kimenete:

lt= 20150430.114223.613754 +02:00
utc=20150430.094223.613754 +00:00
past lt= 20150301.114223.613754 +02:00
past utc=20150301.094223.613754 +00:00
past lt=20150301.104223.613754000 +01:00

A legutolsó sor lenne a helyes megfejtés, de csak akkor, ha nem lenne belehardkódolva az 'Europe/Budapest'... Nyomozok tovább.

NevemTeve Creative Commons License 2015.04.30 0 0 5301

Mondjuk azt nem tudtam, hogy ezelőtt két hónappal is nyári időszámítás volt:

 

> select systimestamp,systimestamp + numtodsinterval(-60, 'day') from dual;

SYSTIMESTAMP

SYSTIMESTAMP+NUMTODSINTERVAL(-60,'DAY')

20150430.105146.245334 +02:00

20150301.105146.245334000 +02:00

 

Talán PL/SQL-lel kellene?

halaloszto Creative Commons License 2015.04.30 0 0 5300

job-ból miért lenne más? 

 

minden valamilyen session-ben történik. minden sessionnek van egy nls settingje, meg pl timezoneja meg egy csomó egyebe. 

 

sokféle módon jönnek létre sessionök, és mindegyiknél máshonnan jönnek a defaultok erre. vagy a defaultot kell beállítani, vagy egyszerűen a megfelelő alter sessionökkel elrendezni a dolgot explicit.

 

Vajk

Előzmény: tanárnéni kedvence (5298)
NevemTeve Creative Commons License 2015.04.30 0 0 5299

Reggeli eredmény:

Server UTC: 20150429.220502.091337000 00:00 dow=3(0=Sun)
Server LT:  20150430.000502.091328000 02:00 dow=4(0=Sun)
Client UTC: 20150429.220502.091159000 00:00 dow=3(0=Sun)
Client LT:  20150430.000502.091159000 02:00 dow=4(0=Sun)

Note to self: de még az is kellene, hogy ne csak a pillanatnyi időpontot adja vissza, hanem abból x-másodpercet levonva/hozzáadva... vagy

ts := systimestamp + :add_sec/24/60/60;

lesz az, vagy

ts := systimestamp + numtodsinterval(:add_sec, 'second');

vagy valami más

tanárnéni kedvence Creative Commons License 2015.04.29 0 0 5298

Rosszul. Ahogy utaltam is rá az 5275-ben. Ráadásul jobból megint más az időzóna, mint az adatbázisé.

Előzmény: halaloszto (5295)
halaloszto Creative Commons License 2015.04.29 0 0 5297

iszonyat mennyi időt töltöttem már időzónák meg hasonlók megértésével és kódolásával. mindenféle rendelkezésreállási meg sla riportokon. örülök ha másnak is segít.

 

Vajk

Előzmény: NevemTeve (5296)
NevemTeve Creative Commons License 2015.04.29 0 0 5296

Nos, hála a te segítségednek, meg a google-nak, hogy lett egy fv, ami kigyűjti a szerver és a kliens aktuális időpontját, a tesztprogram kimenete:

 

$ ./date_test

Server UTC: 20150429.140839.785982000 00:00 dow=3(0=Sun)
Server LT:  20150429.160839.785975000 02:00 dow=3(0=Sun)
Client UTC: 20150429.140828.341893000 00:00 dow=3(0=Sun)
Client LT:  20150429.160828.341893000 02:00 dow=3(0=Sun)

és mondjuk a TZ-t meghaxolva:

 

$ TZ=Canada/Central ./date_test

Server UTC: 20150429.140616.048049000 00:00 dow=3(0=Sun)
Server LT:  20150429.160616.048041000 02:00 dow=3(0=Sun)
Client UTC: 20150429.140604.607865000 00:00 dow=3(0=Sun)
Client LT:  20150429.090604.607865000 -5:00 dow=3(0=Sun)

halaloszto Creative Commons License 2015.04.29 0 0 5295

az hogy az offset 2 óra nem jó szinte semmire, mert lehet hogy europe/budapest vagy nyáron, de az is lehet hogy europe/bucharest vagy télen. ha meg neked kell tudni hogy most nyár van vagy tél, akkor ott vagy ahonnan indultál.

 

én nagyon nemzetközi témában dolgozom, itt elképzelhetetlen hogy egy adatbázis ne UTC dbtimezone-al menjen. nincs tapasztalatom hogy milyen az ha a dbtimezone egy local time, és van benne pl átállás. hogy néz ki egy audit log akkor?

 

Vajk

Előzmény: NevemTeve (5294)
NevemTeve Creative Commons License 2015.04.29 0 0 5294

Ezt most nem tudom reprodukálni, a DBTIMEZONE most +02:00 vagyis CEST...

Előzmény: NevemTeve (5280)
NevemTeve Creative Commons License 2015.04.29 0 0 5293

Nem tudtam, de hasznos, köszi!

Előzmény: halaloszto (5292)
halaloszto Creative Commons License 2015.04.29 0 0 5292

azt gondolom tudod, hogy a to_char-nak explicit megmondhatod az nls date language-ot. a to_char(sysdate,'DAY','nls_date_language=hungarian') mindig azt adja hogy SZERDA (vagy ami van :-) )

Előzmény: NevemTeve (5291)
NevemTeve Creative Commons License 2015.04.29 0 0 5291

Épp ez az: egy szubrutint csinálok Pro*C-ben (aztán OCI-ben is meg kell), aminek territory és language függetlenül kellene működnie. Az lenne a cél, hogy egy fv lekérdezze a kliens localtime-ot, kliens UTC-t, szerver localtime-ot, szerver UTC-t, meg még ami ezek környékén van, pl day-of-week, dst-in-effect etc.

Sőt ugyanez a fv visszaadhatná a kliens-szerver időeltérést (persze az UTC nézve), hogy a hívó program esetleg azt modhassa: 'oké, az eltérés nagyobb mint öt perc, most leállok, majd akkor futok, ha valaki beállított valamit'

Előzmény: halaloszto (5290)
halaloszto Creative Commons License 2015.04.29 0 0 5290

Vagy csinálsz egy decode-ot ami a hétfőből egyet, a keddből kettőt csinál, és így tovább. Szerintem robosztusabb. És minden ilyen kódban explicit írni az nls-t, mert egyszer majd valaki egy japán sessionben futtatja, és fene tudja mi fog történni.

 

Vajk

Előzmény: NevemTeve (5289)
NevemTeve Creative Commons License 2015.04.29 0 0 5289

Random ötletem: a DBTIMEZONE megegyezik a to_date(SYSTIMESAMP,'TZH:TZM')-vel, akkor nincs DST, egyébként van. Rendkívül tudományos...

 

Off: Már az sem triviális, hogy a hét napját megkapjam, ugyanis a to_date('D') esetén territory-függő, hogy mit jelentenek az 1-7 számok. A megfejtés az, hogy lekérdezzük egy rögzített hétfői dátumra ugyanezt, és abból kalkulálunk.

halaloszto Creative Commons License 2015.04.28 0 0 5288

a data format mask-ban a tzd field mondja meg hogy az adott dátum az téli vagy nyári.

 

a systimestamp az timestamp with timezone tipust ad vissza. tehát lesz benne időzóna, de nem a session-é, hanem a database timezone. 

 

select to_char(from_tz ( cast(to_date('2015 01 01','yyyy mm dd') as timestamp) ,'europe/budapest') , 'TZD, TZR') from dual;
select to_char(from_tz ( cast(to_date('2015 07 01','yyyy mm dd') as timestamp) ,'europe/budapest') , 'TZD, TZR') from dual;

 

ez CET/CEST-et ad

 

 

select to_char(from_tz ( cast(to_date('2015 01 01','yyyy mm dd') as timestamp) ,'europe/moscow') , 'TZD, TZR') from dual;
select to_char(from_tz ( cast(to_date('2015 07 01','yyyy mm dd') as timestamp) ,'europe/moscow') , 'TZD, TZR') from dual;

 

ez viszont mindenképp MSK-t, mert az oroszoknál nincs óraátállítás.

 

 

select to_char(from_tz ( cast(to_date('2000 01 01','yyyy mm dd') as timestamp) ,'europe/moscow') , 'TZD, TZR') from dual;
select to_char(from_tz ( cast(to_date('2000 07 01','yyyy mm dd') as timestamp) ,'europe/moscow') , 'TZD, TZR') from dual;

 

ez meg MSK/MSD-t, mert 2000-ben még volt. frankó mi?

 

Vajk

Előzmény: NevemTeve (5287)
NevemTeve Creative Commons License 2015.04.28 0 0 5287

Pótkérdés: le lehet-e kérdezni , mondjuk a systimestamp-ból, hogy van-e nyári időszámítás?

halaloszto Creative Commons License 2015.04.28 0 0 5286

sajnos ki lehet. létezik időzóna nélküli timestamp. annak is van zónája, csak az adatbázis nem tud róla hogy mi az, nekünk kell megmondani.

 

 

pl ez a két utc time ugyarra a local time-ra konvertálódik. a tzd format maskkal lehet megtudni hogy az első vagy a másiodik 2:30 aznap.

select from_tz(to_timestamp ('2015 10 25 1:30','yyyy mm dd hh24:mi'), 'UTC') at time zone 'europe/budapest' from dual;
select from_tz(to_timestamp ('2015 10 25 0:30','yyyy mm dd hh24:mi'), 'UTC') at time zone 'europe/budapest' from dual;

 

 

select from_tz(to_timestamp ('2015 10 25 0:30','yyyy mm dd hh24:mi'), 'UTC') at time zone 'CET' from dual;

25-OCT-15 02.30.00.000000000 AM CET

 

select from_tz(to_timestamp ('2015 10 25 0:30','yyyy mm dd hh24:mi'), 'UTC') at time zone 'CEST' from dual;

ORA-01882: timezone region  not found

 

Vajk

Előzmény: edesviz (5284)

Ha kedveled azért, ha nem azért nyomj egy lájkot a Fórumért!