Contexto: versão do MySQL
No MySQL 5.7.17 (como mostrado por SHOW VARIABLES LIKE "%version%";
)
Contexto: configurações de fuso horário do MySQL
e com SELECT @@global.time_zone, @@session.time_zone;
rendimento
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| SYSTEM | SYSTEM |
+--------------------+---------------------+
...o que significa que o servidor rastreia o fuso horário do sistema.
Contexto: fuso horário do sistema
Sendo um Linux, verificamos o fuso horário do sistema assim (saída editada):
$ timedatectl
Local time: Wed 2018-02-14 13:21:30 GMT
Universal time: Wed 2018-02-14 13:21:30 UTC
RTC time: Wed 2018-02-14 13:21:30
Time zone: Europe/London (GMT, +0000)
Contexto: O que sabemos
- Os valores de hora e data não são armazenados com informações de fuso horário no MySQL (não há uma descrição clara disso em The DATE, DATETIME e TIMESTAMP Types , exceto "MySQL converte valores TIMESTAMP do fuso horário atual para UTC para armazenamento e volta de UTC para o fuso horário atual para recuperação. (Isso não ocorre para outros tipos, como DATETIME.)" ; observe que "converte valores TIMESTAMP para UTC para armazenamento" na verdade só faz sentido como uma nota do implementador, não é útil para o usuário - o importante é que TiMEZONE sempre retorna o valor correto em qualquer fuso horário em que se esteja, enquanto DATETIME sempre retornará o mesmo valor em qualquer fuso horário em que se esteja)
Contexto: hora atual
Agora está por aí:
$ date +"The current time is %s alias %c"
The current time is 1518617572 alias Wed 14 Feb 2018 14:12:52 GMT
Problema
Vamos correr:
SELECT NOW(),FROM_UNIXTIME(0),UNIX_TIMESTAMP(),FROM_UNIXTIME(UNIX_TIMESTAMP());
A saída (devidamente girada manualmente; deve haver uma opção para fazer isso):
NOW() 2018-02-14 14:15:13 -- Display "now" in SYSTEM timetone: OK
FROM_UNIXTIME(0) 1970-01-01 01:00:00 -- Display 1970-01-01 00:00:00 in SYSTEM timetone: NOT OK
UNIX_TIMESTAMP() 1518617713 -- Correct unixtime
FROM_UNIXTIME(UNIX_TIMESTAMP()) 2018-02-14 14:15:13 -- Same as NOW(): OK
No acima está tudo bem, exceto a FROM_UNIXTIME(0)
doação 1970-01-01 01:00:00
, que é uma hora de folga. Se Unix Time 0 fosse exibido em UTC, daria 1970-01-01 00:00:00
(ou seria?)
Isso acontece se eu me conectar localmente ou de uma máquina remota.
Para ter certeza dupla, verifiquei coagindo para DATETIME. O mesmo acontece:
CREATE TEMPORARY TABLE test (N DATETIME, FUX DATETIME, UXT LONG, NN DATETIME);
INSERT INTO test SELECT NOW(),FROM_UNIXTIME(0),UNIX_TIMESTAMP(),FROM_UNIXTIME(UNIX_TIMESTAMP());
SELECT * FROM test;
+---------------------+---------------------+------------+---------------------+
| N | FUX | UXT | NN |
+---------------------+---------------------+------------+---------------------+
| 2018-02-14 14:19:51 | 1970-01-01 01:00:00 | 1518617991 | 2018-02-14 14:19:51 |
+---------------------+---------------------+------------+---------------------+
Na hora 0, "Fuso horário: Europa/Londres" era DST (ou não DST?); você não está atualmente no horário de verão (ou está?). Essa é provavelmente a discrepância de 1 hora.
Europa/Londres não é o mesmo que UTC.
Isso depende do fuso horário da sessão. Estou no mesmo fuso horário que você:
Os resultados abaixo são do MariaDB, mas presumo que seja o mesmo com o MySQL.
E:
No entanto:
Estou surpreso que time_zone valorize
SYSTEM
e+0:00
dê resultados diferentes paraFROM_UNIXTIME(0)
, já que meu fuso horário é GMT, +0000. Isso parece um bug para mim, mas talvez haja algo que eu não esteja entendendo.