【问题标题】:How can I get the local server's time zone?如何获取本地服务器的时区?
【发布时间】:2011-06-09 16:00:03
【问题描述】:

如何在不依赖php.ini 或其他配置文件的情况下获取本地服务器的时区?

我正在寻找类似于date('e') 的输出的输出。例如。 “UTC”、“GMT”或“大西洋/亚速尔群岛”。

我需要知道这一点,这样我才能知道 MySQL 时区。

【问题讨论】:

  • 你想在什么操作系统上做这个?

标签: php date timezone


【解决方案1】:

如果您使用的是基于 Linux/Unix 的托管平台,则可以将 date 命令的输出与“字母时区缩写”格式化程序一起使用:

$systemTimeZone = system('date +%Z');

但是,应该注意的是,您不一定要依赖系统的时区,而应该使用date_default_timezone_set(或date.timezone php.ini 设置)来设置所需的时区。

【讨论】:

  • @dvdx 你需要一个像“America/New York”这样的字符串来做什么?
  • 因为 America/New York 将输出此处支持的时区格式列表中的 MANY 之一:php.net/manual/en/timezones.php
【解决方案2】:

如果您使用 *nix,请使用 popen 调用系统的 date:

popen("date +%Z");

【讨论】:

    【解决方案3】:

    在我使用的 linux/unix 上

    shell_exec("date +%Z");
    

    【讨论】:

      【解决方案4】:

      这些答案不好。我不知道有一种便携的方法。

      对于 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(如果这不起作用,请使用源代码)。

      【讨论】:

        【解决方案5】:

        您实际上不需要知道 "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 担心应用程序和数据库服务器之间的时区差异......并且应该适用于所有系统。

        【讨论】:

        • 这并没有给出实际的时区,只给出时区的效果。某些时区重叠,尤其是与 DST 或更改时重叠。
        • @jgmjgm - 公平点,我只是不相信 OP 真的 需要类似字符串 GMT 如果你明白我的意思......你不'任何类型的计算都不需要它,它只会给你一个更清晰的字符串。我想我试图提供一种替代解决方案来解决我怀疑潜在问题的问题,而不是“按原样”实际回答问题……这是不久前的事了;)
        【解决方案6】:

        您可以通过此获取服务器的时区。 echo date_default_timezone_get();

        【讨论】:

          猜你喜欢
          • 2013-11-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-08
          • 2020-03-21
          • 1970-01-01
          • 2016-02-06
          • 2011-03-15
          相关资源
          最近更新 更多