Symfony CRM中FullCalendar编辑3月31日后事件默认跳至2018-08-20求助
排查思路与解决方案
我之前碰到过Symfony DateTimeType结合时区的类似坑,结合你描述的现象——3月31日后的事件仅编辑环节日期异常,展示、数据库、JSON返回都正常——大概率是表单处理时区/日期解析时出了问题,给你几个具体的排查方向和解决办法:
1. 强制指定表单DateTimeType的时区
你的JSON返回和数据库存储的日期都明确使用Europe/London时区,但Symfony的DateTimeType默认会使用系统或框架全局时区(可能不是伦敦时区)。夏令时切换(2018年英国夏令时从3月25日开始)后,时区偏移计算错误就会触发日期异常。
修改Form Type代码,给日期字段加上时区配置:
$builder->add('booking_date', DateTimeType::class, array( 'label' => 'Start Date', 'required' => true, 'widget' => 'single_text', 'label_attr' => array( 'class' => 'control-label required' ), 'attr' => array( 'class' => 'form-control pickr required' ), 'timezone' => 'Europe/London' // 明确指定时区 )); $builder->add('end_date', DateTimeType::class, array( 'label' => 'End Date', 'required' => true, 'widget' => 'single_text', 'label_attr' => array( 'class' => 'control-label required' ), 'attr' => array( 'class' => 'form-control pickr required' ), 'timezone' => 'Europe/London' // 同样添加时区配置 ));
2. 明确日期格式,避免解析歧义
你的bookingDate和endDate仅存储日期部分(时间为00:00),但DateTimeType默认会解析完整的日期时间字符串。可以指定格式只解析日期部分,避免夏令时带来的时间偏移干扰:
// 在DateTimeType的配置中新增format选项 'format' => 'yyyy-MM-dd',
这个格式要和前端pickr插件输出的日期格式保持一致,确保前后端解析无歧义。
3. 检查实体字段的Doctrine映射时区
确认实体中日期字段的Doctrine映射是否指定了正确时区,如果存储的是带时区的日期,映射时未指定会导致Symfony读取时转换错误:
/** * @ORM\Column(type="datetime", timezone="Europe/London") */ private $bookingDate; /** * @ORM\Column(type="datetime", timezone="Europe/London") */ private $endDate;
4. 调试表单前后端的日期值
在控制器中添加调试代码,定位问题环节:
// 编辑页面GET请求时,输出实体原始日期值 $booking = $this->getDoctrine()->getRepository(Booking::class)->find($id); var_dump($booking->getBookingDate()->getTimezone()->getName()); // 应输出Europe/London var_dump($booking->getBookingDate()->format('Y-m-d H:i:s')); // 应输出2018-04-08 00:00:00 // 查看表单绑定后的初始值 $form = $this->createForm(BookingType::class, $booking); var_dump($form->get('booking_date')->getData()->format('Y-m-d H:i:s'));
如果实体原始值正确,但表单值异常,说明是表单渲染时的时区/格式问题;如果前端输入框初始值就不对,要检查pickr插件的时区配置是否正确。
内容的提问来源于stack exchange,提问作者Michael Emerson
相关产品推荐
相关产品推荐

