¿Por qué los valores de fecha / hora se interpretan incorrectamente al parchear / guardar?

Intento guardar datos de un formulario cakephp 3. Todos los datos están bien guardados pero datetime no. Tengo 2 campos de fecha y hora. Esos campos están llenos por el widget jquery-ui.

El problema parece haber sucedido cuando la entidad está pactando.

$intervention = $this->Interventions->patchEntity($intervention, $this->request->data); 
  • Depuración de $ this-> request-> data:

     'user_id' => '1', 'description' => 'test', 'starttime' => '2015/11/15 10:00', 'endtime' => '2015/11/15 12:10' 
  • Depuración de mi objeto $ intervention después de pacthEntity:

objeto (Aplicación \ Modelo \ Entidad \ Intervención)

 'id' => (int) 3, 'user_id' => (int) 1, 'description' => 'test', 'starttime' => null, 'endtime' => null ... 

starttime y endtime se vuelven nulos y no entiendo por qué.

¿Alguien tuvo este pb antes?

Intenté (para la depuración y la comprensión) forzar el valor de los campos después de la reparación y los campos de fecha y hora en mysql están bien.

 $intervention->starttime = date('Ymd H:i:s', strtotime($this->request->data['starttime'])); $intervention->endtime = date('Ymd H:i:s', strtotime($this->request->data['endtime'])); 

Gracias por la ayuda

Los valores de fecha / hora se están lanzando / analizando de forma consciente.


Actualización: este es el comportamiento predeterminado con las versiones de la plantilla de la aplicación CakePHP anteriores a 3.2.5. A partir de 3.2.5, el análisis regional ya no está habilitado por defecto, lo que hará que la lógica de clasificación de fecha / hora espere un valor predeterminado de Ymd H:i:s en Ymd H:i:s lugar.


En el proceso de clasificación, los valores se están “fundiendo” de acuerdo con los tipos de columna respectivos. Para las columnas DATETIME , esto se hace mediante la clase de tipo \Cake\Database\Type\DateTimeType .

Para ser exactos, esto se hace en \Cake\Database\Type\DateTimeType::marshall() .

Con la configuración predeterminada de la plantilla de la aplicación, DateTypeType está configurado para usar el análisis de configuración regional, y dado que no se está configurando ningún formato de configuración regional predeterminada, \Cake\I18n\Time::parseDateTime() analizará los valores de acuerdo con su formato predeterminado “a cadena” ( Time::$_toStringFormat ), que por defecto conoce la configuración regional [IntlDateFormatter::SHORT, IntlDateFormatter::SHORT] .

Por lo tanto, si, por ejemplo, su configuración regional está configurada en en_US , entonces el valor se analizará con un formato esperado de M/d/yy, h:mm a , que su valor no cabría, y por lo tanto, finalmente terminaría con null establecido para la propiedad de la entidad.

Haga que el analizador use el formato correcto

tl; dr

En caso de que el formato para el widget jQuery no se use en todas partes en su aplicación, podría, por ejemplo, establecer temporalmente el formato de configuración regional adecuado o deshabilitar el análisis regional, como

 $dateTimeType = Type::build('datetime')->setLocaleFormat('yyyy/MM/dd HH:mm'); // ... $intervention = $this->Interventions->patchEntity($intervention, $this->request->data); // ... $dateTimeType->setLocaleFormat(null); 

o

 $dateTimeType = Type::build('datetime')->useLocaleParser(false); // ... $intervention = $this->Interventions->patchEntity($intervention, $this->request->data); // ... $dateTimeType->useLocaleParser(true); 

Cabe señalar que esto afectará a todas las entradas de fecha / hora, ¡no solo a los campos de hora de inicio y hora de finalización!

Si el formato utilizado por el widget jQuery por otro lado es el formato que desea utilizar a través de su aplicación, entonces cambiar el formato predeterminado también podría hacerlo, como

 use Cake\I18n\Time; Time::setToStringFormat('yyyy/MM/dd HH:mm'); 

en tu bootstrap.php . Tenga en cuenta que también hay Time::setJsonEncodeFormat() y Time::$niceFormat que también puede querer modificar.

Ver también

  • Libro de cocina> Internacionalización y localización> Análisis de datos de fecha y hora localizados
  • Libro de cocina> Hora> Configurar la configuración regional predeterminada y la cadena de formato

Convierta la entrada antes de ordenarla

Otra opción sería, por ejemplo, convertir los datos en instancias de Time antes del proceso de clasificación. Esto evitaría posibles problemas con la solución mencionada anteriormente que afectaría a todas las entradas.

En su clase InterventionsTable (también podría incluirse en un comportamiento o un oyente externo):

 use Cake\Event\Event; use Cake\I18n\Time; ... public function beforeMarshal(Event $event, \ArrayObject $data, \ArrayObject $options) { foreach (['starttime', 'endtime'] as $key) { if (isset($data[$key]) && is_string($data[$key])) { $data[$key] = Time::parseDateTime($data[$key], 'yyyy/MM/dd HH:mm'); } } } 

Ver también

Libro de cocina> Acceso a la base de datos y ORM> Guardar datos> Modificar datos de solicitud antes de crear entidades