简体   繁体   English

如何处理PHP + MySQL时区和MySQL GROUP BY [date]查询?

[英]How to deal with PHP + MySQL timezones and MySQL GROUP BY [date] queries?

I'm working with Drupal 7, PHP, and MySQL, and trying to get my head around timezone issues when querying from the MySQL database. 我正在使用Drupal 7,PHP和MySQL,并试图从MySQL数据库中查询时区问题。

Drupal handles dates pretty well out of the gate: all dates are stored as UTC timestamp int's in the db, and timezone conversion happens on a per-user basis via a timezone setting in each user profile, using PHP 5's built-in timezone capabilities (so each time a PHP script is run the script's timezone is set to the current user's timezone). Drupal可以很好地处理日期:所有日期都存储为db中的UTC时间戳int,并且使用PHP 5的内置时区功能通过每个用户配置文件中的时区设置按用户对时区进行转换(因此,每次运行PHP脚本时,脚本的时区都会设置为当前用户的时区。

So this is all fine and dandy and fairly painless as long as we stick to PHP. 因此,只要我们坚持使用PHP,这一切都很好,很花哨,也很轻松。

Things start to get tricky when we bring in MySQL, since there doesn't appear to be a way to perfectly synchronize the current PHP script timezone with a given MySQL query . 当我们引入MySQL时,事情开始变得棘手, 因为似乎没有一种方法可以完美地将当前PHP脚本时区与给定的MySQL查询同步 It seems like best practice dictates handling ALL timezone conversion in PHP: only ever querying the database for the raw timestamps, and then converting in PHP as necessary. 最佳实践似乎要求在PHP中处理所有时区转换:仅在数据库中查询原始时间戳,然后根据需要在PHP中进行转换。

This seems reasonable in most cases (even if a bit slower at times), but what am I supposed to do with MySQL GROUP BY [date] queries ? 在大多数情况下,这似乎是合理的(即使有时速度稍慢), 但是我应该对MySQL GROUP BY [date]查询做什么呢? For instance, I'm building a module to handle analytics, and frequently want to do things like: 例如,我正在构建一个模块来处理分析,并且经常想做如下事情:

GROUP BY YEAR(FROM_UNIXTIME(u.created)), MONTH(FROM_UNIXTIME(u.created))

So we run into the timezone issue... 所以我们遇到了时区问题...

Possible solutions that have come to mind: 想到的可能解决方案:

  1. Hard-code a timezone: Use date_default_timezone_set() within my module to insure that the PHP timezone is always set to the system timezone (so MySQL timezone = PHP timezone). 硬编码时区:在我的模块中使用date_default_timezone_set()以确保PHP时区始终设置为系统时区(因此MySQL时区= PHP时区)。 In other words, the analytics timezone will be hard-coded, rather than respecting the timezone of the user viewing the analytics. 换句话说,分析时区将是硬编码的,而不是尊重查看分析的用户的时区。 This really isn't ideal, since we want users in multiple timezones to be able to access the analytics using their timezones. 这确实不是理想的,因为我们希望多个时区的用户能够使用其时区访问分析。 Also, date_default_timezone_set() seems to mess Drupal up, as it sets the timezone for the entire script, instead of just within a particular function... 另外,date_default_timezone_set()似乎使Drupal搞砸了,因为它设置了整个脚本的时区,而不是仅仅在特定函数中。

  2. Forget about using GROUP BY in the queries: just fetch all the raw data from the db (be there tens or hundreds of thousands of rows), then group the results by date in php using for loops... this solution seems like it would be significantly more resource intensive, slower, and somewhat ridiculous. 忘了在查询中使用GROUP BY:只需从db中获取所有原始数据(存在数万或数十万行),然后使用for循环按日期将结果按php分组...该解决方案似乎会显着提高资源密集度,降低速度并有些荒谬。

So I guess what I'm asking is, have I missed something? 所以我想我要问的是,我错过了什么吗? Is there a best practice here that I'm not aware of? 这里有我不知道的最佳实践吗?

Thanks a ton for any help! 非常感谢您的帮助!

I would consider an approach such as this 我会考虑这样的方法

SET time_zone = '+02:00';

http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html

And have 并有

GROUP BY FROM_UNIXTIME(u.created, '%Y-%m');

Since FROM_UNIXTIME bases it's time on time_zone , this should give desired result. 由于FROM_UNIXTIME是基于time_zone的时间,因此应该可以得到理想的结果。

To undo the time_zone change afterwards, consider saving SELECT TIMEDIFF(NOW(), CONVERT_TZ(now(), @@session.time_zone, '+00:00')); 要在以后撤消time_zone更改,请考虑保存SELECT TIMEDIFF(NOW(), CONVERT_TZ(now(), @@session.time_zone, '+00:00')); first and then set it to saved value afterwards. 首先,然后将其设置为保存的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM