Different Timezone_Types on Datetime Object

Different timezone_types on DateTime object

Timezones can be one of three different types in DateTime objects:

  • Type 1; A UTC offset, such as in new DateTime("17 July 2013 -0300");
  • Type 2; A timezone abbreviation, such as in new DateTime("17 July 2013 GMT");
  • Type 3: A timezone identifier, such as in new DateTime( "17 July 2013", new DateTimeZone("Europe/London"));

Only DateTime objects with type 3 timezones attached will allow for DST correctly.

In order to always have type 3 you will need to store the timezone in your database as accepted identifiers from this list and apply it to your DateTime object on instantiation.

compare datetime with different timezone_type php

The really weird part is your initial value of 1409900072+0200. If 1409900072 is a UNIX timestamp, passing a particular timezone with it makes little sense. And it seems to cause PHP to create the instance incorrectly; it creates the instance with the time set to the UTC value (6:54), but the timezone offset of +0200 (where the time should actually be 8:54).

Arguably this should be filed as a bug report; but arguably the input data is nonsensical to begin with.

If you're feeding in a UNIX timestamp, then ignore any timezone information it may contain and explicitly set the timezone to UTC, then it all works as expected:

$t1 = DateTime::createFromFormat('U+', '1409900072+0200', new DateTimeZone('UTC'));
$t2 = new DateTime('2014-09-05 07:54:32', new DateTimeZone('Europe/Copenhagen'));

var_dump($t1 > $t2); // true

Note that PHP before 5.3.9 seems to have problems with the createFromFormat call; you'll probably have to filter out the trailing timezone by hand if you need to support those versions.

PHP - comparing datetime objects with different timezone

DateTime objects with different time zones are considered the same for simple comparison if they represent the same time.

Example:

$dt1 = new DateTime('2019-10-10 00:00', new DateTimeZone('UTC'));
$dt2 = new DateTime('2019-10-10 03:00', new DateTimeZone('Europe/Bucharest'));
var_dump($dt1 == $dt2); //bool(true)

The result of comparison is equal because at the time of 2019-10-10 00:00 it was already 03:00 in Bucharest.
The comparisons with larger and smaller work analogously.

Note: DateTime has implemented special comparisons for this and reacts differently than the comparison of "normal objects"

PHP: Comparing two DateTime objects with different timezones

According to the manual:

As of PHP 5.2.2, DateTime objects can be compared using comparison operators.

You've chosen a very confusing example that includes a fixed date that's not clear if it's supposed to be in the past and a time zone that's currently not active (it's CEST here in Western Europe until the end of October). Whatever, I see nothing wrong in your output: 2015-10-09 10:53:42 CET (which equals 2015-10-09 09:53:42 UTC) is clearly greater than 2015-10-09 10:28:01 Europe/Paris (which equals 2015-10-09 08:28:01 UTC).

With a slightly better example we can guess the operands do work as expected:

    echo "Same date:\n";
$a = new DateTime('2015-01-31 01:23:45 UTC');
$b = new DateTime('2015-01-31 02:23:45 Europe/Paris');
var_dump($a, $b, $a<$b, $a==$b, $a>$b);
echo "\n";

echo "First greater than second:\n";
$a = new DateTime('2015-01-31 01:23:46 UTC');
$b = new DateTime('2015-01-31 02:23:45 Europe/Paris');
var_dump($a, $b, $a<$b, $a==$b, $a>$b);
echo "\n";

echo "First less than second:\n";
$a = new DateTime('2015-01-31 01:23:45 UTC');
$b = new DateTime('2015-01-31 02:23:46 Europe/Paris');
var_dump($a, $b, $a<$b, $a==$b, $a>$b);
Same date:
[...]
bool(false)
bool(true)
bool(false)

First greater than second:
[...]
bool(false)
bool(false)
bool(true)

First less than second:
[...]
bool(true)
bool(false)
bool(false)

Demo with full code.

Another example:

$date_2014 = new DateTime('2014-12-31 23:00:00 -07:00');
$date_2015 = new DateTime('2015-01-01 05:00:00 Asia/Tokyo');
var_dump($date_2014<$date_2015); // bool(false)

DateTime class returning incorrect timezone_type and timezone?

As to why this happens: your PHP install may have Europe/Berlin set as its default time zone.

Either way, createFromFormat as a timezone argument that you should be able to use:

 ...createFromFormat('Y-m-d H:i:s', $inputDateTime, new DateTimeZone("UTC"));

should do the trick.

PHP DateTime::createFromFormat return wrong date

Because in 2021, February 5 is Friday, and February 8 is Monday.

Accurately compare dates from different timezones with zeroed time

I may have misunderstood your question, but I'll assume that you just want to determine whether the two dates are the same, after they have been adjusted for the timezone offset.

Using the two DateTime objects simply call DateTime::diff. If the number of days difference is zero, the two dates are the same (ignoring the time).

// Payroll date
$p = new DateTime('2018-05-01 00:00:00.000000', new DateTimeZone('Australia/Sydney'));

// Timesheet date
$t = new DateTime('2018-04-30 00:00:00.000000', new DateTimeZone('UTC'));

var_dump($t->diff($p)->days === 0); // same


Related Topics



Leave a reply



Submit