I'm developing a scheduling app whose frontend communicates with the backend via UNIX-Timestamp-based time fields. The app has been used for almost a year in production, but suddenly, thank god only on the test server, every save and reload of an event, adds a 1h offset to the event's timestamp. I can't reproduce it locally.
This is the way I configured the serializer.
/**
* @ORM\Column(type="datetime")
* @JMS\Type("DateTime<'U'>")
*/
private $start;
Example of the bug: I schedule an event at 4 pm MET. my frontend computes the timestamp, 1614870000, sends it to the server. When I reload, I get 1614873600 as the timestamp, which is, of course, displayed as 5 pm MET in my frontend. I can repeat these steps, save and reload, and my event will be scheduled later and later...
Obviously, serialization and deserialization are out of sync. Or reading and writing to the DB. But how can it be? I already tried setting the MySql Timezone and PHP timezones to absurd values (locally), but cannot reproduce ANY strange behavior at all. (Apart from that I do not know how the system knows the correct timezone at all, since apparently it is not stored in the DB, so I would think the events should at least change their start time when I switch timezones, which they don't.) This is how a field looks in the database:
+---------------------+
| start |
+---------------------+
| 2021-03-04 23:00:00 |
+---------------------+
And this is the way I get the events from the DB:
$events = $repository->findAll();
$serializer = $this->container->get('jms_serializer');
$context = new SerializationContext();
$context->setSerializeNull(true);
$data = $serializer->serialize($events, 'json', $context);
This is the saving/deserialization side:
$event = $serializer->deserialize($request->getContent(), Event::class, 'json');
$event->setLastEditUser($user);
$event->setCreatedUser($user);
$em = $this->getDoctrine()->getManager();
$em->persist($event);
$em->flush();
Do you have any ideas on how to debug this? Or why this could happen? Again, this bug only appears on a test server, on which I, unfortunately, do not have direct access, but try to be in contact with the admins.
Ok, some more research, and I think I got it:
The answer is different caching behaviour concerning time zones between JMS serializer and doctrine. Somehow, an admin for the server, changed the timezone. He said he changed it to Europe/Berlin (from UTC), my debug output says the opposite way. Anyway. Assume the following situation:
Saving an event:
FE: "Save Event with timestamp 1614956400"
BE: "Ok, JMS Serializer says I got an event with $start = DateTime "2021/3/5 16:00:00 GMT+01:00" (JMS Serializers Default Timezone seems to be stuck in cache.)
DB: "Doctrine told me to save 2021/3/5 16:00:00" (<= NO TIMEZONE!)
...
Loading that event:
FE: "Gimme that event again, please"
BE: "DB, what do you say?"
DB: "The event is at 2021/3/5 16:00:00"
BE: "Ok, doctrine, make a PHP DateTime out of it... Doctrine says it is 2021/3/5 16:00:00 UTC. JMS-Serializer, please tell the Frontend. Ok, its: 1614960000"
Tadaaa. Here we go. So, we got two pitfalls:
So, maybe the real problem was my choosing the wrong doctrine data type?