Usabilidade na exibição de datas e horas

por Administrador - 31/01/2008 - 12:06

Recentemente venho tomando um cuidado maior na forma como apresento as informações de um sistema para o usuário.
Certos tipos de dados quando apresentados para o usuário não trazem consigo muita informação, um caso clássico são as datas e horas. Datas e Horas ganham muito mais significado quando comparadas a outras datas, por isso, seria muito mais interessante que nas consultas, relatórios e outros locais do sistema, aonde mantenham-se datas e horas, o sistema fizesse estas comparações para o usuário, pois se o sistema não o fizer, o usuário vai ter que fazer isto “de cabeça”.

Na prática o que quero demonstrar é que é muito mais fácil e natural, ler algo como “O boleto vence daqui 3 dias”, do que, “O boleto vence dia 10/02/2008”. Percebam como no primeiro exemplo houve uma comparação da data de vencimento do boleto com a data atual, o que significa que o vencimento é daqui 3 dias, enquanto no segundo exemplo apenas foi informado a data de vencimento, nua e crua.

…usabilidade normalmente se refere à simplicidade e facilidade com que uma interface, um programa de computador ou um website pode ser utilizado. Fonte: http://pt.wikipedia.org/wiki/Usabilidade

A informação de que o boleto vence no dia 10 é importante, mas ela seria muito mais informativa se viesse acompanha da dica de que esta data de vencimento acontece somente daqui 3 dias.

Percebam que sempre haverá a comparação com outra data, para poder fornecer este tipo de informação ao usuário, pode ser uma relação da data de nascimento com a data atual, da data de vencimento com a data de pagamento etc.

Sempre que houver uma interface, ou seja, um ponto de contato entre um ser humano e um objeto físico (ex: cafeteira) ou abstrato (ex: software), podemos observar a usabilidade que esse objeto oferece. Fonte: http://usabilidoido.com.br

O Gmail se utiliza desta técnica também, e é muito útil. Quando uma mensagem é aberta, é exibido no canto direito a quantos minutos, horas ou dias a mensagem foi enviada, ao lado da data ou hora de envio.

gmail-fuzzy-date1.jpg

gmail-fuzzy-date2.jpg

Usabilidade é sinônimo de facilidade de uso. Se um produto é fácil de usar, o usuário tem maior produtividade: aprende mais rápido a usar, memoriza as operações e comete menos erros. Fonte: http://usabilidoido.com.br

Desenvolvi uma função em Delphi que permite passar como parâmetro duas datas e retornar a diferença em anos, meses e dias das duas datas. A função tem ainda um terceiro parâmetro opcional que permite definir o nível de comparação, permitindo retornar assim somente os anos/mêses, mêses/dias ou os anos/mêses/dias entre as duas datas.
Adaptando o código, ela poderia ser facilmente convertida para o PHP. Se alguém o fizer, por favor responda, colocando o código-fonte junto.

Segue abaixo o código-fonte da função:

function FuzzyDateBetween(DateOf,DateThen: TDateTime; Nivel: Word=2): string;
var anos, meses, dias, i: integer;
    str, junta: string;
begin
    str := '';
    junta := '';
    EnsureRange(Nivel,1,3);
    for i := 1 to Nivel do
    begin
      anos := YearsBetween(DateOf,DateThen);
      if anos = 0 then
      begin
        meses := MonthsBetween(DateOf,DateThen);
        if meses = 0 then
        begin
          dias := DaysBetween(DateOf,DateThen);
          if dias = 1 then
            str := str + junta + IntToStr(dias) + ' dia'
          else
            str := str + junta + IntToStr(dias) + ' dias';
          break;
        end
        else
        begin
          if meses = 1 then
            str := str + junta + IntToStr(meses) + ' mês'
          else
            str := str + junta + IntToStr(meses) + ' meses';

          junta := ' e ';
          DateOf := incMonth(DateOf, meses);
        end;
      end
      else
      begin
        if anos = 1 then
          str := str + junta + IntToStr(anos) + ' ano'
        else
          str := str + junta + IntToStr(anos) + ' anos';

        junta := ifThen(Nivel=3,', ',' e ');
        DateOf := IncYear(DateOf,anos);
      end;
    end;
    Result := Trim(str);
end;

Alguns exemplos de chamadas a função:

FuzzyDateBetween(’11/09/2001′,’31/01/2008′,1) resulta em “6 anos”
FuzzyDateBetween(’11/09/2001′,’31/01/2008′,2) resulta em “6 anos e 4 meses”
FuzzyDateBetween(’11/09/2001′,’31/01/2008′,3) resulta em “6 anos, 4 meses e 20 dias”

FuzzyDateBetween(’11/09/2007′,’31/01/2008′,1) resulta em “4 meses”
FuzzyDateBetween(’11/09/2007′,’31/01/2008′,2) resulta em “4 meses e 20 dias”
FuzzyDateBetween(’11/09/2007′,’31/01/2008′,3) resulta em “4 meses e 20 dias”

P.S.: Ignorei a conversão da data para não ficar extenso demais, no Delphi o correto seria passar como parâmetro StrToDate(’11/09/2001′), etc.

Na próxima versão da função vou implementar o cálculo de diferença de horas, minutos e segundos.

6 Comentários :
Aurélio V. Schuelter:

Agnaldo, realmente não havia percebido este problema, fiz o teste chamando a função assim FuzzyDateBetween(’01/01/1985′,’01/08/2008′,3) e isso resulta em “2 anos, 6 meses e 1 mês”. Estou um pouco complicado de tempo agora, mas quando resolver este bug, coloco o novo código aqui. Não testei a sua solução, mas obrigado por compartilhar seu código. Um abraço, Aurélio
Agnaldo Alves do Carmo Junior:

Aurélio, segue minha lógica para correção, fiz na pressa mas funcionou. var i,y,anos,meses,dias: integer; str, junta: string; DiaDecode : TAnoMesDia; MatrizOper : array[1..3] of array[1..3] of Integer; begin //CREATED BY AGNALDO 23/07/2008 str := ''; junta := ''; EnsureRange(Nivel,1,3); for i:=1 to Nivel do for y:=1 to Nivel do MatrizOper[i,y]:=0; for i := 1 to Nivel do begin anos := YearsBetween(DateOf,DateThen); MatrizOper[1,i]:=YearsBetween(DateOf,DateThen); if anos = 0 then begin meses := MonthsBetween(DateOf,DateThen); MatrizOper[2,i]:=MonthsBetween(DateOf,DateThen); if meses = 0 then begin dias := DaysBetween(DateOf,DateThen); MatrizOper[3,i]:=DaysBetween(DateOf,DateThen); break; end else begin junta := ' e '; DateOf := incMonth(DateOf, meses); end; end else begin junta := ifThen(Nivel=3,', ',' e '); DateOf := IncYear(DateOf,anos); end; end; DiaDecode.Ano:=0; DiaDecode.Mes:=0; DiaDecode.Dia:=0; for i:=1 to Nivel do begin DiaDecode.Ano:= MatrizOper[1,i]+DiaDecode.Ano; DiaDecode.Mes:= MatrizOper[2,i]+DiaDecode.Mes; DiaDecode.Dia:= MatrizOper[3,i]+DiaDecode.Dia; end; //ESCREVENDO EXTENSO if DiaDecode.Ano = 1 then str := str + junta + IntToStr(DiaDecode.Ano) + ' ano' else str := str + junta + IntToStr(DiaDecode.Ano) + ' anos'; if DiaDecode.Mes = 1 then str := str + junta + IntToStr(DiaDecode.Mes) + ' mês' else str := str + junta + IntToStr(DiaDecode.Mes) + ' meses'; if DiaDecode.Dia = 1 then str := str + junta + IntToStr(DiaDecode.Dia) + ' dia' else str := str + junta + IntToStr(DiaDecode.Dia) + ' dias'; s := Trim(str); Result := DiaDecode;
Agnaldo Alves do Carmo Junior:

Aurélio, foi-me muito útil a sua lógica, no entanto não poderia deixar de observar suas falhas em algumas situações conforme exemplo. Veja o que acontece quando as Datas forem; Entre as dadas 01/01/1985 e incDay('31/07/1987')
Sandro Alencar Fernandes:

Caramba.... Isso sim é produção de conhecimento. Parabéns Aurélio pelo excelente post e Gilmara pelo comentário. Quanto a sugestão em fazer a função em PHP. Desafio o primeiro a postar.
Jonatan da Costa:

Aurélio, muito boa sua colocação. Para complementar, a utilização de mascaras na entrada dos dados também é importante. Abaixo deixo o link com um script para esta finalidade. http://digitalbush.com/projects/masked-input-plugin
Gilmara Elisa:

Pois é, este é um exemplo clássico da qual um detalhe pode fazer toda a diferença no produto final. E na internet, a usabilidade é um fator crucial, ainda mais sabendo que o concorrente está a um clique de distância. Por isso a importância de expor o conteúdo de uma maneira clara e fácil, afinal de contas como disse Felipe Memória no seu livro Design para Internet "Design não são usuários e usuário não são designer."

Escreva um comentário:


O seu endereço de e-mail não será publicado.