0

I have a bug on one of my feature with timezone, let me explain. The goal of this feature is to copy user events of a week to the next week.

I have a UserEvent model with this properties

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserEventRepository")
 */
class UserEvent
{
    /**
     * @ORM\Id()
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="datetime")
     */
    private $start;

    /**
     * @ORM\Column(type="datetime")
     */
    private $end;

    /**
     * @ORM\ManyToOne(targetEntity="UserEventType")
     * @ORM\JoinColumn(nullable=false)
     */
    private $type;

    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="userEvents")
     * @ORM\JoinColumn(nullable=false)
     */
    private $user;

    /* GETTERS AND SETTERS */
}

The datetime are stored in datebase in UTC timezone, and at the moment the client using the application is in the Europe/Paris timezone.

This is the logic to copy events to the next week

$newEvents = [];
foreach ($eventsToCopy as $event) {
    $newEvent = clone $event;
    $newEvent->getStart()->modify('+1 week');
    $newEvent->getEnd()->modify('+1 week');
    $newEvents[] = $newEvent;
}

The weekend are exlude from the week The problem appear on this weeks

WEEK A: 2017-10-23 to 2017-10-27

WEEK B: 2017-10-30 to 2017-11-03

There is a time change schedules between week A and week B therefore the planified hours on the second week are shifted on hour forward.

I can't do a high level change to handling DateTime and timezone, I can only modify this code (legacy application)

I'm not very confortable with timezone, maybe I'm missing something obvious.

Please give me your magic guideline to fix this case ! :)

Mcsky
  • 1,426
  • 1
  • 10
  • 20
  • 1
    If I had a penny for every time this problem afflicts devs ... :D Plase, check this [StackOverflow answer](https://stackoverflow.com/questions/2532729/daylight-saving-time-and-time-zone-best-practices) – DonCallisto Sep 20 '17 at 08:02

1 Answers1

0

I solved my problem by:

  1. Converting UTC from database to Europe/Paris
  2. Do my stuff to modify the datetime like I want
  3. Then I convert back my Europe/Paris datetime to UTC and save it in database

Code example

            $newEvent = new UserEvent();
            $newEvent->setUser($event->getUser());
            $newEvent->setType($event->getType());

            // Convert the datetimes of event to copy to Europe timezone
            // For my case I have only one timezone to handle at the moment, so it's always about Europe/Paris <=> UTC
            // In advanced use case you could convert the UTC datetime to the user's timezone
            list($start, $end) = $this->timezoneFormater->convertUTCDatetimeToEuropeDatetime([$event->getStart(), $event->getEnd()]);

            // Now set the date
            $start->modify('+1 week');
            $end->modify('+1 week');

            // Then convert back to UTC timezone
            list($start, $end) = $this->timezoneFormater->convertEuropeDatetimeToUTCDatetime([$start, $end]);
            $newEvent->setStart($start);
            $newEvent->setEnd($end);

            $newEvents[] = $newEvent;
Mcsky
  • 1,426
  • 1
  • 10
  • 20