使用 JMS 序列化程序对日期时间进行反序列化和序列化之间的奇怪偏移

问题描述

我正在开发一个调度应用程序,其前端通过基于 UNIX 时间戳的时间字段与后端通信。该应用程序已经在生产中使用了将近一年,但突然间,感谢上帝,只有在测试服务器上,每次保存和重新加载事件,都会向事件的时间戳添加 1h 偏移量。我无法在本地重现它。

这是我配置序列化程序的方式。

 /**
     * @ORM\Column(type="datetime")
     * @JMS\Type("DateTime<'U'>")
     */
    private $start;

错误示例:我在 MET 下午 4 点安排了一个活动。我的前端计算时间戳 1614870000,将其发送到服务器。当我重新加载时,我得到 1614873600 作为时间戳,当然,在我的前端显示为 5 pm MET。我可以重复这些步骤,保存并重新加载,我的活动将被安排得越来越晚......

显然,序列化和反序列化是不同步的。或读取和写入数据库。但是怎么可能呢?我已经尝试将 MySql 时区和 PHP 时区设置为荒谬的值(本地),但根本无法重现任何奇怪的行为。 (除此之外,我根本不知道系统是如何知道正确的时区的,因为显然它没有存储在数据库中,所以我认为当我切换时区时,事件至少应该改变它们的开始时间,而他们不这样做' t.) 这是一个字段在数据库中的外观:

+---------------------+

| start               |

+---------------------+

| 2021-03-04 23:00:00 |

+---------------------+

这是我从数据库获取事件的方式:

$events = $repository->findAll();
        

        $serializer = $this->container->get('jms_serializer');
        $context = new SerializationContext();
        $context->setSerializeNull(true);
        $data = $serializer->serialize($events,'json',$context);

这是保存/反序列化方面:

$event = $serializer->deserialize($request->getContent(),Event::class,'json');
        $event->setLastEditUser($user);
        $event->setCreatedUser($user);
        $em = $this->getDoctrine()->getManager();
        $em->persist($event);
        $em->flush();

您对如何调试有任何想法吗?或者为什么会发生这种情况?同样,此错误仅出现在测试服务器上,不幸的是,我无法直接访问该服务器,但尝试与管理员联系。

解决方法

好的,再做一些研究,我想我明白了:

答案是 JMS 序列化程序和学说之间关于时区的不同缓存行为。不知何故,服务器管理员更改了时区。他说他将其更改为 Europe/Berlin(来自 UTC),而我的调试输出则相反。反正。假设以下情况:

保存事件:

FE:“保存带有时间戳的事件 1614956400

BE:“好吧,JMS Serializer 说我收到一个事件, $start = DateTime "2021/3/5 16:00:00 GMT+01:00"(JMS Serializers Default Timezone 似乎卡在缓存中。)

DB:“教义告诉我要保存 2021/3/5 16:00:00”(

...

加载该事件:

FE:“请再给我一次那个活动”

BE:“DB,你说什么?”

DB:“活动时间为 2021/3/5 16:00:00”

BE:“好的,教义,用它制作一个 PHP 日期时间......教义说它是 2021/3/5 16:00:00 UTC。JMS-Serializer,请告诉前端。好的,它的:1614960000"

Tadaaa。开始了。所以,我们有两个陷阱:

  1. Doctrines DateTime 不存储时区,在这种情况下会导致信息丢失,从而为误解留出空间。
  2. 默认时区的不同缓存导致不匹配...

那么,也许真正的问题是我选择了错误的学说数据类型?

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...