admin May 16th, 2009
Nem értem, hogy bírt ez elterjedni. Egy trágya és ezzel még dícsértem is. A timezone kezelése katasztrófális. Nem igazán értem magát az adattárolást sem, a JDBC driver írói pedig egy kicsivel a high school drop-out szint felett vannak (és ez már a saját bevallás szerint újraírt optimalizált változat). Létrehoznak egy Calendart, majd a visszaadandó Date típust ebből úgy állítják előt, hogy new Date(calendar.getTime().getTime()). Végülis, miért ne példányosítsunk minden egyes dátum olvasáskor és íráskor egy Date-t feleslegesen? És ez csak egy metódus volt. A goto-kat már nem is említem. Vagy a deklarált throws NullPointerExceptioneket. Ott már szinte sírtam. 1.5-ös JDK driver, de type safety nuku. Változónevek calendar1, calendar2, calendar3, calendar4. Beszédes. Ciklusváltozó: k1. new String() leírva. Így.
A timestamp with timezone adattípus JDBC konvertálása meg kritikán alúli. Hosszas keresgélés után sem találtam leírást arról, hogyan is működik ez CEST->CET átálláskor. Illetve annyit, hogy nem csak a TZR kell, hanem a TZD is ilyenkor. Mármint ha VARCHAR-t töltünk bele. Ezt értem. De ha java.util.Date kerül bele, akkor az miért nem jó (abban az Epoch óta van benne az idő, tehát minden tuti)? Illetve kiíráskor jó, olvasáskor nem. JDBC driver visszafejt. A következők derültek ki: byte[]-ben tárolja a GMT-be konvertált (persze nem a JDK TimeZone-ja alapján, hanem saját timezone adatok szerint) dátumot (akkor ha a oracle.jdbc.timestampTzInGmt true, ami defaultból igaz azt hiszem) és utána az offsetet. Ez OK, bár hatékonyabban is lehetne tárolni. Kiolvasás. Na, ez itt katasztrófa. Új Calendart hoz létre GMT TZ-vel, majd beletölti a GMT-be konvertált dátumot és hozzáadja a TZ offsetet, ebből csinál egy java.util.Date-t és azt visszaadja. Mindössze arról feledkeztek el a zseniális programozók, hogy CEST->CET, illetve hasonló átálláskor az így keletkező október 25 02:30 nem lesz egyértelmű, hogy CEST vagy CET és szopás van (szopunk is). Nem ám, hogy egy (TZ offsetnek) megfelelő Calendart hoznak létre és abba megy a dátum, majd getTime() és már jók is vagyunk. Lehet, hogy van oka annak, de ez így tuti nem jó. Hogy tesztelték ezt?
Úgy néz ki, hogy néhány timezone issue-t próbáltak így fixelni (11.1.0.7-es változat, tehát nem egy korai bétáról van szó!):
BUG-6749320
Timestamp values are incorrect around daylight savings time change
when the client time zone is different from the session time zone.
BUG-6870832
Same as 6749320 above but for TIMESTAMP WITH LOCAL TIME ZONE.
BUG-6977990
Wrong value TIMESTAMPLTZ when the retrieved timestamp is in the
DST overlap for the session timezone.
BUG-7028625
Wrong value of TIMESTAMPTZ with the retrieved value is near the
DST changeover.
Gratulálok! A kód már teljes mértékben áttekinthetetlen, aluldokumentált és már teljesen elvesztettem a fonalat. Javadoc reménytelen: “The timezone information is stored as an offset in the RegionID format or in the HOUR/MINUTE format”. Mikor melyik? Azt már nem írják le. Beszédes metódusnevek. getDate, getDate2. Hogy melyik micsoda, az csak akkor derül ki, ha visszafejti az ember és látja, hogy melyiket mikor hívják meg.
Hétfőn megpróbálom a oracle.jdbc.timestampTzInGmt-t false-ra állítani és úgy tesztelni. Amennyire átlátható az átláthatatlan kód, úgy ebben az esetben a dátum visszaadásakor legalább erőfeszítést tesz a helyes TZ beállítására. Találtam Eclipse kódot. Na, abból kezdem megérteni az Oracle driver működését. A kód fele az Oracle driver dátumkezelésének workaroundja.