Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá Pessoal,
Tenho a seguinte necessidade:
Encontrar a diferença, em horas, entre dois fusos horários indiferente se a diferença é para maior ou menor.
Qual a utilidade?
Tenho um projeto onde o usuario precisa indicar o seu fuso horario para realizar uma determinada ação. Até ai ok.
Entretanto, este meu usuario poderá estar num fuso diferente da minha aplicação.
Tendo dito o cenário é o seguinte:
Minha aplicação está num servidor de fuso Espanha/Madrid e meu usuário está no fuso America/Sao_paulo.
Neste exemplo eu tenho uma diferença e 5 horas, onde o usuário em America/Sao_paulo está a 5 horas antes do horario do meu servidor, ou seja, usuário está logado as 1500 do dia 23/08 e no meu servidor todas as informações estão sendo processadas as 20:00 do dia 23/08..
Então para facilitar a vida deste meu usuário, ele vai indicar o seu fuso e o meu sistema fara os calculos para que, de acordo com a diferença entre os fusos, meu servidor processe tudo baseado no horario local de Europe/Madrid.
Parece simples mas chegarei a um momento onde terei usuarios de diversos fusos realizando ações em minha aplicação.
Deste modo eu tenho rabisquei o seguinte código
date_default_timezone_set('Europe/Madrid'); //seto como default o fuso do meu servidor
$datek = date('H'); //salvo na variavel a hora do meu servidor
echo "<br>".$datek."<br>"; //imprimo por imprimir
date_default_timezone_set('America/Sao_paulo'); //seto um novo default com o fuso do meu usuario
$datep = date('H'); /salvo na variavel a hora baseada no fuso do usuario
echo "<br>".$datep."<br>"; //imprimo por imprimir
echo "<br>".(($datek - $datep)+24)."<br>"; //imprimo e o resultado é 5
Neste modo com o fuso America/Sao_paulo o resultado é 5, ou seja, correto, logo me atende!
Agora se o meu usuario tiver o fuso Europe/Lisbon, onde a diferença é 1 hora a menos entre Lisboa e Madrid (por exemplo Lisboa 03:00AM - MAdrid 04:00AM) o resultado deste script é 25
Alguma sugestão de melhoria ou alguma outra função que me traga essa diferença de hora entre dois fusos?Sistemas com múltiplos fuso horários tendem a unificar os horários salvos em GMT (Greenwich Mean Time) ou UTC 0, para que cada usuário possua seu próprio fuso horário e os seus registros estejam unificados.
Quanto a forma de exibição, a biblioteca Date/Time consegue resolver isso pra ti de forma bem flexível:
$timeZone = new DateTimeZone("America/Sao_Paulo");
$UTC = new DateTimeZone("UTC");
$date = new DateTime("2017-08-24 10:15:00", $timeZone );
$date->setTimezone( $UTC );
echo $date->format('Y-m-d H:i:s');
Saída
>
Citar
2017-08-24 13:15:00
>
16 horas atrás, marsolim disse:
tem certeza que vais precisar calcular a diferença? não seria só ter a lista de fusos pro usuário escolher? aí já vai ter o fuso correto sem precisar calcular...
Preciso sabe porque?
Porque a aplicação que estou trabalhando não tem "inteligência" para interpretar timezones distintos então eu preciso dessa "gambiarra"
Vamos supor
timezone Europe/Madrid
Neste momento são 21:32PM
timezone America/Sao_paulo
Neste momento são 16:32PM
Diferença 5 HORAS
Por mais que eu indique a minha aplicação que está em Europe/Madrid que o horario que está recebendo está vindo de um timezone distinto, a aplicação sempre gera suas ações baseadas no seu timezone ignorando o timezone do usuario mesmo quando indicado.
Deste modo o que eu preciso fazer é identificar a diferença de horas entre os dois timezone.
Encontrada essa diferença eu somo ou subtraio esse valor na hora do cliente para mandar a minha aplicação o horario correto.
Vamos supor que eu tenho uma ação de agendamento
O meu usuario em time America/Sao_paulo quer agendar uma ação para as 17h.
Quando mando essa info para a aplicação, a aplicação não agenda a ação e a executa imediatamente. Porque? Porque ela ignora a indicação do timezone e trata tudo no timezone local.
Neste caso eu preciso pegar a hora indicada pelo meu usuario - 17h - e somar 5 horas (diferença entre os dois fusos).
Deste modo a ação de agendamento ao meu servidor vai chegar para as 22h (17h + 5h) e assim, somente assim, minha aplicação faz o agendamento do comando.
Em resumo, minha aplicação somente processa dados de data em seu timezone local ignorando o timezone do usuario.
o script do Gabriel Heming te serve como uma luva acho eu pois ele faz pegar a hora de uma tz e converter na outra sem precisar mais nada. acho que é o que precisa
Segue o caminho encontrado para ter a Diferença entre dois fusos (em hora)
function tzDifference($tz){
//PUXO A HORA ATUAL DE ACORDO COM O TZ INFORMADO PELO USUARIO
$date = new DateTime('now', new DateTimeZone($tz) );
$date = strtotime($date->format('H:i:s'));
//PUXO A HORA ATUAL DA MINHA APLICAÇÃO DE ACORDO COM O MEU TZ FIXO
$date2 = new DateTime('now', new DateTimeZone('Europe/Madrid') );
$date2 = strtotime($date2->format('H:i:s'));
//CALCULO AS DATAS E IMPRIMO O RESULTADO
$diffHours = round(($date2 - $date) / 3600);
switch($diffHours){
case $diffHours > 0:
$x = '+'.$diffHours.'hours';
break;
default:
$x = $diffHours.'hours';
break;
}
return $x;
//EXEMPLO DE SAIDA: '+5Hours' ou '-5hours'
}
E tendo esse resultado eu aplico assim:
$horaDiferenca = tzDifference('America/Sao_paulo'); //aqui o meu usuario indica num select box qual o timezone dele
$dataEnvio = date("Y-m-d H:i:s", strtotime($programa[0]['data'].$programa[0]['hora'].$horaDiferenca));
Porque tudo isso?:
Porque a aplicação API que estou chamando trabalha unica e exclusivamente via TZ Europe/Madrid e para que ações programadas/agendadas funcionassem corretamente, era preciso encontrar a diferença em horas de acordo com o TZ do API com o TZ do meu usuario e indicar a hora ao API de acordo com a hora do TZ dele, que é Europe/Madrid
Espero que ajude alguem e se alguem tiver mais sugestões de melhoria, fico aberto a opiniões :)
tem certeza que vais precisar calcular a diferença? não seria só ter a lista de fusos pro usuário escolher? aí já vai ter o fuso correto sem precisar calcular...