Php 不同时区的每小时日志;MySQL
我正在寻找通过我的api从不同的时区向我的用户提供简单的日志,我有点迷路,希望能得到一些帮助 我有一个叫做日志的下表:Php 不同时区的每小时日志;MySQL,php,mysql,timezone,Php,Mysql,Timezone,我正在寻找通过我的api从不同的时区向我的用户提供简单的日志,我有点迷路,希望能得到一些帮助 我有一个叫做日志的下表: CREATE TABLE `logs` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `userId` int(11) NOT NULL, `ip` VARCHAR(45) NOT NULL, `timestamp` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIM
CREATE TABLE `logs` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`userId` int(11) NOT NULL,
`ip` VARCHAR(45) NOT NULL,
`timestamp` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
我有一个小时表,可以在24小时内绑定我的查询
CREATE TABLE `log_hours` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`hourId` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO log_hours
(hourId)
VALUES
(1),
(2),
(3),
(4),
(5),
(6),
(7),
(8),
(9),
(10),
(11),
(12),
(13),
(14),
(15),
(16),
(17),
(18),
(19),
(20),
(21),
(22),
(23),
(24);
每次我得到一个api命中我存储日志采取以下数据
id | userId | ip | timestamp
1 1 0.0.0.0 2018-08-23 14:20:34
2 1 0.0.0.0 2018-08-23 14:20:34
3 1 0.0.0.0 2018-08-23 14:20:34
4 1 0.0.0.0 2018-08-23 14:20:34
5 1 0.0.0.0 2018-08-23 14:20:34
现在,如果我像下面这样运行我的查询
SELECT DW.hourId AS hour, ifnull(t.hits,0) hits from log_hours DW left join (
SELECT COUNT( * ) AS hits, HOUR( logs.timestamp ) AS `hour`
FROM logs WHERE DAY( logs.timestamp ) = DAY(CURDATE())
AND MONTH( logs.timestamp ) = MONTH(CURDATE())
AND `userId` = 1 GROUP BY HOUR( logs.timestamp )) t on DW.hourId = t.hour
ORDER BY hour ASC
这很好,给了我每小时的日志,就像这样
现在我被困在时区上,我的数据库时区设置为BST
比如说,我在美国有一个用户,如果他们在他们的时区中点击了api,mysql会自动将他们的时区转换为我的BST时区,这样输出数据才有意义吗
我应该使用datetime NOT NULL默认当前时间戳,还是应该使用INT并使用php time()函数插入记录
我应该首先通过php从我的时区返回数据,然后转换成他们的时区吗?在这种情况下,最佳做法是什么
编辑:
SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
date_default_timezone_set('America/Los_Angeles');
./mysql_tzinfo_to_sql /usr/share/zoneinfo | ./mysql -uroot -proot mysql
CONVERT_TZ(NOW(), @@session.time_zone, 'America/Los_Angeles')
2018-08-24 02:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Indian/Antananarivo')
2018-08-24 12:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Asia/Dhaka')
2018-08-24 15:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Antarctica/Troll')
2018-08-24 11:07:36
首先,如果我在这里问了一些愚蠢的问题,但我真的很想完全理解这个过程,我很抱歉
在什么时候检索用户的本地时区?我应该将其作为必需参数添加到API中吗
这是我的PHP代码,我只是将所有内容添加到一个函数中,这样更易于阅读我的过程是MVC
public function usage_get(){
$userId = $this->get('userId'); // i am obviously not getting the users info this way this is just for the example
// DO I MAKE THEM SEND THEIR TIMEZONE TO THE API AS A PARAM THEN USE IT IN MYSQL
//https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_convert-tz?
$timezone = $this->get('timezone');
// DO I SOMEHOW RETRIEVE THE TIME ZONE BASE ON IP AND GET IT THAT WAY?
$query = $this->db->query("SELECT DW.hourId AS hour, ifnull(t.hits,0) hits
from log_hours DW
left join (
SELECT COUNT( * ) AS hits, HOUR( logs.timestamp ) AS `hour`
FROM logs
WHERE DAY( logs.timestamp ) = DAY(CURDATE())
AND MONTH( logs.timestamp ) = MONTH(CURDATE())
AND `userId` = ".$this->db->escape_str($userId)."
GROUP BY HOUR( logs.timestamp )
) t on DW.hourId = t.hour ORDER BY hour ASC");
// DO I RUN A PHP FUNCTION AFTER THE MYSQL BASED ON TIMEZONE?
if($query->num_rows() > 0){
$this->response([
'status' => TRUE,
'message' => 'Success',
'data' => $query->result(),
], REST_Controller::HTTP_OK);
}else{
$this->response([
'status' => FALSE,
'message' => 'Error'
], REST_Controller::HTTP_OK);
}
}
如果你把所有的时间戳都记录在世界时,你的头痛就会少一些。追踪谁拥有哪一个夏令时,谁很快就会变老。保持简单始终是最好的主意。独立于本地时间保存所有日期。在我看来,其他一切都是坏习惯,因为当地时间只会导致以后的混乱和问题 比如说,我在美国有一个用户,如果他们在他们的时区中点击了api,mysql会自动将他们的时区转换为我的BST时区,这样输出数据才有意义吗 如果要将日志时间作为本地时间传递,请将其转换为本地时间。在数据库中,应始终存储UTC(+/-0)。在MySQL中,您可以在查询期间使用
CONVERT_TZ
函数()
我应该使用datetime NOT NULL默认当前时间戳,还是应该使用INT并使用php time()函数插入记录
CURRENT\u TIMESTAMP
似乎是正确的方法,因为它是独立的()。我看不出有什么好的理由使用PHPtime()
函数,因为CURRENT\u TIMESTAMP
是最精确的,如果服务器时间设置正确,那么总是正确的,但是基本上,除了PHP调用和实际数据库插入之间的毫秒之外,应该没有区别
我应该首先通过php从我的时区返回数据,然后转换成他们的时区吗?在这种情况下,最佳做法是什么
在我看来,使用数据库进行转换是最好的(最快的)-至少如果您可以编写自己的SQL查询。否则,通过PHP进行转换是完全合法的,但是会有一些最小的开销。如何做到这一点,以前有人问过:
在什么时候检索用户的本地时区?我应该将其作为必需参数添加到API中吗
这是一个应用程序架构的问题,没有“规则”。检索用户时区的可能性:
SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
date_default_timezone_set('America/Los_Angeles');
./mysql_tzinfo_to_sql /usr/share/zoneinfo | ./mysql -uroot -proot mysql
CONVERT_TZ(NOW(), @@session.time_zone, 'America/Los_Angeles')
2018-08-24 02:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Indian/Antananarivo')
2018-08-24 12:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Asia/Dhaka')
2018-08-24 15:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Antarctica/Troll')
2018-08-24 11:07:36
好的,首先感谢Blackam提供的信息,我也一直在阅读这篇文章
据我所知,UTC是24小时时钟起点的参考,然后可以将其偏移以转换为正确的时区。该时区以前是GMT或GMT,不确定,但它是起点
当最初的时间参考必须被定义时,人们同意将其相对于地球上的某一点。格林威治,伦敦的一个自治区,是本初子午线(0度经度)的所在地,被选为这一点
然后,偏移量由PHP或MySql中基于字符串参数计算偏移量的函数表示,例如,这些函数可以更改并存储在全局数据库中
MySQL:
SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
date_default_timezone_set('America/Los_Angeles');
./mysql_tzinfo_to_sql /usr/share/zoneinfo | ./mysql -uroot -proot mysql
CONVERT_TZ(NOW(), @@session.time_zone, 'America/Los_Angeles')
2018-08-24 02:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Indian/Antananarivo')
2018-08-24 12:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Asia/Dhaka')
2018-08-24 15:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Antarctica/Troll')
2018-08-24 11:07:36
PHP:
SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
date_default_timezone_set('America/Los_Angeles');
./mysql_tzinfo_to_sql /usr/share/zoneinfo | ./mysql -uroot -proot mysql
CONVERT_TZ(NOW(), @@session.time_zone, 'America/Los_Angeles')
2018-08-24 02:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Indian/Antananarivo')
2018-08-24 12:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Asia/Dhaka')
2018-08-24 15:07:36
CONVERT_TZ(NOW(), @@session.time_zone, 'Antarctica/Troll')
2018-08-24 11:07:36
在模糊地理解了这一点后,我现在可以看到我的设置的解决方案,因为我将有来自不同时区的多个用户注册我的服务。对我来说,在他们的帐户配置文件下有一个选项来设置他们正确的时区是有意义的
这使我能够获取他们的时区,然后更新mysql查询以返回他们时区中的正确数据。我同意Blackam,我更喜欢使用mysql
我的过程如下