如何使用MariaDB返回本地时间SQL结果
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用MariaDB返回本地时间SQL结果相关的知识,希望对你有一定的参考价值。
这个问题已被多次询问(和回答)mysql,我确信这些答案也适用于MariaDB,但要么他们没有,要么更可能我只是做错了。运行这些脚本几分钟后,date
返回Sat Feb 24 18:20:38 UTC 2018
。我已经得出结论,在大多数情况下,MySQL / MariaDB应该保持为UTC配置,我不会做不同的事情。我确实按预期工作,并将结果发布在下面。
<?php
//php.ini has set date.timezone =America/Los_Angeles
function displayTime($desc,$db) {
echo("<h5>$desc</h5>");
$stmt=$db->query('SELECT @@global.time_zone');
echo 'MariaDb global.time_zone: '.$stmt->fetchColumn()."<br>";
$stmt=$db->query('SELECT @@session.time_zone');
echo 'MariaDb session.time_zone: '.$stmt->fetchColumn()."<br>";
$stmt=$db->query('SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);');
echo 'MariaDb offset: '.$stmt->fetchColumn()."<br>";
$stmt=$db->query('SELECT tsValueUpdated FROM points WHERE id=6');
echo 'Adjusted time: '.$stmt->fetchColumn()."<br>";
}
function getTimezoneFromDb() {
$tzs = DateTimeZone::listIdentifiers();
return $tzs[rand(0, count($tzs)-1)];
}
function getOffset() {
$os=(new DateTime())->getOffset();
if($os>(13*60*60)) $os=-24*60*60; //MySQL/MariaDB bug for Pacific/Kiritimati, Pacific/Chatham, and Pacific/Apia
return $os >= 0?'+'.gmdate("G:i", $os):'-'.gmdate("G:i", -$os);
}
function test($sql, $value, $db) {
$desc="Test for $sql using $value";
$stmt=$db->prepare($sql);
try{
$stmt->execute([$value]);
displayTime($desc,$db);
}
catch(PDOException $e) {
echo("<h5>$desc</h5>".$e->getMessage().'<br>');
}
}
//tsValueUpdated is type datetime and data was inserted using NOW()
$db=parse_ini_file(__DIR__.'/../config.ini',true)['mysql'];
$db=new PDO("mysql:host={$db['host']};dbname={$db['dbname']};charset={$db['charset']}",$db['username'],$db['password'],array(PDO::ATTR_EMULATE_PREPARES=>false,PDO::MYSQL_ATTR_USE_BUFFERED_QUERY=>true,PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_OBJ));
displayTime('Before changing timezone',$db);
$tz=getTimezoneFromDb();
echo "Timezone: $tz<br>";
date_default_timezone_set($tz);
displayTime('After changing PHP timezone',$db);
$os=getOffset();
echo "Offset: $os<br>";
//Reference https://stackoverflow.com/a/19069310/1032531
test('SET GLOBAL time_zone = ?', $os, $db);
test('SET GLOBAL time_zone = ?', $tz, $db);
test('SET @@global.time_zone = ?', $os, $db);
test('SET time_zone = ?', $os, $db);
test('SET time_zone = ?', $tz, $db);
test('SET @@session.time_zone = ?', $os, $db);
产量
Before changing timezone
MariaDb global.time_zone: +06:00
MariaDb session.time_zone: +06:00
MariaDb offset: 06:00:00
Adjusted time: 2018-02-24 18:15:46
Timezone: Africa/Tripoli
After changing PHP timezone
MariaDb global.time_zone: +06:00
MariaDb session.time_zone: +06:00
MariaDb offset: 06:00:00
Adjusted time: 2018-02-24 18:15:46
Offset: +2:00
Test for SET GLOBAL time_zone = ? using +2:00
MariaDb global.time_zone: +02:00
MariaDb session.time_zone: +06:00
MariaDb offset: 06:00:00
Adjusted time: 2018-02-24 18:15:46
Test for SET GLOBAL time_zone = ? using Africa/Tripoli
SQLSTATE[HY000]: General error: 1298 Unknown or incorrect time zone: 'Africa/Tripoli'
Test for SET @@global.time_zone = ? using +2:00
MariaDb global.time_zone: +02:00
MariaDb session.time_zone: +06:00
MariaDb offset: 06:00:00
Adjusted time: 2018-02-24 18:15:46
Test for SET time_zone = ? using +2:00
MariaDb global.time_zone: +02:00
MariaDb session.time_zone: +02:00
MariaDb offset: 02:00:00
Adjusted time: 2018-02-24 18:15:46
Test for SET time_zone = ? using Africa/Tripoli
SQLSTATE[HY000]: General error: 1298 Unknown or incorrect time zone: 'Africa/Tripoli'
Test for SET @@session.time_zone = ? using +2:00
MariaDb global.time_zone: +02:00
MariaDb session.time_zone: +02:00
MariaDb offset: 02:00:00
Adjusted time: 2018-02-24 18:15:46
命令行测试
MariaDB [datalogger]> explain points;
+----------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| idPublic | int(11) | NO | MUL | 0 | |
| accountsId | int(11) | NO | MUL | NULL | |
| name | varchar(45) | NO | MUL | NULL | |
| value | float | YES | | NULL | |
| valueOld | float | YES | | NULL | |
| units | varchar(45) | YES | | NULL | |
| type | char(8) | NO | MUL | NULL | |
| slope | float | NO | | 1 | |
| intercept | float | NO | | 0 | |
| tsValueUpdated | datetime | YES | | NULL | |
+----------------+-------------+------+-----+---------+----------------+
11 rows in set (0.00 sec)
MariaDB [datalogger]> SELECT tsValueUpdated FROM points WHERE id=6;
+---------------------+
| tsValueUpdated |
+---------------------+
| 2018-02-24 18:09:46 |
+---------------------+
1 row in set (0.00 sec)
MariaDB [datalogger]> SET time_zone ='+12:00';
Query OK, 0 rows affected (0.00 sec)
MariaDB [datalogger]> SELECT tsValueUpdated FROM points WHERE id=6;
+---------------------+
| tsValueUpdated |
+---------------------+
| 2018-02-24 18:09:46 |
+---------------------+
1 row in set (0.00 sec)
MariaDB [datalogger]> SET GLOBAL time_zone ='+12:00';
Query OK, 0 rows affected (0.00 sec)
MariaDB [datalogger]> SELECT tsValueUpdated FROM points WHERE id=6;
+---------------------+
| tsValueUpdated |
+---------------------+
| 2018-02-24 18:09:46 |
+---------------------+
1 row in set (0.00 sec)
MariaDB [datalogger]>
mysqld --help --verbose | grep时区
2018-02-24 18:07:19 140183024801920 [Warning] Changed limits: max_open_files: 1024 max_connections: 151 table_cache: 431
2018-02-24 18:07:19 140183024801920 [Note] Plugin 'FEEDBACK' is disabled.
2018-02-24 18:07:19 140183024801920 [Warning] Could not open mysql.plugin table. Some options may be missing from the help text
--default-time-zone=name
default-time-zone (No default value)
system-time-zone
编辑。新研究
<?php
date_default_timezone_set('America/Los_Angeles');
$config=parse_ini_file(__DIR__.'/../config.ini',true);
$db = $config['mysql'];
$db=new PDO("mysql:host={$db['host']};dbname={$db['dbname']};charset={$db['charset']}",$db['username'],$db['password'],array(PDO::ATTR_EMULATE_PREPARES=>false,PDO::MYSQL_ATTR_USE_BUFFERED_QUERY=>true,PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_OBJ));
$os=(new DateTime())->getOffset();
if($os>(13*60*60)) $os=-24*60*60; //MySQL/MariaDB bug for Pacific/Kiritimati, Pacific/Chatham, and Pacific/Apia
$os = $os >= 0?'+'.gmdate("G:i", $os):'-'.gmdate("G:i", -$os);
$stmtSelect = $db->prepare("SELECT id, NOW() now, mydatetime FROM test WHERE id = ?");
$stmtInsert = $db->prepare("INSERT INTO test(id, mydatetime) VALUES(?,NOW())");
$stmtSelectConvert1 = $db->prepare("SELECT id, NOW() now, CONVERT_TZ(mydatetime, '+00:00', '$os') mydatetime FROM test WHERE id = ?");
$stmtInsert->execute([1]);
$stmtSelect->execute([1]);
echo("
INSERTED BEFORE SETTING SQL TIMEZONE. NO CONVERT
");
print_r($stmtSelect->fetch());
$stmtSelectConvert1->execute([1]);
echo("
INSERTED BEFORE SETTING SQL TIMEZONE. YES CONVERT1
");
print_r($stmtSelectConvert1->fetch());
echo("
SET SQL TIMEZONE
");
$db->exec("SET time_zone='$os';");
$stmtInsert->execute([2]);
$stmtSelectConvert2 = $db->prepare("SELECT id, NOW() now, CONVERT_TZ(mydatetime, '+00:00', '$os') mydatetime FROM test WHERE id = ?");
$stmtSelect->execute([1]);
echo("
INSERTED BEFORE SETTING SQL TIMEZONE. NO CONVERT
");
print_r($stmtSelect->fetch());
$stmtSelectConvert1->execute([1]);
echo("
INSERTED BEFORE SETTING SQL TIMEZONE. YES CONVERT1
");
print_r($stmtSelectConvert1->fetch());
$stmtSelectConvert2->execute([1]);
echo("
INSERTED BEFORE SETTING SQL TIMEZONE. YES CONVERT2
");
print_r($stmtSelectConvert2->fetch());
$stmtSelect->execute([2]);
echo("
INSERTED AFTER SETTING SQL TIMEZONE. NO CONVERT
");
print_r($stmtSelect->fetch());
$stmtSelectConvert1->execute([2]);
echo("
INSERTED AFTER SETTING SQL TIMEZONE. YES CONVERT1
");
print_r($stmtSelectConvert1->fetch());
$stmtSelectConvert2->execute([2]);
echo("
INSERTED AFTER SETTING SQL TIMEZONE. YES CONVERT2
");
print_r($stmtSelectConvert2->fetch());
OUTPUT
INSERTED BEFORE SETTING SQL TIMEZONE. NO CONVERT
stdClass Object
(
[id] => 1
[now] => 2018-02-27 20:16:22
[mydatetime] => 2018-02-27 20:16:22
)
INSERTED BEFORE SETTING SQL TIMEZONE. YES CONVERT1
stdClass Object
(
[id] => 1
[now] => 2018-02-27 20:16:22
[mydatetime] => 2018-02-27 12:16:22
)
SET SQL TIMEZONE
INSERTED BEFORE SETTING SQL TIMEZONE. NO CONVERT
stdClass Object
(
[id] => 1
[now] => 2018-02-27 12:16:22
[mydatetime] => 2018-02-27 20:16:22
)
INSERTED BEFORE SETTING SQL TIMEZONE. YES CONVERT1
stdClass Object
(
[id] => 1
[now] => 2018-02-27 12:16:22
[mydatetime] => 2018-02-27 12:16:22
)
INSERTED BEFORE SETTING SQL TIMEZONE. YES CONVERT2
stdClass Object
(
[id] => 1
[now] => 2018-02-27 12:16:22
[mydatetime] => 2018-02-27 12:16:22
)
INSERTED AFTER SETTING SQL TIMEZONE. NO CONVERT
stdClass Object
(
[id] => 2
[now] => 2018-02-27 12:16:22
[mydatetime] => 2018-02-27 12:16:22
)
INSERTED AFTER SETTING SQL TIMEZONE. YES CONVERT1
stdClass Object
(
[id] => 2
[now] => 2018-02-27 12:16:22
[mydatetime] => 2018-02-27 04:16:22
)
INSERTED AFTER SETTING SQL TIMEZONE. YES CONVERT2
stdClass Object
(
[id] => 2
[now] => 2018-02-27 12:16:22
[mydatetime] => 2018-02-27 04:16:22
)
NotionCommotion
Quote
MultiQuote
Edit
......或者更有可能我只是做错了什么。
答对了! :-)
看这里......(重点补充):
MariaDB [datalogger]> explain points; +----------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | idPublic | int(11) | NO | MUL | 0 | | | accountsId | int(11) | NO | MUL | NULL | | | name | varchar(45) | NO | MUL | NULL | | | value | float | YES | | NULL | | | valueOld | float | YES | | NULL | | | units | varchar(45) | YES | | NULL | | | type | char(8) | NO | MUL | NULL | | | slope | float | NO | | 1 | | | intercept | float | NO | | 0 | | | tsValueUpdated | datetime | YES | | NULL | | +----------------+-------------+------+-----+---------+----------------+ 11 rows in set (0.00 sec)
MariaDB有两种不同的数据类型,能够存储日期+时间:DATETIME
(你正在使用)和TIMESTAMP
(你不是)。
关键的区别在于TIMESTAMP
从/向会话time_zone
转换并以UTC格式存储,而DATETIME
只是按照提供的方式存储和检索(不考虑时区)。
这在Time zone effects下记录:
某些功能受时区设置的影响。这些包括
以及从
TIMESTAMP
列存储和检索的值。后者在存储时转换为UTC(Coordinated Universal Time),并在检索时转换回来。某些功能不受影响。这些包括:
因此,无论您使用多少时区设置,如果您的值存储在DATETIME
列中,那么它们将始终按照输入的方式进行检索。如果您希望MariaDB在插入/检索时处理会话时区之间的转换,则必须使用TIMESTAMP
列。
以上是关于如何使用MariaDB返回本地时间SQL结果的主要内容,如果未能解决你的问题,请参考以下文章
SQL Concat int 到 mariadb 中的字符串