Reputation: 1562
I have a Ubuntu / Apache2 / PHP (Symfony2) / MySQL date problem. I think it is a system problem, as I don't have it in dev env, only in rec and prod envs. When I POST a form containing a datetime, it is 2 hrs less in DB that what I have entered. When I read it, I have the same datetime on screen that what I have in DB. The 2 hrs difference meets my timezone (Europe/Paris).
Dev environment :
rec / prod environments :
When I run date -R
on both machines, I have a match : Sat, 24 Sep 2016 19:39:53 +0200
, a few seconds more & less, being the time I've taken to type the command.
/etc/timezone
contains "Europe/Paris" on both machines.
On both machines, the (CGI side) date.timezone of PHP is also "Europe/Paris".
On both machines, the SQL query SELECT @@global.time_zone, @@session.time_zone;
returns "SYSTEM" & "SYSTEM"
I use bootstrap datetime picker, based on moment.js, to enter this date & time. But I eliminated it from the suspects by examining the POSTed datas in my browser's console and confirmed the date hasn't been altered.
The application code is identical (same subversion revision) on both machines.
Do you see others things to test ?
Upvotes: 1
Views: 632
Reputation: 46
probably due to this PR only merged recently.
try changing this
- $dateTime = new \DateTime(sprintf('@%s', $timestamp), new \DateTimeZone($this->outputTimezone));
+ $dateTime = new \DateTime(sprintf('@%s', $timestamp));
+ // set timezone separately, as it would be ignored if set via the constructor,
+ // see http://php.net/manual/en/datetime.construct.php
+ $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
in
DateTimeToLocalizedStringTransformerTest.php
see this.
Upvotes: 1
Reputation: 11943
PHP doesn't use the system timezone. It has its own internal timezone setting date.timezone
configurable by PHP. It also has its own internal timezone database that it relies on, not your system's /etc/timezone
.
You can configure the timezone globally in your php.ini, or locally in code (i.e. using date_default_timezone_set()
, using one of PHP's timezone identifiers. Without specifying a timezone in the DateTime
constructor, for example, or without a GMT offset in the arguments passed to functions like strtotime
, PHP uses the default configured date.timezone
setting to pick the timezone. If none are configured, it falls back to UTC
.
From the PHP manual on date_default_timezone_set()
:
In order of preference, this function returns the default timezone by:
Reading the timezone set using the
date_default_timezone_set()
function (if any)Prior to PHP 5.4.0 only: Reading the
TZ
environment variable (if non empty)Reading the value of the
date.timezone
ini option (if set)Prior to PHP 5.4.0 only: Querying the host operating system (if supported and > allowed by the OS). This uses an algorithm that has to guess the timezone. This is by no means going to work correctly for every situation. A warning is shown when this stage is reached. Do not rely on it to be guessed correctly, and set date.timezone to the correct timezone instead.
If none of the above succeed,
date_default_timezone_get()
will return a default timezone of UTC.
So since you're not using PHP < 5.4.0, PHP will always just look at date.timezone
setting and fall back to UTC
if it's not set.
The best way to transport time between client and server in a timezone agnostic fashion is to just use Unix timestamps (i.e. UTC) during transport and only do the conversion on the remote-end. So for example, sending something like time() * 1000
to the browser, and having your Javascript translate that into a format date/time using Date
, would mean that the end-user sees the correct date/time according to their timezone information locally, but your server still gets the correct time regardless of the timezone.
So, as a general practice, it's a good idea to:
strtotime()
, DateTime::getTimestamp()
, etc...)Date.getTime()
)Doing this insures that the formating is and translation between timezones remains separate from storing the correct time, because it's easy to apply a timezone conversion to a formatted date and then accidentally forget or store/transport it in the wrong timezone. This is why always doing the transport in a timezone agnostic way prevents corrupting the data and only applies the conversion (if even necessary) at the terminating end of that transport. Then either PHP or Javascript can work with the Unix timestamps however they wish, and when they need to talk each other again, they can just convert back to UTC/Unix timestamp and send that instead.
Upvotes: 0