2016-09-24 124 views
1

我有一个Ubuntu/Apache2/PHP(Symfony2)/ MySQL日期问题。我认为这是一个系统问题,因为我没有它在开发环境中,只有在rec和prod中。当我发布一个包含日期时间的表单时,数据库中的内容少于我输入的时间2小时。当我阅读它时,屏幕上的日期时间与我在数据库中的相同。 2小时的差异符合我的时区(欧洲/巴黎)。TimeZone调试需要帮助

开发环境:

  • 本地机器
  • 的Ubuntu 16.04 LTS桌面
  • 阿帕奇/ 2.4.18(Ubuntu的)
  • Mysql的5.5.43-0 +上的虚拟主机的Debian 8 deb8u1 LAN
  • PHP 7.0.8-0ubuntu0.16.04.2,Symfony的2.8.7

REC /生产环境:

  • 两个相同的专用服务器上
  • 的Ubuntu 15.10服务器
  • 的Apache/2.4.12
  • MySQL的5.6.28-0ubuntu0.15.10.1
  • PHP 5.6.11 -1ubuntu3.1

当我运行在两台机器上date -R,我有一个匹配:Sat, 24 Sep 2016 19:39:53 +0200,几秒钟&更少,因为我已经采取了键入命令的时间。

/etc/timezone在两台机器上都包含“Europe/Paris”。

在这两台机器上,PHP的(CGI方)date.timezone也是“欧洲/巴黎”。

在两台机器上,SQL查询SELECT @@global.time_zone, @@session.time_zone;返回 “SYSTEM” & “SYSTEM”

我用引导日期时间选择器,基于moment.js,进入这个日期&时间。但我通过检查浏览器控制台中的POST数据并将其从犯罪嫌疑人身上清除,并确认日期未被更改。

这两个机器上的应用程序代码是相同的(相同的颠覆版本)。

您是否看到别人要测试的东西?

回答

1

可能是由于this PR最近才合并。

尝试改变这种

-   $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)); 

DateTimeToLocalizedStringTransformerTest.php 

看到this

+0

看起来像你发现它!我支持项目工作区,更新了我的一个开发人员的symfony/symfony,并重现了错误。然后我像你提议的那样打补丁,并且bug消失了。但我肯定无法在自动交付过程中为这样的供应商打补丁,我已经读到它只会在下个月初修复。所以我仍然在寻找一个干净的解决方案。 – Moonchild

+0

作为临时修复,可能会覆盖您的src中的班级! – frian

+0

我使用作曲者的symfony/symfony 2.8.7修正了symfony/symfony的版本号。必要时我会手动测试并升级Symfony。对我来说这样更安全。 – Moonchild

0

PHP不使用系统时区。它有自己的内部时区设置date.timezone可由PHP配置。它也有它自己的internal timezone database它依赖,而不是你的系统的/etc/timezone

你可以在你的php.ini全局配置时区,或在本地代码(即使用date_default_timezone_set(),使用PHP的timezone identifiers之一。如果没有在DateTime构造函数指定一个时区,例如,或者没有在格林尼治标准时间偏移参数传递给strtotime等函数,PHP使用默认配置的date.timezone设置来选择时区,如果没有配置,则返回UTC

从PHP手册上date_default_timezone_set()

按优先顺序排列,此函数返回由默认时区:

  • 读取使用date_default_timezone_set()函数(如果有的话)

    的时区设定
  • 仅在PHP 5.4.0之前:读取TZ环境变量(如果不为空)

  • date.timezone INI选项的值(如果设置)

  • 之前PHP 5.4.0只:查询所述主机操作系统(如果支持和>操作系统允许)。这使用必须猜测时区的算法。这绝不会在任何情况下都能正确工作。当达到此阶段时会显示警告。不要依赖它来正确猜测,而是将date.timezone设置为正确的时区。

如果以上都不是成功的,date_default_timezone_get()将返回UTC的一个默认的时区。

因此,既然你不使用PHP < 5.4.0,PHP将永远只是看date.timezone设置,回落到UTC,如果它没有设置。

运输客户端和服务器之间的时间在一个时区无关的方式,最好的方法是只使用传输期间的Unix时间戳(即UTC)和仅做在远程端的转换。例如,向浏览器发送类似time() * 1000的东西,并将您的Javascript翻译成使用Date格式的日期/时间,这意味着最终用户根据他们的本地时区信息查看正确的日期/时间,但是您的服务器无论时区如何,仍然可以获得正确的时间。

所以,作为一般的做法,这是一个好主意:

  • 商店都在数据库中作为UTC
  • 在UTC从只有
  • 交通运输PHP和数据库之间
  • 运输时间戳服务器在UTC客户端(strtotime()DateTime::getTimestamp(),等...),从客户端
  • 传输到服务器UTC(Date.getTime()

这样做确保了格式化和时区之间的转换与存储正确的时间保持分开,因为很容易将时区转换应用于格式化日期,然后意外忘记或将其存储/传输到错误的时区。这就是为什么总是以时区不可知的方式进行传输可以防止数据被破坏,并且仅在该传输的终止处应用转换(如果有必要的话)。然后PHP或Javascript可以使用Unix时间戳,但是他们希望,并且当他们需要再次相互交谈时,他们可以转换回UTC/Unix时间戳并发送。

+0

优秀回答谢里夫 – Drew

+0

谢谢您的长时间回答谢里夫。但正如我在我的文章中所说的,这不是一个PHP端时区问题。 – Moonchild