O Ano 19100

time localtime gmtime Time::HiRes DateTime

Esta parte do Tutorial Perl explicará o uso do tempo no perl.

O Perl possui uma função interna chamada time() que irá retornar um número de 10 dígitos representando o número de segundos passados desde a "época" demarcada pela data 1 de Janeiro de 1970 na maioria dos sistemas operacionais.

$t = time();         # retorna um número parecido com este: 1021924103

Você pode usar essa função como uma etiqueta de tempo por exemplo, para verificar tempos percorridos. Você pode salvar os segundos no seu código por invocar time() e então ao chamar time() novamente. E então, comparando os resultados obtidos nas duas chamadas:

my $t = time();
# várias linhas de código
say 'Tempo percorrido: ', (time() - $t);

localtime

Há uma outra função chamada localtime() que pega aquele número de 10 dígitos, que representa o tempo, e convertê-lo em algo mais legível:

my $then = localtime($t);  # retorna um texto parecido com este       Thu Feb 30 14:15:53 1998

Na verdade a função nem precisa de um argumento. Se chamada sem argumentos, ela iŕa invocar a função time() por si só.

my $now = localtime();    # retorna um texto com o tempo local

Você pode salvar as etiquetas de tempo várias vezes durante a execução de um programa, geradas pela função time(), e depois você pode usar os valores para calcular o tempo percorrido, ou então transformar os valores de tempo em algo mais legível.

O outro localtime

O que acontece se nós chamarmos a mesma função localtime($t) como acima mas dessa vez direcionando o seu retorno a um array? Você esperaria o mesmo texto como descrito acima, na primeira posição do array?

my @then = localtime($t);

O array será preenchido com os seguintes valores:

53 15 14 30 1 98 4 61 0

O que são esses números estranhos? Você deve estar se perguntando. Se você observar com mais cuidado, irá perceber que o primeiro valor armazena os segundos, seguido pelos minutos e então pelas horas e alguns outros números representando o mesmo momento no tempo. A lista completa segue abaixo:

my ($sec ,$min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$sec   - segundos (0-59)
$min   - minutos (0-59)
$hour  - horas  (0-23)
$mday  - dia do mês (1-31)
$mon   - mês (0-11) - 0 é Janeiro, 11 é Dezembro.
$year  - ANO - 1900
$wday  - dia da semana (0-6), 0 é Domingo, 6 é Sábado.
$yday  - dia do ano (0-364 ou 0-365 em ano bissexto).
$isdst - horário de verão - Verdadeiro se for horário de verão pela configuração do seu computador. Falso caso não seja.

Note que no campo representando o mês 0 significa Janeiro e 11 significa Dezembro. Nos campos representando o dia da semana 0 significa Domingo e 6 significa Sábado.

Por outro lado o campo representando o dia do mês vai de 1 até 28, 29 ou 30 dependendo do mês.

O mais problemático de todos é o campo representando o ano. Pode facilmente levar ao bug Y2K

O bug do milênio

Em meados de 1998 as pessoas utilizavam o $year como sendo 98 e queria imprimir 1998, então escreviam 19$year. Isso funcionava bem ara eles, até mesmo em 1999, mas quando o ano 2000 veio, e 19$year se tornou 2000-1900 = 100, o seu texto bem formatado se tornou 19100.

Foi essa a origem do ano 19100. Foi exatamente assim que as pessoas criaram código com o tal bug do milênio

Se elas tivessem lido a documentação, elas teriam escrito:

1900 + $year

que é a forma correta de se ter o número real de nossa data segundo o Calendário Gregoriano. O formato de calendário mais comum e utilizado ao redor do mundo.

gmtime

O Perl possui ainda uma função chamada gmtime() que faz as mesmas coisas que localtime(), mas fornece o tempo em Greenwich, Londres. (O $isdst é sempre 0 neste caso).

Como o tempo realmente funciona?

Normalmente o relógio de hardware de seu computador deve estar configurado para GMT (Greenwich Mean Time) (ou então UTC which is more or less the same).

Seu sistema operacional (Windows, Linux, Mac OSX, Unix, etc) deve ter noção sobre o fuso horário configurada por você, e se o horário de verão está sendo aplicado. localtime() leva em consideração esses valores enquanto gmtime() apenas usa os valores "brutos" do relógio do hardware.

Tempo de alta precisão

A função interna time() retorna o tempo atual em segundos. Isso signiica que não é capaz de medir períodos mais curtos de tempo do que um segundo. Se você precisar de medidas de alta precisão, existe um módulo chamado Time::HiRes que pode prover um substituto para a função time().

use strict;
use warnings;
use 5.010;

use Time::HiRes qw(time);

say time;

E o resultado é:

1021924103.58673

DateTime

Enquanto que as funções acima podem lhe fornecer formas básicas de manipulação de datas e do tempo, provavelmente qualquer coisa além do mais simples pode ser realizado através do módulo do CPAN DateTime.

Nós iremos aprender sobre ele mais tarde.

Noção do contexto

Todas as considerações acima são importantes, mas há ainda um aspecto muito importante dessa aula. Nós sutilmente passamos sobre essa questão importante do Perl, onde a função localtime() é apenas um exemplo.

Se você observar no exemplo acima, você irá perceber que a função localtime() de alguma forma sabe se o valor de retorno será atribuído a uma escalar ou um array, para que então o valor de retorno possa ser legível ou então representado na forma de um número de 9 dígitos.

Essa é uma característica geral do Perl 5. Uma característica muito importante e nós iremos aprender muito mais sobre ela. A mensagem importante a ser passada aqui é entender que em muitas situações, o Perl é sensível ao contexto.

Otras páginas

Perl tutorial

Author

Gabor Szabo (szabgab) Gabor Szabo