colburton
colburton

Reputation: 4715

Doctrine and DateTime showing wrong difference

I can't wrap my head around an issue with DateTime(). I want the difference between some saved time in the database and now. It works on my local machine but not on the live server.

This is my field definition:

/**
 * @ORM\Column(name="start_time", type="datetime", nullable=true)
 */
protected $startTime;    
/**
 * @ORM\Column(name="end_time", type="datetime", nullable=true)
 */
protected $endTime;

Setting start and end time and then calcualting the difference always works:

$diff = $entry->getEndTime()->diff($entry->getStartTime());

If only start time is set, I want the difference to the current time, so I do this:

$diff = (new \DateTime())->diff($entry->getStartTime());

But this does not work. The difference is 2 hours to low.

Start and end time are set with an form input like that:

// user inputs for example: 08:50 for $start and 17:45 for $end
$dateStr = date('Y-m-d');
$entry->setStartTime(new \DateTime($dateStr.' '.$start));
$entry->setEndTime(new \DateTime($dateStr.' '.$end));

I am guessing the 2 hours off come from having the timezone Europe/Berlin instead of UTC, but how do I accomodate for this?

Replacing new \DateTime()
with new \DateTime('now', new \DateTimeZone('Europe/Berlin'))
or new \DateTime('now', new \DateTimeZone('UTC'))
has no effect.

Thanks for you help.

Edit as requested

$currentDate = new \DateTime();
$currentDate->modify($currentDate->getOffset() . ' seconds');
// var_dump($entry->getStartTime())
object(DateTime)#358 (3) {
  ["date"]=> string(19) "2014-06-29 09:20:00"
  ["timezone_type"]=> int(3)
  ["timezone"]=> string(3) "UTC"
}
// var_dump($currentDate)
object(DateTime)#337 (3) {
  ["date"]=> string(19) "2014-06-29 06:50:00"
  ["timezone_type"]=> int(3)
  ["timezone"]=> string(3) "UTC"
}
// local time: 11:20:00
// difference should be: 2:30 but is 0:30

Upvotes: 1

Views: 2223

Answers (3)

David Jacquel
David Jacquel

Reputation: 52809

When a Berliner user fills 12:00 (12:00 Europe/Berlin in is mind - 10:00 in UTC time), doctrine saves a date (12:00) with no timezone.

When you retrieve you DateTime field, it is recreated by Doctrine as a 12:00 UTC (default application timeZone) and not a 12:00 Berlin.

So, you need to store User timezone in order to compare user provided dates with system provided ones. See Doctrine documentation

Upvotes: 1

heiglandreas
heiglandreas

Reputation: 3861

As DateTime::diff compares two date-objects it doesn't matter whether you set it to any timezone or not, as it - as far as I know - will first create the time and then set the timezone adapting the internal date appropriately. So new DateTime('now', new DateTimezone('Europe/Berlin')) and new DateTime('now', new DateTimezone('UTC')) reference the same time.

Therefore you will have to look what timezone your $entry->getStartTime() is in and adapt that appropriately to get the desired result. As the start (and end) time are given via a form I assume that you add them to the Entity without any timezone-information or with timezone UTC and you therefore compare a UTC-datetime with a Europe/Berlin-datetime. You should add those dates with a timezone-information to the database.

So as a workaround the following should work, but it is not a fix to the actual problem!

$currentDate = new \DateTime();
$currentDate->modify($currentDate->getOffset() . ' seconds');
$diff = $currentDate->diff($entry->getStartTime());

Upvotes: 1

David Jacquel
David Jacquel

Reputation: 52809

new \DateTime() returns your server time. And I guess your server is 2 hour late.

a date command in your terminal will tell you if I'm right.

Upvotes: 0

Related Questions