【发布时间】:2011-06-09 16:00:03
【问题描述】:
如何在不依赖php.ini 或其他配置文件的情况下获取本地服务器的时区?
我正在寻找类似于date('e') 的输出的输出。例如。 “UTC”、“GMT”或“大西洋/亚速尔群岛”。
我需要知道这一点,这样我才能知道 MySQL 时区。
【问题讨论】:
-
你想在什么操作系统上做这个?
如何在不依赖php.ini 或其他配置文件的情况下获取本地服务器的时区?
我正在寻找类似于date('e') 的输出的输出。例如。 “UTC”、“GMT”或“大西洋/亚速尔群岛”。
我需要知道这一点,这样我才能知道 MySQL 时区。
【问题讨论】:
如果您使用的是基于 Linux/Unix 的托管平台,则可以将 date 命令的输出与“字母时区缩写”格式化程序一起使用:
$systemTimeZone = system('date +%Z');
但是,应该注意的是,您不一定要依赖系统的时区,而应该使用date_default_timezone_set(或date.timezone php.ini 设置)来设置所需的时区。
【讨论】:
如果您使用 *nix,请使用 popen 调用系统的 date:
popen("date +%Z");
【讨论】:
在我使用的 linux/unix 上
shell_exec("date +%Z");
【讨论】:
这些答案不好。我不知道有一种便携的方法。
对于 Linux,这是一种选择:https://bojanz.wordpress.com/2014/03/11/detecting-the-system-timezone-php/
其他人列出的日期解决方案可能不准确,因为问题出在 Linux 中,日期实用程序(gnuutils、gnulib)将继承相同的问题。
如果我将时区设置为欧洲/柏林,然后询问时区的日期,它将给我 CET。
Linux中获取时区的方法是这样的:
#include <time.h>
#include <stdio.h>
extern char *tzname[2];
extern long timezone;
extern int daylight;
void main() {
tzset();
printf(tzname[0]);
}
问题是区域文件不包括他们的名字,只有父时区列表或类似的东西。
CET 与欧洲/柏林区不同。如果我把 CET 放进去,那么日期可能会计算不正确。有时这并不重要,因为某些国家/地区几十年来一直使用一个时区,但有时它可能很重要。
这里使用 zdump 是 CET 和 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
如果您使用的是 unixtime,其中一些甚至可能无关紧要,但您可以在这里清楚地看到在 70 年代有些会。使用 tzset 的结果,可能还有一些其他时区会发生更近期的更改,这些更改可能会中断。对于许多人来说,这只是一个边缘问题,但如果它确实影响到您,结果可能不会令人愉快。
我不知道 windows 的约定是什么,或者是否存在同样的问题。这个问题有一个例外。如果您的系统时区是根时区(如 GMT、UTC、CET 等),那么我认为不会出现此问题。
但是你的问题最终是关于 MySQL 的:
SELECT IF(@@global.time_zone = 'SYSTEM', @@global.system_time_zone, @@global.time_zone) AS time_zone;
如果设置为 SYSTEM,它也会遭受与 PHP 和 tzset 相同的命运。我检查了一个朋友的服务器,通常会有一个小时的差异,因为 MySQL 将欧洲/伦敦转换为 GMT。 GMT 不包括导致许多问题的 BST。在内部 MySQL 可能没问题,因为它仍在使用 /etc/localtime ,即使 MySQL 报告了错误的名称,它也会指向正确的文件,但是如果你使用错误的名称并使用它来加载时区和其他东西,那么两者可能不会有相同的时区。
即使您尝试包含 DST,它也不是一个完美的解决方案。如果您的 MySQL 实例使用的是 SYSTEM,您可能想查看是否可以将日期从该日期转换为 UTC(或 PHP 日期/时间),这可能会影响性能。从理论上讲,您可以尝试蛮力检测,但我不建议这样做。您也可以尝试在会话变量中设置时区,MySQL 可能会自动转换,但请务必确保始终使用 RTM(如果这不起作用,请使用源代码)。
【讨论】:
您实际上不需要知道 "timezone" MySQL 运行在哪个位置 - 您只需要知道与 UTC 的区别。
您可以简单地询问 MySQL:
SELECT TIMESTAMPDIFF(HOUR, UTC_TIMESTAMP, NOW())
由于NOW() 的值基于 MySQL 运行所在的时区,因此它将读取NOW() 与 UTC 时间之间的差异,以小时为单位。然后,您可以使用该值创建一个完整的时间戳,例如 2016-04-15T15:52:01+01:00,可以在 DateTime::__construct() 中使用。
然后,您可以通过比较 DateTime 对象让 PHP 担心应用程序和数据库服务器之间的时区差异......并且应该适用于所有系统。
【讨论】:
GMT 如果你明白我的意思......你不'任何类型的计算都不需要它,它只会给你一个更清晰的字符串。我想我试图提供一种替代解决方案来解决我怀疑潜在问题的问题,而不是“按原样”实际回答问题……这是不久前的事了;)
您可以通过此获取服务器的时区。 echo date_default_timezone_get();
【讨论】: