datetime - 为什么在修补/保存时日期/时间值解释不正确?

标签 datetime cakephp internationalization marshalling cakephp-3.0

我尝试从 cakephp 3 表单中保存数据。所有数据都保存得很好,但日期时间没有。我有 2 个日期时间字段。这些字段由 jquery-ui 小部件填充。

问题似乎发生在对实体进行打包时。

$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 :

  • 对象(应用程序\模型\实体\干预)
    'id' => (int) 3,
    'user_id' => (int) 1,
    'description' => 'test',
    'starttime' => null,
    'endtime' => null
    ...
    

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

    有人以前有这个铅吗?

    我尝试(用于调试和理解)在修补后强制字段值
    和 mysql 中的日期时间字段都可以。
    $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 完成的类型类。

    准确地说,这是在 中完成的。 \Cake\Database\Type\DateTimeType::marshall() .

    使用默认应用模板配置,DateTimeType配置为使用语言环境感知解析,并且由于没有设置默认语言环境格式, \Cake\I18n\Time::parseDateTime() 将根据其默认的“字符串格式”( Time::$_toStringFormat )解析值,默认为语言环境感知 [IntlDateFormatter::SHORT, IntlDateFormatter::SHORT] .

    因此,例如,如果您的语言环境设置为 en_US ,那么该值将被解析为预期格式 M/d/yy, h:mm a ,您的值不适合,因此您最终会得到 null为实体属性设置。

    使解析器使用正确的格式

    tl;博士

    如果 jQuery 小部件的格式未在您的应用程序中的任何地方使用,您可以例如临时设置正确的语言环境格式,或禁用语言环境解析,例如

    // 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领域!

    另一方面,如果 jQuery 小部件使用的格式是您希望在整个应用程序中使用的格式,那么更改默认格式也可以,例如
    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');
    

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

    也可以看看
  • Cookbook > Internationalization & Localization > Parsing Localized Datetime Data
  • Cookbook > Time > Setting the Default Locale and Format String
  • CakePHP 3 time column gets date added

  • 在编码之前转换输入

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

    在您的 InterventionsTable类(也可以放在行为或外部监听器中):
    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

    关于datetime - 为什么在修补/保存时日期/时间值解释不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33734683/

    相关文章:

    php - Cakephp 2.x 停放域 https 不工作

    java - Maven过滤乱码特殊字符

    mysql - 获取 MYSQL SELECT 中的剩余天数(减去 3 个日期时间)

    python - 从日期时间列中提取日期作为数组

    MySQL 减去两个日期时间并以纳秒为单位返回

    php - CakePHP 数据库查询 DISTINCT/GROUP BY 错误

    cakephp - 仅在cakephp中查询具有日期条件的日期时间字段

    wpf - 如何在基于 WPF XAML 的 UI 上提供语言支持

    php - 生成 Yii 翻译消息文件

    java - 如何重新格式化时间格式?