Why are date / time values ​​incorrectly interpreted when correcting / saving?

I am trying to save data from cakephp 3 form. All data is well saved but not. I have 2 datetime fields. These fields are populated with jquery-ui widgets.

The problem occurs when a pacthing entity.

$intervention = $this->Interventions->patchEntity($intervention, $this->request->data); 
  • Debugging data this this-> request->:

     'user_id' => '1', 'description' => 'test', 'starttime' => '2015/11/15 10:00', 'endtime' => '2015/11/15 12:10' 
  • Debugging my $ intervention object after pacthEntity:

object (App \ Model \ Entity \ Intervention)

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

start time and end time become zero, and I don’t understand why.

Has anyone had this pb before?

I tried (for debugging and understanding) to force the fields to use afer patching and the datetime fields in mysql are fine.

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

thanks for the help

+5
source share
1 answer

Date / time values ​​are recorded / analyzed in a mode known in the locale


Update: This is the default behavior with CakePHP application template versions prior to 3.2.5. Starting with version 3.2.5, locale parsing is no longer enabled by default, which will make the date and time marshalling logic expect Ymd H:i:s by default.


During the sorting process, the values ​​are cast according to the corresponding column types. For DATETIME columns, this is DATETIME a class of type \Cake\Database\Type\DateTimeType .

To be precise, this is done in \Cake\Database\Type\DateTimeType::marshall() .

With the default application template setting, DateTypeType configured to use locale-dependent parsing, and since the language format is not set by default, \Cake\I18n\Time::parseDateTime() will parse the values ​​according to the default "string format "( Time::$_toStringFormat ), which defaults to locale [IntlDateFormatter::SHORT, IntlDateFormatter::SHORT] .

So, if, for example, your locale is set to en_US , then the value will be parsed with the expected format M/d/yy, h:mm a , whose value does not fit, and therefore, you finally get null for the object property.

Make parser the correct format

TL; dg

If the jQuery widget format is not used everywhere in your application, you can, for example, either temporarily set the correct locale format or disable locale parsing, for example

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

or

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

It should be noted that this will affect all input data of the date and time, and not just the starttime and endtime !

If the format used by jQuery widgets, on the other hand, is the format that you want to use completely through your application, then changing the default format can also do this, for example

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

in bootstrap.php . Note that there is also Time::setJsonEncodeFormat() and Time::$niceFormat , which you can also change.

see also

Convert input before sorting it

Another option is to, for example, convert the data into Time instances before the sorting process. This would avoid possible problems with the previous solution, which would affect all input data.

In your class, InterventionsTable (can also be placed in a behavior or an external listener):

 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'); } } } 

see also

Cookbook> Database and ORM Access> Saving Data> Modifying Query Data Before Creating Objects

+17
source

Source: https://habr.com/ru/post/1236046/


All Articles