为什么打补丁/保存时日期/时间值解释不正确? [英] Why are date/time values interpreted incorrectly when patching/saving?

查看:180
本文介绍了为什么打补丁/保存时日期/时间值解释不正确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试从cakephp 3表单保存数据.所有数据保存正确,但日期时间保存不正确.我有2个datetime字段.这些字段由jquery-ui小部件填充.

I try to save data from a cakephp 3 form. All data are well saved but datetime not. I've got 2 datetime fields. Those fields are filled by jquery-ui widget.

放置实体时似乎发生了此问题.

The problem seems to happened when pacthing entity.

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

  • 调试$ this-> request-> data:

    'user_id' => '1',
    'description' => 'test',
    'starttime' => '2015/11/15 10:00',
    'endtime' => '2015/11/15 12:10'
    

  • 在pacthEntity之后调试我的对象$ intervention:

    object(App \ Model \ Entity \ Intervention)

    object(App\Model\Entity\Intervention)

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

    开始时间和结束时间为空,我不明白为什么.

    starttime and endtime become null and I don't understand why.

    有人以前有这个铅吗?

    我试图(用于调试和理解)在修补后强制字段值 mysql中的datetime字段都可以.

    I tried (for debuging and understanding) to force fields value afer patching and datetime fields in mysql are ok.

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

    感谢帮助

    推荐答案

    日期/时间值以语言环境感知的方式强制转换/解析


    更新:这是3.2.5之前的CakePHP应用程序模板版本的默认行为.从3.2.5版本开始,默认情况下不再启用区域设置解析,这将使日期/时间编组逻辑期望使用默认格式Y-m-d H:i:s.

    在编组过程中,将根据相应的列类型投射"值.对于DATETIME列,这是通过\Cake\Database\Type\DateTimeType类型类完成的.

    In the marshalling process, values are being "casted" according to the respective column types. For DATETIME columns, this is done by the \Cake\Database\Type\DateTimeType type class.

    确切地说,这是在 \Cake\Database\Type\DateTimeType::marshall() .

    使用默认应用模板配置,将DateTimeType配置为使用可感知区域设置的解析,并且由于未设置默认区域设置格式,因此 Time::$_toStringFormat ),默认为支持区域设置的[IntlDateFormatter::SHORT, IntlDateFormatter::SHORT].

    With the default app template configuration, DateTimeType is configured to use locale aware parsing, and since no default locale format is being set, \Cake\I18n\Time::parseDateTime() will parse the values according to its default "to string format" (Time::$_toStringFormat), which defaults to the locale aware [IntlDateFormatter::SHORT, IntlDateFormatter::SHORT].

    因此,例如,如果您的语言环境设置为en_US,则将使用期望的格式M/d/yy, h:mm a解析该值,该值将不适合您的值,因此您最终会以null为实体属性设置.

    So, if for example your locale is set to en_US, then the value would be parsed with an expected format of M/d/yy, h:mm a, which your value wouldn't fit, and hence you'd finally end up with null being set for the entity property.

    tl; dr

    如果jQuery小部件的格式未在您的应用程序中到处使用,则可以例如临时设置适当的语言环境格式,或禁用语言环境解析,例如

    In case the format for the jQuery widget is not being used everywhere in your app, you could for example either temporarily set the proper locale format, or disable locale parsing, like

    // for time- or date-only comlumn types you'd use 'time' or 'date' instead of 'datetime'
    $dateTimeType = Type::build('datetime')->setLocaleFormat('yyyy/MM/dd HH:mm');
    
    // ...
    $intervention = $this->Interventions->patchEntity($intervention, $this->request->data);
    // ...
    
    $dateTimeType->setLocaleFormat(null);
    

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

    请注意,这将影响所有日期/时间输入,不仅会影响您的starttimeendtime字段!

    It should be noted that this will affect all date/time input, not just your starttime and endtime fields!

    另一方面,jQuery小部件使用的格式应该是您希望在整个应用程序中一直使用的格式,然后更改默认格式也可以做到这一点,例如

    Should the format used by the jQuery widget on the other hand be the format that you wish to use all the way through your app, then changing the default format could do it too, like

    use Cake\I18n\Time;
    use Cake\I18n\FrozenTime;
    
    // To affect date-only columns you'd configure `Date` and `FrozenDate`.
    // For time-only columns, see the linked SO question below.
    Time::setToStringFormat('yyyy/MM/dd HH:mm');
    FrozenTime::setToStringFormat('yyyy/MM/dd HH:mm');
    

    中的

    .请注意,您可能还希望/也需要修改Time/FrozenTime::setJsonEncodeFormat()Time/FrozenTime::$niceFormat.

    另请参见

    另一种选择是例如在编组过程之前将数据转换为Time实例.这样可以避免前面提到的解决方案可能会影响所有输入的问题.

    Another option would be to for example convert the data to Time instances before the marshalling process. This would avoid possible problems with the previous mentioned solution that would affect all input.

    在您的InterventionsTable类中(也可以放入行为或外部侦听器中):

    In your InterventionsTable class (could also be put 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');
            }
        }
    }
    

    另请参见

    Cookbook > Database Access & ORM > Saving Data > Modifying Request Data Before Building Entities

    这篇关于为什么打补丁/保存时日期/时间值解释不正确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆