Como posso lidar com fusos horários em meu webapp?

106

Estou procurando um melhor entendimento da seguinte história de usuário:

John trabalha em Sidney. Às 9h da manhã, ele registra um evento em um aplicativo da web executado em um servidor em Zurique. No dia seguinte, ele viaja para Nova York para uma reunião de emergência na qual o evento será discutido. Durante a reunião, ele pesquisa o evento por data e hora.

A meu ver, há pelo menos dois problemas aqui:

  1. Como devo salvar as marcas de tempo no banco de dados
  2. Como devo apresentá-los na IU

Quando John pesquisar o evento, ele saberá que aconteceu às 9h, mas o que ele deve inserir no navegador da web? Ele não encontrará nada quando apenas inserir "9:00" como carimbo de data / hora, porque pode ser o horário de Zurique ou Nova York (como o evento não foi encontrado, o aplicativo não tem como saber que aconteceu em Sidney, então não pode selecionar automaticamente o fuso horário correto).

Qual é uma boa maneira de pedir ao usuário um carimbo de data / hora que pode incluir o fuso horário?

A segunda questão é como exibir os resultados. Se equipes de todo o mundo precisam discutir o evento (e encontrar eventos relacionados, pense em um ataque de cracker que visa vários sites em todo o globo de uma vez).

Qual é um bom exemplo de exibição de carimbos de data / hora que podem ter sido criados em um fuso horário diferente?

Observação: concentre-se na usabilidade do requisito. Eu posso descobrir o mapeamento do banco de dados sozinho. Atualmente, não tenho certeza sobre o fluxo de trabalho. Deve pedir / apresentar as informações necessárias de forma não intrusiva / intuitiva. Se você puder, forneça um link para um aplicativo da web existente que já resolve isso.

Aaron Digulla
fonte
5
Stack Overflow resolve isso colocando tudo em UTC. Nem sempre é conveniente, mas é definitivamente inequívoco, não é difícil de implementar e funciona.
Ry-
2
UTC é tentador, mas OTOH, SO nunca precisa sincronizar eventos em vários fusos horários.
Aaron Digulla
3
E se um dos países envolvidos promulgar legislação que altera o horário local depois que o evento foi agendado, mas antes que ele ocorra? Como o sistema deve lidar com isso? en.wikipedia.org/wiki/…
Julius Musseau
1
Este tipo de pergunta clássica de fuso horário foi tão batida até a morte por décadas em toda a Internet e impressa, estou surpreso de ver tantas contribuições e recompensas animadas sobre esta questão!
BenSwayne
2
Acrescento um ponto adicional de complexidade apontando o óbvio, ou seja, que a maior parte do mundo ocidental muda de fuso horário duas vezes por ano ("Horário de verão"), e que as regras para quando isso ocorre não são uniformes globalmente nem necessariamente triviais, algoritmicamente falando?
fr13d

Respostas:

99

A questão de armazenar carimbos de data / hora é simples: armazene-os em UTC.

Quanto a exibi-los, faria sentido pegar a configuração de fuso horário do dispositivo e usá-la como o fuso horário atual. Dito isso, deve haver uma lista suspensa de fuso horário ao lado da caixa "entrada de hora", que é padronizada para o fuso horário atual do dispositivo, para que o usuário possa alterá-lo se necessário.

A maioria dos seus usuários provavelmente não mudará muito os fusos horários, ou nem mudará nada. Na maior parte, a situação que você descreveu é incomum. Ao implementar uma lista suspensa com um padrão adequado, você deve ser capaz de tornar as coisas fáceis o suficiente para aqueles que se deslocam (porque eles normalmente têm uma compreensão melhor dos fusos horários do que um não viajante).

Na verdade, melhor ainda seria salvar o fuso horário em que o dispositivo foi definido quando seu aplicativo foi executado pela primeira vez e ver se ele muda. Se mudar, o usuário provavelmente é um viajante e provavelmente se beneficiaria com a lista suspensa de fuso horário. Caso contrário, apenas não mostre o menu suspenso e o padrão para o fuso horário do dispositivo (porque o usuário não precisa saber sobre eles). Em qualquer caso, tenha uma configuração no aplicativo que permita ao usuário mostrar / ocultar manualmente a lista suspensa de fuso horário.


Para resumir o acima:

  • Na primeira execução, salve o fuso horário para o qual o dispositivo está definido.
  • Use esse fuso horário como o fuso horário padrão. Sempre assuma esse fuso horário.
  • Se o dispositivo mudar de fuso horário, adicione uma lista suspensa para selecionar em qual fuso horário o evento está, padronizando para o próprio fuso horário do dispositivo.
  • Adicione uma opção para mostrar / ocultar a lista suspensa de fuso horário manualmente.
  • Sempre armazene carimbos de data / hora em UTC.
Niet the Dark Absol
fonte
O que queremos dizer com "fuso horário" Parece usado de forma ambígua. Isso parece uma referência: en.wikipedia.org/wiki/Tz_database Pelo que posso dizer, um "fuso horário" é "Área / Localização", por exemplo, "América / New_York". Isso parece ser geográfico, o que é ótimo porque, por exemplo, América / Los_Angeles significa AMBOS PST e PDT, dependendo se o globo está operando no horário de verão. E se for esse o caso, a questão é como contabilizamos as mudanças semestrais na compensação UTC para as zonas? Também como chamamos essas avaliações, uma vez que não são "zonas" geograficamente corretas?
iJames
Esta é uma ótima resposta. Existe uma prática recomendada sobre como armazenar as informações de fuso horário? Por exemplo - qual seria melhor - 'PST' ou 'América / Pacífico'? Como poderei facilmente converter um carimbo de data / hora em UTC para o fuso horário do usuário capturado? Quaisquer melhores práticas sobre isso seriam apreciadas.
Patthebug de
27

Em nossos aplicativos, geralmente armazenamos o fuso horário do usuário quando nos registramos pela primeira vez, como costumamos ver em sites de fóruns, e sempre exibimos a hora com o fuso horário .

Quanto ao armazenamento das datas, o UTC é o caminho a seguir. Converta para UTC e cole-o no banco de dados. Durante a recuperação, basta converter a hora para o fuso horário definido para o usuário.

Tive que resolver um caso de uso semelhante, onde notificações personalizadas, como "Feliz Ano Novo", puderam ser enviadas a todos os usuários do aplicativo web. Como os usuários estão espalhados pelo mundo todo, precisávamos exibir a notificação de acordo com o fuso horário. Armazenar o carimbo de data / hora em UTC atendeu bem ao nosso propósito, sem soluços.

No seu caso de uso, se você não estiver armazenando o fuso horário do usuário em algum lugar, você nunca poderá retornar com precisão os resultados da pesquisa sem solicitar a entrada do usuário, a menos que comece a usar algum tipo de detecção de localização como o gmaps faz, mas isso não é t confiável. Portanto, você precisará solicitar o fuso horário todas as vezes para garantir que o usuário saiba o que está inserindo no site.

Se você tiver informações de fuso horário, todo o aplicativo da web deve ser executado com a configuração de fuso horário. Portanto, quando o usuário pesquisar 9h, ele estará pesquisando com o fuso horário de Sydney. Por outro lado, se ele criar um evento enquanto estiver sentado em Nova York, ele criará um evento com o fuso horário de Sydney. Resolvemos esses casos exibindo sempre o fuso horário ao exibir as datas.

Espero que ajude! :)

Varun Achar
fonte
Acho que com a adição de uma lista suspensa para fusos horários ao pesquisar e criar eventos, este é o caminho a seguir. (quando preciso pesquisar o evento criado por um colega em Nova York, não quero fazer as contas sozinho)
RasmusWL
Esta é uma ótima resposta. Existe uma prática recomendada sobre como armazenar as informações de fuso horário? Por exemplo - qual seria melhor - 'PST' ou 'América / Pacífico'? Como poderei facilmente converter um carimbo de data / hora em UTC para o fuso horário do usuário capturado? Quaisquer melhores práticas sobre isso seriam apreciadas.
Patthebug de
11
  1. UTC. Mantenha simples.

  2. Use o fuso horário mais relevante para o usuário.

    Se você sabe que o usuário estará em ou viajando para Sydney para o evento, ele estará pensando nesse fuso horário ao providenciar o transporte para o evento. O fato de estarem atualmente em Nova York é bastante irrelevante. E, claro, se seu aplicativo mostra datas em uma variedade de fusos horários, ele sempre deve mostrar o fuso horário ao lado da data, por exemplo, 09:00 EST .

    Se isso não atrapalhar muito sua interface, você pode exibir as datas no fuso horário do evento e no fuso horário local, por exemplo, 2012-06-13 09:00 EST (2012-06-12 19:00 EDT) .

    Eu diria que pesquisar é um problema semelhante, com uma ressalva: podemos tolerar falsos positivos (obtendo um resultado que não esperávamos), mas não podemos tolerar falsos negativos (não obtendo o resultado que esperávamos).

    Novamente, eu me concentraria em pesquisar o fuso horário mais relevante para o usuário (por exemplo, fuso horário do evento) e daria a esses resultados prioridade nos resultados da pesquisa, mas você também pode retornar eventos que correspondem a outros fusos horários que são relevantes para o usuário (por exemplo horário local). Se você fizer isso, deverá mostrar a data do evento no fuso horário correspondente, especialmente se destacar o texto correspondente.

Richard Poole
fonte
7

Aqui estou dando sugestões para a melhor usabilidade sem me preocupar muito com a viabilidade de implementação.
1. Para a primeira edição de armazenamento de eventos em db, todos concordariam em armazená-lo em UTC

2. Para dar a melhor experiência ao usuário, salve o histórico do fuso horário do usuário. Se você pudesse salvar o carimbo de data / hora da alteração do fuso horário, melhor ainda. Isso nos permitirá dar liberdade ao usuário para consultar sem especificar o fuso horário explicitamente todas as vezes.

Então, com esses recursos, vamos ver como a consulta de pesquisa de apenas "9,00" por John será tratada:
Com os recursos mencionados acima, agora eu sei que John esteve em 2 fusos horários até a data (ou obtenha a lista de fusos horários para o período mencionado). Então, vou converter 9,00 do fuso horário de Sydney para UTC, disparar uma consulta. Converta também 9,00 do fuso horário de Nova York para UTC e dispare uma consulta. Como resultado, mostrarei 2 linhas para John exibindo o que ele fez às 9h em Sydney e às 9h em Nova York. A linha de Nova York estará em branco neste caso, mas acho que ainda deve ser mostrada ao usuário, apenas para informá-lo que pesquisamos por este fuso horário também.

3. Qual é uma boa maneira de solicitar ao usuário um carimbo de data / hora que pode incluir o fuso horário?

Se o seu fuso horário foi alterado recentemente, sempre que ele logar no aplicativo, uma notificação deve ser fornecida que seu fuso horário padrão é alterado para o fuso horário nativo.
Ao criar o evento, digamos que o usuário selecione o fuso horário no menu suspenso. Não sobrecarregue o usuário, dando opções de todos os fusos horários do mundo. A primeira opção do menu suspenso deve ser o fuso horário atual do dispositivo do usuário. depois desses fusos horários de sua história de fusos horários, então UTC e os fusos horários restantes que ele nunca usou até agora.

4. Como exibir os resultados, se equipes de todo o mundo precisam discutir o evento:

Gostaria de dividir este caso de uso entre o número de equipes 2 ou mais de 2.
Para apenas 2 equipes, preferiria que cada equipe visse o carimbo de data / hora em seu fuso horário local e o fuso horário da outra equipe. (Eu pessoalmente prefiro falar no fuso horário da pessoa do outro lado para sua conveniência ao agendar uma reunião). Para mais de 2 equipes, é melhor considerar o fuso horário mais comum, ou seja, UTC. Portanto, neste caso, cada usuário deve ver o carimbo de data / hora em 2 fusos horários, em UTC e em seu fuso horário padrão.

Essas sugestões são dadas com a intenção de que o usuário não precise fazer nenhum cálculo em seu horário local, mas ao mesmo tempo ele deve ser capaz de se comunicar com outros usuários fluentemente em seu fuso horário preferido.

Pranalee
fonte
2
+1 Esta é uma ideia muito interessante porque sei que o usuário entrou em um evento às 9h em Sidney, então quando o mesmo usuário pesquisa por um horário (sem fuso horário explícito), devo presumir que ele quer dizer "onde eu estava daquela vez "
Aaron Digulla
4

Ok, tenho uma abordagem diferente das outras:

Em primeiro lugar, presumi algumas coisas de antemão.

A pessoa que está listando um evento tem um smartphone (se for um navegador, não preciso fazer essas suposições) com:

  1. GPS

  2. Capacidade de HTML5.

  3. Capacidade de Javascript

Como devo salvar os registros de data e hora no banco de dados?

Solução: Obviamente UTC , sobrepus o procedimento abaixo:

Etapa 1. Use a geolocalização do usuário usando a API de geolocalização

    window.onload = getMyLocation;

    function getMyLocation() {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(displayLocation);
        } else {
            alert("Oops, no geolocation support");
        }
    }

    function displayLocation(position) {
        var latitude = position.coords.latitude;
        var longitude = position.coords.longitude;
        var div = document.getElementById("location");
        div.innerHTML = "You are at Latitude: " + latitude + ", Longitude: " + longitude;
    }

Etapa 2. Dê o (Long, Lat) como argumentos para algumas das APIs ( Lat, Long) para TimeZone, como a API do Yahoo (use o Sinalizador R para converter o Latitude em Fuso Horário) para obter o fuso horário dos usuários.

=> O fuso horário dos usuários é determinado sem a entrada do usuário (estou usando isso porque você não pode simplesmente assumir que o usuário sabe o fuso horário do lugar em que mora, eu sabia meu fuso horário apenas depois de alguns meses ou algo no local: P, que idiota! )

Cada tabela de eventos tem Timezone, Evente também pode ter. CityName Crie outra tabela de banco de dados com classificação baseada em CityNames. Então aqui o usuário terá duas colunas

|---------------------------------------|
|_____NewYork________|______Sydney______|
|                    |                  |
|Event 1             |  Event 2         |
|____________________|__________________| 

Para IU

=> usar a API do Google Agenda ou alguma das APIs

Leituras relacionadas:

  1. Determine o fuso horário de latitude / longitude sem usar serviços da web como Geonames.org

  2. Pesquisa de fuso horário a partir de latitude e longitude

Eu sei que é só mostrar uma ideia de como resolver esse problema. Mas veja como ele se torna preciso e leve para os usuários quando o fuso horário é determinado usando APIs de dispositivo

Espero que ajude!

uday
fonte
4
É muito fácil encontrar o fuso horário de alguém sem geolocalização. new Date().getTimezoneOffset()dá em minutos atrás do UTC.
Ry-
@minitech, isso é verdade, mas e se o evento estiver acontecendo em Nova York e em algum lugar ao sul onde é o mesmo fuso horário. Estou usando a geolocalização para que você possa localizar a cidade (até mesmo precisa), o fuso horário em oneshot e basear minha tabela db nela. Quero minimizar a entrada do usuário usando a API do dispositivo para aumentar a eficácia do aplicativo.
dia
Assim? A hora será a mesma nos dois lugares, então não há problema. -1
Ry-
@minitech, você pode ver este link explicando porque eu recomendo o uso de APIs de dispositivo em vez de outros métodos. webdirections.org/sotmw2011
uday
2
Ok, mas a questão aqui não é obter a cidade do usuário. Trata-se apenas de obter o fuso horário. Usar uma API de geolocalização que não funciona em todos os navegadores / computadores e, em seguida, redirecionar para uma API de calendário é uma maneira ruim de obter o fuso horário de um usuário quando está disponível em uma linha de código.
Ry-
2

Para esse caso específico, armazenaria a hora local e a hora UTC. UTC é um pouco importante e usado para sincronização e conversão de hora para o fuso horário atual. Local é usado para pesquisas e informações adicionais, como:

Você tem uma reunião:

12:00 Monday (UTC)
9:00 Monday (Sydney, creation local time)
11:00 Monday (Zurich, local time)

ou algo assim. A outra maneira é armazenar o fuso horário de criação e converter no tempo de execução (isto é particularmente melhor caso o usuário altere o horário da reunião). De qualquer forma, o principal motivo é ser capaz de restaurar o tempo de criação original para que o usuário possa consultá-lo.

Petr Abdulin
fonte
2
  1. Como devo salvar as marcas de tempo no banco de dados

Na criação do evento, eu armazenaria a hora UTC e o fuso horário local (também conhecido como creation time zone). Eu usaria o que armazenei para converter a hora UTC em hora local (também conhecida como creation time) e armazená-la junto com a hora UTC e creation time zone.

NOTA: Posso armazenar a hora local desde o início, mas quando o usuário faz uma pesquisa por um evento, espero que exista uma conversão para a hora local. Também espero que o servidor possa detectar em qual fuso horário o cliente está.

  1. Como devo apresentá-los na IU

Quando um usuário procura para "09:00", eu iria procurar por eventos que incluem "9:00" em qualquer UTC OU creation time OU hora local. Para os resultados, eu exibiria uma tabela de resultados em creation time(isso se destina a exibir carimbos de data / hora que podem ter sido criados em um fuso horário diferente, pois supomos que o usuário está procurando a hora em que criou um evento para onde quer que esteja). e exiba uma segunda tabela de resultados abaixo com resultados relacionados, talvez com o cabeçalho "Não é o que você está procurando? Ver resultados relacionados" (isso inclui o UTC restante e os resultados de hora local).

No geral, eu exibiria o horário UTC, o horário local, o creation time, e o creation time zone(ou seja, o horário local e o fuso horário do evento onde foi criado) classificados pelo horário UTC, para que você possa ver qual evento vem primeiro, no caso de dois os eventos foram programados para as 9h em dois fusos horários diferentes.


fonte
1
+1 Gosto da ideia de mostrar todos os eventos em todos os fusos horários onde coincida a hora local; Estou apenas insatisfeito com o SQL ( BETWEENcondições 24x ).
Aaron Digulla