Sziasztok,
A kerdesem egyszeru, de sok tesztesetet igenyel, amiket nem en akarok "elsokent megkeresni", ha mar mas is megtette. Adott egy erosen multilanguage, tobb orszagbol es tobb idozonabol hasznalt backoffice. Meg egy rakas adat, amit GROUP BY DATE(created_at)-ezik a mysql mikor grafikont rajzolunk. a GROUP BY DATE(created_at) szeretnenk, ha a browser idozonajanak megfeleloen futna le (form fieldkent kuldjuk, PHP adja at es escape-eli amugy).
Amit szeretnek:
Input:
JS-bol a browser felhasznalojanak timezone-ja valamilyen formaban (lehetoleg minel kevesebb (idealis esetben nulla) kulso lib felhasznalasaval. JQuery-t es moment.js -t amugy include-ol a projekt, de a Date() sem tunik olyan butanak, legjobban annak orulnek, ha csak az kene hozza)
Output:
String, amit a mysql megeszik, es atallitja azalapjan megfelelore az idozonat
(Ugy erzem a ketto kozt lesz valami szabvany amit nem ismerek/nem jut eszembe/nem vagyok biztos a teszteseteiben)
Peldak:
Tegyuk fel hogy iden nyaron vagyunk Londonban, vagy Budapesten
JS:
var d = new Date()
var n = d.getTimezoneOffset();
// n == -60 ha London (UTC vs BST (DST)), -120 Budapesten
MySQL-hez string generalas:
// summer: (in winter different offsets apply)
case -60:
return "SET time_zone = 'Europe/London';";
case -120:
return "SET time_zone = 'Europe/Budapest';";
Ahol futnia kell a JS resznek: mindenkori legujabb Chrome-on es Safarin (iOS mobil miatt) kivul sehol. Tehat nem zavar, ha nem fut IE8-on pl.
Elso ranezesre mukodo, de altalam nem kedvelt workaround (meg amugy sem tudom, hogy a nyari-teli valtas benne van-e, ha meg is oldom elmeletben, teszteset problemaim tovabbra is lesznek):
GROUP BY DATE(CONVERT_TZ(created_at,'+00:00','+02:00'))
- 1440 megtekintés
Hozzászólások
Apro mellekinformacio: a szerver OS minden esetben Unix-like vagy Unix-based: elesen Linux, dev kornyezetben MacOS.
Az idozonak Mac-en es Linuxon is igy lettek "feltoltve": https://gist.github.com/brianburridge/11298396
- A hozzászóláshoz be kell jelentkezni
Ugyebár az a nagy alap probléma, hogy a mysql mindenféle időcímkéket fog konvertálni, nemcsak current time-ot, tehát, mint a fenti példában látszik, neki komplett időzóna adatbázist kell(ene) adni, például "Europe/Budapest", ami akár még mondjuk például egy "Europe/Prague"-tól is különbözhet – nem mostanában, hanem múltbeli, és esetleg egyszer majd jövőbeli időpontokban is.
A getTimezoneOffset() viszont csak most adja meg az eltérést, az ég-világon semmit sem mond arról, hogy régebben, avagy a jövőben hogy is fog alakulni az offset, mikor voltak/lesznek óratologatások.
Azt keresed, hogy ebből a pillanatnyi offsetből hogyan lehet megkapni a komplett időzóna-leíró táblát az adott földrajzi helyre. Nyilván sehogy.
Nem tudok olyan JavaScript függvényről, amely a böngésző által használt teljes időzóna-leírót elérhetővé tenné számodra (de még csak libc függvényről sem; valszeg teljesen custom kóddal kell végignyalni a leíró fájlt). Marad tehát az, hogy a user választ egy listából (semmi autodetect), esetleg IP geolokáció alapján megtippelve a defaultot; vagy pedig korlátozottan és potenciálisan szarul működő hack hack hack mint amit odafenn felvázoltál.
- A hozzászóláshoz be kell jelentkezni
Azt ki lehet számolni, nyári vagy téli időszámítás van-e (megnézed, januárban mennyi az offset és júliusban mennyi az offset), ez alapján egy DB-vel be lehet lőni de ez egy ilyen kis bizonytalan hash ami tippelni fog.
Van erre viszont lib, a moment-timezone:
https://momentjs.com/timezone/
Nem egzakt megoldás (az nem is lehet), de célra talán jó lesz.
- A hozzászóláshoz be kell jelentkezni
Valóban, továbbgondolva, ha az összes ismert időzóna leírása benne van egy JS libben, akkor az próbálgatással (az offset megnézésével több időpillanatra is) meg tudja állapítani, hogy melyik van beállítva a böngészőben. Franc se tudja, van-e ilyen lib. Az általad linkeltben nem találom hirtelen, hogy ezt tudná.
- A hozzászóláshoz be kell jelentkezni
Nincs ezekre amugy valami szabvany?
DST pl. mindenhol ugyanaz nap all at? Ha igen, nincs valami szabvany ami mondjuk pl. UTC+1+(DST?'+1':'0') szinten leirja ezt, es tobb nyelvhez is van ertelmezoje tesztesetekkel?
- A hozzászóláshoz be kell jelentkezni
Koszi, ranezek majd
- A hozzászóláshoz be kell jelentkezni
Szia,
Igazából szép megoldás nem létezik, csak trükkök, amik közelítenek a megoldáshoz.
Pár alapötletet találhatsz itt:
https://stackoverflow.com/questions/1091372/getting-the-clients-timezon…
Üdv,
LuiseX
Szerk: kicsit felütve a mysql manualját, nem kötelező Europe/Budapest jelegben megadni, UTC-hez viszonyított offsettel is működik :)
( Ld. : https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html )
- A hozzászóláshoz be kell jelentkezni
Aha, és magától átáll nyáron vagy ez olyan lesz mint az "óraátállítás a HUP-on" topic, amit mai napig nem fogok fel teljesen?
- A hozzászóláshoz be kell jelentkezni
Szia,
Bocsi a késő válaszért, csak most jutottam el idáig :)
Az offsetet letudod kérdezni (ld. https://www.w3schools.com/jsref/jsref_gettimezoneoffset.asp , de ha rákattintottál volna a linkemre, látod ezt te is) a rendszertől, innentől kezdve, nem teljesen értem, mi nem tud átállni...
Ami mindig is problémás volt a TZ lekérdezése, mivel a böngészőkben futó JS motorok nem biztosítanak hozzáférést ezekhez az információkhoz. Egyszerűbben megfogalmazva, Europe/Budapest DST helyett UTC+2:00-t tudsz megszerezni (visszamenő kompatibilitással)...
Üdv,
LuiseX
- A hozzászóláshoz be kell jelentkezni
Informaciod Out of date, regi bongeszokre igaz. :)
- A hozzászóláshoz be kell jelentkezni
Szia,
Gondolom az első hozzászólás linkjét nem nézted meg te sem :) Ott kitérnek erre, nálam talán JS-hez jobban értő emberek.
Mindössze azért nem tartom megoldásnak, mivel átlagos esetben elég régi bőngészökön is üzemelnie kell az adott kódnak. Illetve, az általam felvetett ötlet az eredeti próblémára (feltételezésem szerint) megoldást nyújt: MySQL-nek megközelítő információt adni (eredetileg meg nem jelölt platformon) az időzónáról kliens oldalról.
Üdv,
LuiseX
- A hozzászóláshoz be kell jelentkezni
A szerver ismert időzónát használ, a kliens ismeretlent.
A kliens elküldi, hogy szerinte mennyi az aktuális helyi idő.
Ezután szerver oldalon ki tudod számolni, hogy a kliens helyi ideje és a szerver helyi ideje, valamint a szerver időzónája alapján, hogy a kliens milyen időzónában van.
Ennyi az egész.
- A hozzászóláshoz be kell jelentkezni
Ez nem teljesen jó. Evvel azt tudod megmondani, hogy *jelenleg* hány óra eltérés van a szerver és kliens ideje között, tehát a jelenlegi időpontot tudod jól formázni. Jövő/múltbeli időpontokra nem mindig fog működni. Mert lehet olyan, hogy két időzónában néha azonos a UTC offszet, de nem mindig. Illetve a kliens/szerver közötti offszet sem lesz állandó.
- A hozzászóláshoz be kell jelentkezni
Egesz addig mukodik, amig a JS el nem kuld egy olyan idozonat, ahol nincs DST, MySQL meg betolt egy olyat, ahol van. Onnantol kezdve a JS DAY(created_at)-en a par honappal ezelotti datumokon a grafikonnal onhover 23:00-t vagy 1:00-t mutat es jo esellyel ennek ellenere hasonlo szamot. :P
Aadaam megoldasa egy lepessel kozelebb van. Teljes megoldas azert nincs, mert nem letezik/nem lattunk (egyikunk sem ahogy elnezem) olyan szabvanyt, ami ezt egyertelmusitene.
Hozzateszem amit merunk, azt nem sokan hasznaljak este 23:00 es 1:00 kozott, ugyhogy szerintem ezt a reszet "el fogom engedni" a specifikacionak. Epp eleg nekunk, ha 01:00 es 23:00 kozott megbizhatoan mukodik USA-ban is, Ausztraliaban is es itt is DATE(created_at)-tel egyutt. Ez a statisztikai szignifikancia szintet messze nem lepi at
- A hozzászóláshoz be kell jelentkezni
1. mysql_tzinfo_to_sql /usr/share/zoneinfo
2. kliensoldali offset-et megadja a js, ezt elosztod 60-nal és meg is van ami kell neked pl. "set time_zone='-06:00';"
3. date és timestamp másképp tárolódik, ezt nézd át: https://dev.mysql.com/doc/refman/5.6/en/datetime.html
4. linkek:
https://dev.mysql.com/doc/refman/5.7/en/time-zone-support.html
https://dev.mysql.com/downloads/timezones.html
- A hozzászóláshoz be kell jelentkezni
datetime-ot es timestamp-et nagyon jol ismerem, de azert koszi.
"-06:00"-ban nincs DST
- A hozzászóláshoz be kell jelentkezni
lekerdezed a kliensen a datumot es elkuldod a szervernek, az osszehaosnlitja a szerver utc/gmt orajaval es megvan az offset. ennel megbizhatobbat nem tudok elkepzelni.
a mysqlbe meg mindent utc-ben tarolnek es megjeleniteskor konvertalnam csak.
- A hozzászóláshoz be kell jelentkezni
A mostani pillanatra jo, de Februarban 23:00-kor, 00:00-kor vagy 01:00-kor volt vege a napnak? ;) Ha pl. Februar es Junius kozt kernek le statot (kozte volt egy DST valtas, ami lehet A idozonat erintette, B-t nem).
- A hozzászóláshoz be kell jelentkezni
Az a baj, hogy az időzóna kezelés elsőre könnyűnek tűnik, de valójában baromi bonyolult, és ahogy itt is látszik, sok ember csak hiszi, hogy vágja az időzónákat, közben meg tele a világ bugos időzóna kódokkal. Egyszer meg akartam érteni a MySQL időzóna kezelését, de szerintem katasztrófa. A JS date/time API is elég gáz. Bugos megoldástól még a megoldás hiánya is jobb, tehát mindent egy fix időzónában kiírni, és kész.
- A hozzászóláshoz be kell jelentkezni
Ahan, tehat epp olyan idozona standardot igenylek, ami egyelore most nem letezik
- A hozzászóláshoz be kell jelentkezni
Itt az a baj, hogy az offset nem határozza meg a kliens időzónát. Viszont a moment.js-nél van olyan, hogy moment.tz.guess (link), ami vagy megy vagy nem.
Ha ez nem megy, akkor megpróbálhatod földrajzi koordináta vagy IP cím alapján "betippelni" az országot, de maga az offset az mindenképpen kevés ahhoz, amit szeretnél.
- A hozzászóláshoz be kell jelentkezni
"maga az offset az mindenképpen kevés ahhoz, amit szeretnél"
Ez eddigis megvolt, pont ezt irtam ;) De azert koszi.
- A hozzászóláshoz be kell jelentkezni
És a moment.tz.guess() se működik?
- A hozzászóláshoz be kell jelentkezni
Az valoszinuleg de, mukodni fog, egesz addig, amig valamelyik orszag meg nem valtoztatja az idozonajat :P
- A hozzászóláshoz be kell jelentkezni
Jó, hát mindenre azért nem lehet felkészülni :)
- A hozzászóláshoz be kell jelentkezni
> mysqlbe meg mindent utc-ben tarolnek es megjeleniteskor konvertalnam csak
Azaz, de meg igy is legyen ontesztelo a DB-t hasznalo kod ("erre a lekerdezesre ezt kell kapnom, ha nem akkor BAIL."), mert a mysql idozona kezelese completely, utterly braindead. Egy ideg latszolag mukodik, aztan egy admin atallitja a szerveren a LOCALE-t es a mysql elkezd konvertalgatni ossze vissza. Ugyanez, ha a DB connection locale-ja allitodik at. Vagy ha a szerver idoznaja (illik UTC-ben lennie, de lehetnek kivetelek). Ezek mind fuggetlenek a db-t hasznalo szoftvertol es a bongeszos klienstol is, tehat a programozo nincs ra hatassal. Es ez meg csak a kezdet a mysql idokezeles galadsagaival kapcsolatban.
Volt regebben egy nagyon jo cikk/blog ami ezt a "tudjuk, hogy teljesen random, de nem merunk valtoztatni a legacy dolgok miatt" allapotot bemutatta, de nem talalom. Valaki?
- A hozzászóláshoz be kell jelentkezni
Regi bongeszokre ott a hack. Ujakra meg: Intl.DateTimeFormat().resolvedOptions().timeZone
- A hozzászóláshoz be kell jelentkezni
Nahát, hol tart már a tudomány, ott a pont. Nálam jót írt ki.
- A hozzászóláshoz be kell jelentkezni
Ezt nagyon szepen koszonom. Tokeletesen megfelel a leirasnak (kiveve a tesztesetes tulzasaimat :P )
Regi bongeszoket ez a projekt szerencsere semennyire sem tamogat. Plane nem egy ilyen szokoevente megnyitott csak bejelentkezve latszodo statisztikust igenylo feature-hoz. :P
Fun fact - Microsoft Edge-en nem mukodik (nekunk nem szamit)
- A hozzászóláshoz be kell jelentkezni
up2date edgel mukodnie kell
- A hozzászóláshoz be kell jelentkezni
Valoban ez egy 2015-os build. Modern.ie + parallels ezt huzta be.
- A hozzászóláshoz be kell jelentkezni
Lazán kapcsolódik:
https://youtu.be/-5wpm-gesOY
- A hozzászóláshoz be kell jelentkezni