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

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

问题描述

我尝试从 cakephp 3 表单中保存数据.所有数据都保存得很好,但日期时间没有.我有 2 个日期时间字段.这些字段由 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(AppModelEntityIntervention)

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

    starttime 和 endtime 变为 null,我不明白为什么.

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

    以前有人用过这个铅吗?

    Is somebody had this pb before ?

    我尝试(为了调试和理解)在修补后强制字段值和 mysql 中的日期时间字段都可以.

    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 列,这是由 CakeDatabaseTypeDateTimeType 类型类完成的.

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

    确切地说,这是在 CakeDatabaseTypeDateTimeType::marshall().

    使用默认应用模板配置,DateTimeType 配置为使用区域设置感知解析,并且由于未设置默认区域设置格式,CakeI18nTime::parseDateTime() 将根据其默认的字符串格式"(Time::$_toStringFormat),默认为语言环境感知[IntlDateFormatter::SHORT, IntlDateFormatter::简短].

    With the default app template configuration, DateTimeType is configured to use locale aware parsing, and since no default locale format is being set, CakeI18nTime::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;博士

    如果 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 CakeI18nTime;
    use CakeI18nFrozenTime;
    
    // 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');
    

    在您的 bootstrap.php 中.请注意,还有 Time/FrozenTime::setJsonEncodeFormat()Time/FrozenTime::$niceFormat 您可能想要/也需要修改.

    in your bootstrap.php. Note that there's also Time/FrozenTime::setJsonEncodeFormat() and Time/FrozenTime::$niceFormat which you may want/need to modify too.

    另见

    另一种选择是例如在编组过程之前将数据转换为 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 CakeEventEvent;
    use CakeI18nTime;
    
    ...
    
    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 > 数据库访问 &ORM > 保存数据 > 构建实体前修改请求数据

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

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