Ci ho messo 2 gg per riuscire a capire il perchè la categoria di applicazione Date & ORBDateTime non funziona sempre come da aspettative.
In questo caso ho creato un semplice PHP service:
class Debug { public function printR($object) { return print_r($object, true); } public function echoObject($object) { return $object; } public function timeToDate($time) { return new ORBDateTime($time * 1000, 0); } public function mysqlDatetimeToTime($datetime) { $is_daylight_savings_time = -1; if (preg_match('|^([\d]{4})-([\d]{1,2})-([\d]{1,2}) +([\d]{1,2}):([\d]{1,2}):([\d]{1,2})$|', $datetime, $matches)) { $year = $matches[1]; $month = $matches[2]; $day = $matches[3]; $hour = $matches[4]; $minute = $matches[5]; $second = $matches[6]; if (!checkdate($month, $day, $year)) throw new Exception('Invalid date specification: ' . $year . '-' . $month . '-' . $day);; if (!(0 < = $hour && $hour <= 24)) throw new Exception('Invalid time specification, out of range hour: ' . $hour); if (!(0 <= $minute && $minute <= 60)) throw new Exception('Invalid time specification, out of range minute: ' . $minute); if (!(0 <= $second && $second <= 60)) throw new Exception('Invalid time specification, out of range seconds: ' . $second); return mktime($hour, $minute, $second, $month, $day, $year, $is_daylight_savings_time); } throw new Exception('Invalid datetime format, expected format: YYYY-MM-DD hh:mm:ss'); } public function mysqlDatetimeToDate($datetime) { return new ORBDateTime($this->mysqlDatetimeToTime($datetime) * 1000, 0); } }
In particolare, chiamando service.printR(object) da Flex, posso ottenere una rappresentazione di qualunque oggetto ActionScript:
com.example.project.Debug.printR(new Date(2008, 7, 15, 12, 0, 0, 0); // 2008-08-15 12:00:00.000) returned: "ORBDateTime Object ( [m_milliseconds:private] => 1.2187944E+12 [m_timeZone:private] => 0 ) "
Chiamando service.mysqlDatetimeToDate(string) devo tornare a ActionScript Date object da una (string) formato “YYY‚MM-DD hh:mm:ss”:
com.example.project.Debug.mysqlDatetimeToDate("2008-08-15 12:00:00") returned: Fri Aug 15 12:00:00 GMT+0200 2008
Chiamando seervice.mysqlDatetimeToTime(string), ottengo il numero di secondi dalla Unix Epoch in formato (string) “YYYY-MM-DD hh:mm:ss” :
com.example.project.Debug.mysqlDatetimeToTime("2008-08-15 12:00:00") returned: 1218794400
Funziona correttamente quasi sempre, infatti il timestamp della funzione mkdate() di php corrisponde a m_milliseconds dell’oggetto ORBDateTime (moltiplicati per 1000):
------------------------------------------------------------------------------------------------- com.example.project.Debug.printR(new Date(1902, 0, 1, 0, 0, 0, 0); // 1902-01-01 00:00:00.000) returned: "ORBDateTime Object ( [m_milliseconds:private] => -2145920400000 [m_timeZone:private] => 0 ) " ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToDate("1902-01-01 00:00:00") returned: Wed Jan 1 00:00:00 GMT+0100 1902 ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToTime("1902-01-01 00:00:00") returned: -2145920400 ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- com.example.project.Debug.printR(new Date(1912, 0, 1, 0, 0, 0, 0); // 1912-01-01 00:00:00.000) returned: "ORBDateTime Object ( [m_milliseconds:private] => -1.8303876E+12 [m_timeZone:private] => 0 ) " ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToDate("1912-01-01 00:00:00") returned: Mon Jan 1 00:00:00 GMT+0100 1912 ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToTime("1912-01-01 00:00:00") returned: -1830387600 ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- com.example.project.Debug.printR(new Date(1969, 11, 31, 23, 59, 59, 0); // 1969-12-31 23:59:59.000) returned: "ORBDateTime Object ( [m_milliseconds:private] => -3601000 [m_timeZone:private] => 0 ) " ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToDate("1969-12-31 23:59:59") returned: Wed Dec 31 23:59:59 GMT+0100 1969 ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToTime("1969-12-31 23:59:59") returned: -3601 ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- com.example.project.Debug.printR(new Date(1970, 0, 1, 0, 0, 0, 0); // 1970-01-01 00:00:00.000) returned: "ORBDateTime Object ( [m_milliseconds:private] => -3600000 [m_timeZone:private] => 0 ) " ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToDate("1970-01-01 00:00:00") returned: Thu Jan 1 00:00:00 GMT+0100 1970 ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToTime("1970-01-01 00:00:00") returned: -3600 ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- com.example.project.Debug.printR(new Date(1970, 0, 1, 0, 59, 59, 0); // 1970-01-01 00:59:59.000) returned: "ORBDateTime Object ( [m_milliseconds:private] => -1000 [m_timeZone:private] => 0 ) " ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToDate("1970-01-01 00:59:59") returned: Thu Jan 1 00:59:59 GMT+0100 1970 ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToTime("1970-01-01 00:59:59") returned: -1 ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- com.example.project.Debug.printR(new Date(1970, 0, 1, 1, 0, 0, 0); // 1970-01-01 01:00:00.000) returned: "ORBDateTime Object ( [m_milliseconds:private] => 0 [m_timeZone:private] => 0 ) " ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToDate("1970-01-01 01:00:00") returned: Thu Jan 1 01:00:00 GMT+0100 1970 ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToTime("1970-01-01 01:00:00") returned: 0 -------------------------------------------------------------------------------------------------
C’è, per lo meno, un caso dove l’applicazione non è corretta:
------------------------------------------------------------------------------------------------- com.example.project.Debug.printR(new Date(1963, 7, 14, 14, 54, 22, 0); // 1963-08-14 14:54:22.000) returned: "ORBDateTime Object ( [m_milliseconds:private] => -201438338000 [m_timeZone:private] => 0 ) " ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToDate("1963-08-14 14:54:22") returned: Wed Aug 14 15:54:22 GMT+0200 1963 ------------------------------------------------------------------------------------------------- com.example.project.Debug.mysqlDatetimeToTime("1963-08-14 14:54:22") returned: -201434738 -------------------------------------------------------------------------------------------------
Penso siano collegati ad alcuni problemi di Daylight Saving Time, ma funziona fino il “2008-08-15 12:00:00″! Anche inserendo l’ultimo parametro(DST) di mktime() per 1 soltanto i problemi peggiorano ( tutto il resto dei dati diventa errato)
Seconda domanda: Il secondo parametro di ORBDateTime constructor (m_timeZone), dovrebbe rappresentare la compensazione dell’ ora (timezone) dal GMT, ma in che unità di misura? Ore? Minuti? Secondi? Millisecondi? Com’ è specificata, come un numero intero o n serie( come GTM + 0200″ o del genere)?
Una soluzione potrebbe essere il salvataggio dei dati UTC nel database, dopo questo dovrà essere convertito (solo una volta) dal client con l’ora locale. Questa conversione potrebbe essere giusta o sbagliata( forse per alcuni dati precedenti), ma per lo meno all’origine(database) dell’ora e di conseguenza tutti i calcoli relativi diventerebbero corretti..
Infatti i millisecondi scambiati tra Flex & PHP sono assoluti: Millisecondi da Unix Epoch time: ” 1970-01-01 00:00:00″, l’ingannevole punto che non mi era chiaro: il GMT time, che significa che l tempo 0 è attualmente ” 1970-01-01 00:00:00″ nella zona “Europe/Rome”. Quindi, usando l’orario UTC nel server trasmetto l’orario UTC nella rete senza alcuna conversione(d’orario), la quale verrà effettuata, se necessario, solo dal client flex.
C’è un altro problema comunque, la funzione php mktime() , è valida approssimativamente solo nell’intervallo tra 1901-2038. UNIX_TIMESTAMP() agisce ancor peggio: non ritorna al “tempo base”, quindi le date antecedenti al 1900-01-01 non sono considerate valide.
La soluzione in questo caso è l’uso della funzione di PHP5 DateTime(), che si comporta all’incirca come strtime(), che lega la data in qualunque formato standard e ritorna la “data base”; la differenza è il tipo di dati double anzichè int, cosicchè vada molto più in la dell’intervallo 1901-2038:
$date = $db_row['date']; // 'YYYY-MM-DD HH::MM:SS' $dateTime = new DateTime($date, new DateTimeZone('UTC')); return new ORBDateTime($dateTime->format('U') * 1000, 0);
Inoltre, se si specifica qualunque data( senza l’ora), è meglio specificare direttamente UTC, con metodo setUTCXXX() di ActionScript Date class, quindi non accadrà nessuna conversione oraria locale.





