Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

Introdução

Trabalhar com data e hora em sistemas modernos requer entender completamente o uso de fuso horários. Uma aplicação web ou mobile é composta, em sua maioria das vezes, de banco de dados, servidor e cliente (navegador web ou aplicativo). É necessário entender bem que o fuso de cada uma dessas camadas pode ter especificações diferentes que podem gerar confusões ao implementar seu sistema.

Banco de dados

A maioria dos bancos de dados fornecem alguns tipos de dados para armazenamento de data (tipo DATE), data e hora (tipo DATETIME) ou apenas hora (tipo TIME). Tais tipos podem considerar as informações de fuso ou não. A grande confusão ocorre quando tais tipos não levam em consideração o fuso, o que acabam ficando dependente de uma configuração correta do servidor e cliente para que não haja diferença de horários. Falaremos disso mais na frente. 

Os tipos mais comuns são:

  • DATE: armazena apenas a data sem informações do fuso. Contém apenas uma data civil, sem qualquer consideração de fuso horário. Por exemplo, data de nascimento, ou a data de vencimento de uma conta, ou um prazo legal, é DATE;.
  • DATETIME: armazena data e hora sem informações de fuso.  Contém data e hora civis, novamente sem considerar o fuso horário. Se, por exemplo, o prazo de pagamento é "dia tal até 13:0013h00", é responsabilidade do pagador saber se estamos no horário de verão ou não, qual o fuso horário do local em que ele se encontra, etc.
  • TIME: armazena apenas hora sem informações de fuso. É o mesmo que os campos acima, porém não específica a data;.
  • TIMESTAMP: armazena informações de data e hora levando em consideração o fuso horário. É um número que determina um momento específico. Tipicamente é expresso como o "número de segundos desde 1/1/1970 00:00 em Londres", mas poderia ser qualquer outra base. A ideia do timestamp é que ele vale no mundo todo, ou seja, ele identifica o momento exato em que algo aconteceu. Um acontecimento com timestamp "0" aconteceu em 31/12/1969 às 21:00 no Brasil e 1/1/1970 00:00 em Londres.

O timestamp é útil para registrar log, e para determinar se A aconteceu antes ou depois de B, mesmo que A e B tenham acontecido em lados opostos do planeta. Por outro lado, o timestamp é inadequado para registrar datas e horas "civis" porque a hora e até a data muda conforme o fuso horário em que o timestamp é interpretado.

Nem sempre a melhor opção é óbvia. Por exemplo, registrar a data de nascimento com DATETIME ou TIMESTAMP? De um ponto de vista matemático, o TIMESTAMP seria ideal porque um bebê nasce num momento bem determinado. Por outro lado, a data e hora de nascimento têm efeitos civis - colocar a data de nascimento diferente da Carteira de Identidade pode causar um monte de aborrecimentos - então é melhor usar DATETIME e o local de nascimento, já que o fuso horário é de conhecimento público.

Resumindo, ao usar DATE, DATETIME ou TIME, seu servidor tem que conhecer em qual fuso horário você deseja obter e gravar esses valores, para esses casos, recomendamos que o Banco e o Servidor estejam no mesmo fuso horário.

Servidor

O servidor normalmente tem apenas uma configuração global de fuso horário. Ao gravar ou obter campos do tipo DATE, DATETIME ou TIME, ele vai usar a informação de fuso configurada para suas conversões internas. Ao gravar ou obter campos do tipo TIMESTAMP, ele vai simplesmente respeitar o que está informado no valor, ou seja, as informações do fuso horário do servidor não interferem. O Cronapp usa o JAVA como plataforma base do servidor e o tipo java.util.Date para representação de todos os tipos internos: data, data e hora, hora e timestamp. O uso de um único tipo é um padrão especificado pela Java Persistence Interface (JPA). Para "entender" o que significa cada tipo, o JPA exige anotações acima da declaração do tipo do atributo na classe que representa a tabela do banco. Não vamos entrar em detalhes, viso que é um assunto mais High-Code que fica abstraído para quem usa o Cronapp apenas como Low-Code.

Cliente (Navegador ou Aplicativo)

O fuso horário do aplicativo é o que pode sofrer mais variações. Nos sistemas modernos, na Na maioria das vezes em sistemas modernos, os usuários estão ao redor do mundo. Sendo assim, na maioria dos casos, precisamos aceitar entradas e exibições de datas e horas , considerando o fuso horário de quem está digitando ou lendo.

Exemplo: Imagine um sistema de cadastro de eventos. Nesse sistema, usuários do mundo inteiro poderão cadastrar eventos que devem acontecer segundo o contexto de fuso de quem cadastra, porém, para outros usuários ao redor do mundo, tais horários podem ser exibidos com diferenças. Um evento às 10:00 de Londres ocorre às 07:00 do Brasil. Ou um evento 00:00 de Londres do dia 10/11/2019 ocorre às 21:00 do dia 09/11/2019 no Brasil.

Como o Cronapp trata Data e Hora

O Cronapp procurou deixar tudo mais simples para seus usuários, inclusive aqueles que não têm pretensão de que seus sistemas funcionem em diferentes fusos horários. Para isso, vale a pena entender bem os recursos e configurações que o Cronapp oferece, para que não haja desperdício de tempo com tentativas, erros ou suporte. Então, vamos as configurações:

Configurando o fuso horário no Cronapp

Através do menu Projeto > Configurações e depois na aba Configurações de Projeto (Figura 1), existem dois campos importantes:

  1. Converter Fuso Horário do Cliente: marcando essa opção o Cronapp se comportará de forma bem simples. Independente do fuso que o cliente (navegador web ou aplicativo) estiver ele será desconsiderado e será utilizado o fuso informado na opção Fuso Horário.
  2. Fuso horário: configura o fuso horário do servidor (da aplicação). Os campos DATE, DATETIME e TIME terão o fuso da opção selecionada. O campo TIMESTAMP não é afetado por essa opção (a não ser no formato textual). O valor padrão para esse campo é (GMT00:00) UTC.


Image Modified

Figura 1 - Campos de configuração de configuração de fuso horário no Cronapp

Os formatos usados no diagrama de dados

O diagrama de dados oferece os 4 tipos mais comuns de data de bancos de dados:

  1. Data: criará ou considerará o campo do banco como DATE. O fuso será considerado como informado nas configurações do projeto;
  2. Data e Hora: criará ou considerará o campo do banco como DATETIME. O fuso será considerado como informado nas configurações do projeto;
  3. Hora: criará ou considerará o campo do banco como TIME. O fuso será considerado como informado nas configurações do projeto;
  4. Date e Hora com Fuso: criará ou considerará o campo do banco como TIMESTAMP.

Cliente (Editor HTML)

Cada campo que é capaz de exibir ou editar uma data, data e hora ou hora possui alguns tipos a serem considerados. Eles terão comportamentos diferentes a depender da configuração feita nas configurações do projeto (mostrado na Figura 1). Vários campos podem receber datas. Exemplos:

  • Entradas: entrada de texto, listas etc. Para esses casos, usam-se as propriedades Tipo e Máscara do componente (Figura 2.1);

Image Modified

Figura 2.1 - Campos Tipo e Máscara nas propriedades de uma entrada de texto


  • Qualquer texto da Tela: grade, títulos etc. Para esses casos usa-se o "..." ao lado da propriedade (Figura 2.2);

Image Modified

Figura 2.2 - Abrir janela de conteúdo do componente texto


  • Qualquer propriedade Textual de qualquer componente: rótulos, conteúdos etc. Para esses casos, o ícone para editar expressão (Figura 2.3) que aparece ao passar o mouse sobre a propriedade é usado para abrir a mesma janela da Figura 2.2.

Image Modified

Figura 2.3 - Editar expressão do conteúdo do componente texto


A exibição desses campos será influenciada pelo Tipo e pela Máscara que serão escolhidas. As opções para o Tipo podem ter os seguintes valores para uma data, data e hora ou hora:

  • Data (Date): exibe a data desconsiderando a hora, mesmo que no diagrama tenha sido usado algum tipo que considere a hora. Se o tipo no diagrama tiver hora, ela será armazenada como 00:00:00. Se a opção Converter Fuso Horário do Cliente estiver marcada, esse campo irá exibir o fuso da opção, caso contrário usará o fuso do navegador web ou aplicativo;
  • Data e Hora (Date and Time): exibe a data e hora. Se a opção Converter Fuso Horário do Cliente estiver marcada, esse campo irá exibir o fuso da opção, caso contrário usará o fuso do navegador web ou aplicativo;
  • Data e Hora Locais (Date and Time Local): exibe a data e hora. Será exibido no fuso local do navegador/aplicativo;
  • Hora (Time): exibe apenas a hora. Se o tipo no diagrama tiver data, ela será armazenada como 01/01/1970;
  • Hora Local (Time Local): exibe apenas a hora. Se o tipo no diagrama tiver data, ela será armazenada como 01/01/1970. Será exibido no fuso local do navegador/aplicativo;
  • Mês (Month): exibe apenas o mês da data (Janeiro, Fevereiro etc). Ao entrar uma nova data, usará dia, ano e hora atuais;
  • Semana (Week): exibe apenas o dia da semana da data (Segunda-Feira, Terça-Feira etc). Ao entrar uma nova data, usará mês, ano e hora atuais.

Exemplo: Um campo com a data  22/11/2000 10:00:00 UTC (00:00). Se estivermos com a opção Converter Fuso Horário do Cliente e o fuso escolhido tiver sido UTC (00:00) e o fuso do cliente seja America/Sao_Paulo (-03:00), teremos os valores para os diferentes tipos:

  1. Date: 22/11/2000;
  2. Date and Time 22/11/2000 10:00:00;
  3. Date and Time Local: 22/11/2000 07:00:00;
  4. Time: 10:00:00;
  5. Time Local: 07:00:00. Será exibido no fuso local do navegador/aplicativo;
  6. Month: Novembro;
  7. Week: Quarta-Feira;

A máscara irá determinar o padrão da janela de escolha rápida de datas, horas, meses, semanas, dias etc. Exemplos:

  • DD/MM/YYYY: sobe um seletor apenas de data;
  • MM: sobe um seletor de mês em texto e exibe o mês em número (Figura 3.1);
  • MMMM, MMM: sobe um seletor de mês em texto e exibe o mês também em texto;
  • DD/MM/YYYY HH:mm:ss: sobe um seletor com data e hora;
  • DD/MM/YYYY HH:mm:ss A: sobe um seletor com data e hora com seleção e AM e PM;
  • HH:mm:ss: sobe um seletor com hora, minuto e segundo;
  • HH:mm: sobe um seletor com hora e minuto (Figura 3.2);
  • dddd: sobe um seletor de data, mas exibe apenas o nome da semana no campo.

Para entender mais sobre máscaras no cliente, leia o documento Formatação de máscaras para campos de texto.

Nessa Nesta página

Índice
maxLevel3
printablefalse



Figura 3.1 - Utilizando a máscara MM e o seu comportamento no browser




Figura 3.2 - Utilizando a máscara HH:mm e o seu comportamento no browser



Bloco de Programação

O bloco de programação fornece algumas funções para tratamento de datas. Algumas das mais importantes são:

Camada Servidor: 

  • Obter valor do campo: obtém o valor de qualquer campo da tela cliente no servidor. Todos os campos data e hora trafegam entre o cliente e servidor no formato ISO 8601 que inclui todas as informações de data, hora com minutos, segundos, milissegundos e fuso. Ao trafegar do cliente para o servidor, ele leva as devidas conversões de fuso;
  • Obter campo (Banco de Dados): essa função obtém o campo do banco de dados que sempre estará no fuso especificado para a aplicação; 
  • Exibir Notificação: essa função bem comum merece uma observação importante, ao exibir uma data. Caso você não formate a data, ela será exibida no fuso horário do cliente;
  • Imprimir: essa função bem comum merece uma observação importante, ao imprimir uma data. Caso você não formate a data, ela será exibida no formato ISO 8601 no fuso horário do servidor;
  • Converter Texto para Data: essa função converterá um texto (representação textual de uma data) para um objeto data. Caso uma máscara seja informada, ela a usará para tentar fazer a conversão, caso contrário, algumas máscaras predefinidas serão usadas - levando em consideração o idioma do cliente. Caso o formato textual não considere o fuso na sua escrita (ex: 12/03/1910), o fuso padrão do servidor será usado. Caso o fuso tenha sido especificado (ex: 2019-09-22T02:30Z), ele será usado;
  • Converter Texto para Data com Fuso Horário: tem o mesmo comportamento da função acima, porém, quando o fuso não está discriminado, ele usa o especificado pelo parâmetro de fuso da função;
  • Formatar Data: formata uma data para um formato textual. Caso a máscara seja informada, ele a usará (Figura 4), caso contrário, usará o padrão de máscara do idioma escolhido pelo cliente. Ao formatar para um texto, o Cronapp irá usar o fuso especificado para a aplicação;
  • Formatar Data com Fuso Horário: tem o mesmo comportamento da função acima, porém o fuso pode ser especificado através do parâmetro da função.




Figura 4 - Utilizando máscara no bloco e exibindo no componente




Observações:

  1. Caso um Objeto Data seja enviado para qualquer função que espere um texto, ele será representado pelo formado ISO 8601 no fuso horário especificado para a aplicação. Ex: JSON enviado para um serviço REST;
  2. Tenham atenção ao visualizar o formato ISO 8601 das datas. Datas com textos diferentes podem representar o mesmo valor, pois o fuso pode estar escrito de forma diferente: Ex: 2019-09-22T00:00:00Z é igual a 2019-09-21T09:00:00-03:00;
  3. A especificação de máscaras no servidor é diferente do cliente. Seguem alguns exemplos de máscaras no servidor:
dd-MM-yy31-01-12
dd-MM-yyyy31-01-2012
MM-dd-yyyy01-31-2012
yyyy-MM-dd2012-01-31
yyyy-MM-dd HH:mm:ss2012-01-31 23:59:59
yyyy-MM-dd HH:mm:ss.SSS2012-01-31 23:59:59.999
yyyy-MM-dd HH:mm:ss.SSSZ2012-01-31 23:59:59.999+0100
EEEEE MMMMM yyyy HH:mm:ss.SSSZSaturday November 2012 10:45:42.720+0100
dd/MM/yyyy31/01/2012
dd/MM/yyyy HH:mm:ss31/01/2012 23:59:59


Para o cliente, leia o documento Formatação de máscaras para campos de texto.