How can I get the local server's time zone?
How can I get the local server's timezone without relying on php.ini
or other configuration files?
I am looking for an output similar to the output of date('e')
. eg. "UTC", "GMT", or "Atlantic/Azores".
I need to know this so that I may know开发者_运维技巧 the MySQL timezone.
If you're using a Linux/Unix based hosting platform, you could use the output of the date command with the "alphabetic time zone abbreviation" formatter as such:
$systemTimeZone = system('date +%Z');
However, it should be noted that you shouldn't necessarily rely on the system's timezone and that you should instead use date_default_timezone_set (or the date.timezone
php.ini setting) to set the required timezone.
If you're on *nix, call the system's date
using popen
:
popen("date +%Z");
On linux/unix i use
shell_exec("date +%Z");
These answers are not good. I don't know of a portable way to do it.
For Linux here is one option: https://bojanz.wordpress.com/2014/03/11/detecting-the-system-timezone-php/
The date solution others are listing might not be accurate as the problem is in Linux and the date utility (gnuutils, gnulib) will inherit the same problem.
If I set the timezone to Europe/Berlin and then ask date for the timezone it will give me CET.
The way to get the timezone in Linux is like this:
#include <time.h>
#include <stdio.h>
extern char *tzname[2];
extern long timezone;
extern int daylight;
void main() {
tzset();
printf(tzname[0]);
}
The problem is the zone files don't include their name, only the list of parent timezones or something like that.
CET is not the same as the Europe/Berlin zone. If I put CET in then dates can be calculated incorrectly. Sometimes this wont matter as some countries have been using one timezone for decades but occasionally it can matter.
Using zdump here is a diff between CET and Europe/Berlin:
> Fri Mar 31 23:06:31 1893 UTC = Fri Mar 31 23:59:59 1893 LMT isdst=0 gmtoff=3208
> Fri Mar 31 23:06:32 1893 UTC = Sat Apr 1 00:06:32 1893 CET isdst=0 gmtoff=3600
< Sun Sep 16 00:59:59 1945 UTC = Sun Sep 16 02:59:59 1945 CEST isdst=1 gmtoff=7200
< Sun Sep 16 01:00:00 1945 UTC = Sun Sep 16 02:00:00 1945 CET isdst=0 gmtoff=3600
< Sun Apr 3 00:59:59 1977 UTC = Sun Apr 3 01:59:59 1977 CET isdst=0 gmtoff=3600
... SNIP about a dozen ...
< Sun Sep 30 01:00:00 1979 UTC = Sun Sep 30 02:00:00 1979 CET isdst=0 gmtoff=3600
> Wed May 23 23:59:59 1945 UTC = Thu May 24 01:59:59 1945 CEST isdst=1 gmtoff=7200
... SNIP couple dozen...
> Sun Oct 2 01:00:00 1949 UTC = Sun Oct 2 02:00:00 1949 CET isdst=0 gmtoff=3600
Some of these might not even matter if you're using a unixtime but you can clearly see here that in the 70s some would. There are likely a few other timezones with much more recent changes that would break is using the result from tzset. For many this would be a fringe issue but if it does effect you the result likely wont be pleasant.
I do not know what the convention is for windows or if there is the same problem. There is an exception to this problem. If your system timezone is a root one (like GMT, UTC, CET, etc) then I don't think this problem should occur.
However your question is ultimately about MySQL:
SELECT IF(@@global.time_zone = 'SYSTEM', @@global.system_time_zone, @@global.time_zone) AS time_zone;
If it is set to SYSTEM it will also suffer the same fate as PHP and tzset. I checked a friend's server and there's often an hour's difference because MySQL converts Europe/London to GMT. GMT does not include BST which is a cause of many problems. Internally MySQL might be fine because it's still using /etc/localtime which will point to the right file even if MySQL is reporting the wrong name but if you take that wrong name and use it to load the timezone with something else then the two may not have the same timezone.
Even if you tried to include DST it would not be a perfect fix. If you MySQL instance is using SYSTEM you may instead want to see if you can convert the dates from that to UTC (or the PHP date/time) which might be painful for performance. In theory you could try to brute force detection but I wouldn't advise it. You could also try setting the timezone in the session variable and MySQL may convert automatically but take care to be sure and always RTM (if that doesn't work use the source).
You don't actually need to know what "timezone" MySQL is running on - you merely need to know the difference to UTC.
To get that you can simply ask MySQL:
SELECT TIMESTAMPDIFF(HOUR, UTC_TIMESTAMP, NOW())
Since the value of NOW()
is based on the timezone MySQL is running on, that will read the difference between NOW()
and the UTC time, in hours. You can then use that value to create a full timestamp like 2016-04-15T15:52:01+01:00
which can be used in DateTime::__construct()
.
You can then let PHP worry about the difference the timezones between the application and database servers by comparing DateTime
objects... and that should work on all systems.
you can get timezone of your server by this. echo date_default_timezone_get();
精彩评论