Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como lidar com o fuso horário do MySQL no script


Você executou esta consulta de diagnóstico de tempo em seu servidor MySQL.
select @@time_zone, now(), utc_timestamp()

Está claro a partir de sua hora local e hora utc que a configuração de fuso horário do sistema da sua máquina servidora é 'Canada/Mountain', e o software do servidor MySQL não possui sua própria configuração de fuso horário.

Se você pegar suas mesas e movê-las inalteradas para um servidor em algum fuso horário próximo, poderá atualizar seu software sempre para emitir o comando
set time_zone = 'Canada/Mountain';

logo após você se conectar a partir do seu software. Isso fará com que sua nova conexão MySQL se comporte como a atual em relação ao fuso horário. Se você possui o servidor MySQL, você pode definir seu fuso horário padrão de acordo com as instruções nesta página. http://dev.mysql.com/doc /refman/5.5/en/time-zone-support.html

Agora, aqui está a história sobre os tipos de dados de tempo. DATE , TIME e DATETIME são todos ignorantes de fuso horário . Depois de armazenar um valor de data/hora, você o recuperará com o mesmo valor, mesmo que altere as configurações de fuso horário.

O TIMESTAMP o tipo de dados é sensível ao fuso horário . Esses itens de dados são sempre armazenados em UTC, também conhecido como hora Z , anteriormente conhecido como Greenwich Mean Time. Eles são sempre convertidos para UTC ao serem armazenados e sempre convertidos novamente ao serem recuperados.

As funções internas para obter a data e hora atuais (NOW() e amigos) são sensíveis ao fuso horário . Eles produzirão valores na hora local. As exceções são as três funções que começam com UTC_ que produzem valores em hora UTC.

Muitos aplicativos MySQL de vários fusos horários usam a seguinte disciplina operacional:
  1. Peça a cada usuário um fuso horário de preferência do usuário ou descubra-o a partir de algum outro dado pessoal sobre o usuário. (Os telefones têm essas informações fornecidas a partir da rede.) Armazene isso como um zoneinfo-friendly descritor de fuso horário ('America/New_York', 'Canada/Mountain', 'Europe/Vienna', etc) em nome do usuário.
  2. Ao estabelecer uma sessão MySQL em nome do usuário, defina o fuso horário do usuário com um set time_zone consulta como a mostrada acima. Você deve fazer isso logo após sua connect operação.
  3. Armazenar datas e horários para usuários em TIMESTAMP tipos de dados. Eles serão convertidos para UTC à medida que forem armazenados.
  4. Recupere-os conforme necessário. Eles serão convertidos de volta para a hora local.

A ideia é que o fuso horário do seu usuário faça parte do contexto dele. Isso funciona bem, porque se o usuário A estiver em Vancouver e o usuário B em Halifax, e por algum motivo o usuário B visualizar os dados de tempo do usuário A, eles serão mostrados a B no horário do Atlântico mais ou menos automaticamente.

Também é bom porque lida de forma transparente com os caprichos globais da mudança da luz do dia para o horário padrão. Um carimbo de data/hora do verão passado será exibido na hora local do verão passado.

Muitos gerentes de servidores para uso global definem o horário do servidor do sistema, ou o fuso horário padrão do MySQL, para UTC. (O seu não.)

Outra maneira de lidar com tudo isso é a maneira como você começou. Escolha um fuso horário e armazene seus carimbos de data/hora em relação a esse fuso horário. É melhor se você escolher um fuso horário que não alterne entre a luz do dia e o horário padrão nesse caso. Então, ao armazenar tempos no banco de dados, converta explicitamente. Você armazenaria os tempos de usuários em Ottawa fazendo algo assim.
INSERT INTO tbl (appt) VALUES ( 'whatever-time' - INTERVAL 120 MINUTE)

e você obteria os valores da mesma maneira. Isso é propenso a erros, mas você pode fazê-lo funcionar.

Finalmente, você mesmo pode fazer suas conversões. Se quiser saber quantos minutos de deslocamento existem entre um fuso horário arbitrário e o UTC, tente essas duas consultas.
set time_zone = 'Canada/Atlantic';
select timestampdiff(minute, utc_timestamp(), now());

Nesta época do ano isso devolve -240, que é -4:00. Você precisa usar minutos em vez de horas devido aos deslocamentos de fuso horário de meia hora ou quarto de hora em alguns países.

Por fim, fique atento. TIMESTAMP tipos de dados não representam tempos antes de 1970. E, na minha instância MariaDB 10.0, parece ir para o inferno em um balde logo após 2038-01-19T03:14:07 UTC quando o tempo passa de 32 bits.