2010-09-23 11 views
5

Tengo una aplicación CakePHP que está extrayendo datos de dos bases de datos diferentes, que almacenan fechas y horas en sus datos de diferentes zonas horarias. La zona horaria de una base de datos es Europe/Berlin, y la otra es Australia/Sydney. Para hacer las cosas más complicadas, la aplicación está alojada en un servidor en los EE. UU. Y los tiempos deben presentarse al usuario final en su zona horaria local.convirtiendo fechas entre zonas horarias en AppModel-> afterFind (cakePHP)

Es bastante fácil decir a qué base de datos tengo que acceder, así que configuro la zona horaria apropiada (usando date_default_timezone_set()) en mi beforeFind para que la consulta se envíe con una fecha en la zona horaria correcta.

Mi problema está entonces convirtiendo las fechas en el afterFind en la zona horaria del usuario. Estoy pasando esta zona horaria a través de un parámetro con nombre, y para acceder a esto en el modelo estoy usando Configure::write() y Configure.read(). Esto funciona bien
El problema es que parece estar aplicando mi conversión de zona horaria varias veces. Por ejemplo, si estoy consultando la base de datos Australia/Sydney desde Australia/Perth, el tiempo debe ser de dos horas, pero sale con seis horas de retraso. Traté de hacer eco de los tiempos de mi función antes y después de convertirlos, y cada conversión funcionaba correctamente, pero estaba convirtiendo los tiempos más de una vez, y no puedo entender por qué.

Los métodos que uso actualmente (en mi AppModel) para convertir de una zona horaria a otra, es el siguiente:

function afterFind($results, $primary){ 
    // Only bother converting if the local timezone is set. 
    if(Configure::read('TIMEZONE')) 
     $this->replaceDateRecursive($results); 
    return $results; 
} 

function replaceDateRecursive(&$results){ 
    $local_timezone = Configure::read('TIMEZONE'); 

    foreach($results as $key => &$value){ 
     if(is_array($value)){ 
      $this->replaceDateRecursive($value); 
     } 
     else if(strtotime($value) !== false){ 
      $from_timezone = 'Europe/Berlin'; 
      if(/* using the Australia/Sydney database */) 
       $from_timezone = 'Australia/Sydney'; 
      $value = $this->convertDate($value, $from_timezone, $local_timezone, 'Y-m-d H:i:s'); 
     } 
    } 
} 

function convertDate($value, $from_timezone, $to_timezone, $format = 'Y-m-d H:i:s'){ 
    date_default_timezone_set($from_timezone); 
    $value = date('Y-m-d H:i:s e', strtotime($value)); 
    date_default_timezone_set($to_timezone); 
    $value = date($format, strtotime($value)); 

    return $value;      
} 

Así que, ¿alguien tiene alguna idea de por qué la conversión se está llevando varias veces? ¿O alguien tiene un mejor método para convertir las fechas? Obviamente estoy haciendo algo mal, solo estoy atrapado en lo que es eso.

+0

Gracias por este código, terminé haciendo algo muy similar. –

Respuesta

2

Encontré una solución. Realmente no entendí para qué era el parámetro $primary en el afterFind hasta ahora. Así que para arreglar mi código anterior, todo lo que tengo que hacer es cambiar el if en el afterFind a lo siguiente:

function afterFind($results, $primary){ 
    // Only bother converting if these are the primary results and the local timezone is set. 
    if($primary && Configure::read('TIMEZONE')) 
     $this->replaceDateRecursive($results); 
    return $results; 
} 

Como nota al margen, ya no estoy usando la función date_default_timezone_set() para hacer la conversión zona horaria, ya sea . Mi función convertDate ha cambiado de la siguiente manera:

function convertDate($value, $from_timezone, $to_timezone, $format = 'Y-m-d H:i:s'){ 
    $dateTime = new DateTime($value, new DateTimeZone($from_timezone)); 
    $dateTime->setTimezone(new DateTimeZone($to_timezone)); 
    $value = $dateTime->format($format); 

    return $value;      
} 
Cuestiones relacionadas