[SP-pm] Perl e horário de verão

Geraldo Netto geraldonetto at gmail.com
Fri Feb 28 09:49:14 PST 2014


Opa!

Boas dicas Buss e Blabos!!!
Fico devendo a pizza! :)

Vou melhorar aqui o que eu já tenho e vamos conversando!

Sobre outros módulos, eu realmente não quero tentar instalar e etc
porque eu sei que eu não vou conseguir mexer nesse servidor

mesmo que o POC funcione, acho difícil que alguém me autorize a mexer
(instalar um módulo) em um servidor sem suporte do fornecedor (tenho
um dinossauro de Unix que mexe nele quando as coisas explodem e olhe
lá...)

E mesmo com a possível dificuldade de manipulação de datas com a api do posix
eu prefiro ela que ter que calcular as coisas todas em shell, eheheh :)

Além do mais, eu acho que eu posso pegar alguns atalhos no sentido de
limpar a forma como eu to desenhando esse script

Outros incrementos virão! :)


Força e Honra Senhores!

Geraldo Netto
Sapere Aude => Non dvcor, dvco
São Paulo, Brasil, -3gmt
site: http://exdev.sf.net/


2014-02-28 14:28 GMT-03:00 Blabos de Blebe <blabos at gmail.com>:
> Eu tava escrevendo uma resposta, mas o buss foi mais rápido então cortando
> os overlaps, com bastante licença poética:
>
> Primeiro as masturbações estilísticas:
>
>> #!/usr/bin/perl
>
> Eu prefiro usar:
>
> #!/usr/bin/env perl
>
> Porque, se o script for usado num ambiente onde espera-se outro perl que não
> o do /usr/bin, como num perlbrew por exemplo, você não fica com a versão
> antiga do perl hardcoded.
>
> Mas no seu caso, não acredito que vá ocorrer esse caso de uso, então pode
> ficar como está, numa boa. Não está errado.
>
>> use strict;
>> use warnings;
>
> Bom garoto!
>
> Ambas as pragmas são mandatórias, caso você esteja escrevendo algo
> minimamente decente. Tem gente que gosta também do:
>
> use diagnostics;
>
> que te dá ainda mais informação em caso de problemas.
>
>> use POSIX;
>
> Aqui, a explicação longa é longa (call @garu), mas resumidamente, você está
> importando alguns símbolos desnecessários automaticamente pro namespace
> corrente.
>
> Isso é completamente irrelevante pro seu caso, mas vc poderia fazer assim:
>
> use POSIX ();
>
> que significa, adicione o módulo POSIX mas não importe nenhum símbolo. Ou
> ainda:
>
> use POSIX qw{ strftime }
>
> que significa, adicione o módulo POSIX e importe somente o símbolo (função)
> strftime. Nesse caso, ao usar a sub, vc não precisaria mais prefixar com
> POSIX::
>
> Do meu ponto de vista, tanto faz:
>
> use POSIX ();
> POSIX::strftime();
>
> ou
>
> use POSIX qw( strftime );
> strftime();
>
>
> Eu também prefiro nomear_funcoes_em_minusculas_com_underscore do que
> comCameCaseIgualAoJava.
>
>
> ***
>
>
> Sobre a sua dúvida na captura e tratamento dos parâmetros tem algumas
> sutiliezas que podem levar a erros.
>
> *** Primeiramente, acessar elementos versus acessar slice de um array
>
> A forma de acessar um escalar dentro de um array é indicando que ele é um
> escalar, e dizendo qual índice você quer, ou seja, para acessar o terceiro
> elemento do array foo, temos:
>
> my $elemento = $foo[ 2 ];
>
> que significa mais ou menos, pegue o escalar ($) que está no array foo na
> posição 3 (índice 2).
>
> Quando você faz:
>
> $a = @_[3];
>
> Você está pedindo, me dê um array (@) contendo os elementos que estão "nos
> índices" 3 do array _. Isso é um slice, que normalmente é usado pra pegar
> pedaços de array.
>
> No seu caso, como você tá pedidndo uma lista com apenas um elemento, também
> funciona mas experimente testar o seguinte:
>
> my $a = @_[1,2];
>
>
> Dito isso, quando vc faz:
>
> $foo = @_[0], a menos que você saiba exatamente o que está fazendo, isso
> está errado. Não é questão de estilo aqui. O correto seria:
>
> $foo = $_[0];  ## Me dê o escalar que está no índice zero do array _
>
>
> *** Acessando parâmetros de funções
>
> Os parâmetros de funções são passados no array _, ou seja, @_.
>
> Ele faz aliasing das variáveis passadas, ou seja, ao lidar com $_[]
> diretamente, você pode causar efeitos colaterais externos inesperados.
>
> Por exemplo, nesse oneliner apenas para efeitos didáticos:
>
> perl  -e 'sub foo { $_[0]++ } $a=1; foo($a); print $a . $/'
>
> Por isso é boa prática criar uma cópia local dos argumentos dentro da
> função. Isso pode ser feito de varias maneiras, conforme o caso:
>
>
> ## Crie uma cópia do @_ chamada @args;
> my @args = @_;
>
>
> ## Crie uma lista com dois escalares, atribua os dois primeiros elementos do
> @_ a cada um deles e descarte o resto;
> my ( $first, $second ) = @_;
>
>
> ## Crie uma lista contendo dois escalares, um array, guarde os dois
> primeiros elementos de @_ nos escalares e o resto no array @tail
> my ( $first, $second, @tail ) = @_
>
>
> ## Remova o primeiro elemento de @_ e coloque-o no escalar criado
> my $first = shift;   ## Equivalente a my $first = shift @_;
> my $second = shift;   # Pegue o "novo primeiro" elemento de @_
>
> A vesão com shift remove definitivamente o primeiro elemento do array. O
> segundo elemento passa a ser o primeiro, e assim sucessivamente. O tamanho
> do array é reduzido em 1.
>
> Minhas fontes não confiáveis apontam que a versão com shift é menos
> eficiente. Por favor me corrijam quem estiver com as fontes corretas.
>
> Eu prefiro usar as duas primeiras formas. my @args = @_;  ou my ( $first,
> $second ) = @_;
>
> ***
>
> Conforme o buss apontou, separe uma instrução por linha:
>
> sub calcularDeslocamentoAno {
>     my ( $ano ) = @_;
>
>     die 'ano invalido'
>       unless defined $ano;
>
>     return $ano > 99 ? $ano - 1900 : $ano;
> }
>
> Veja como fica mais claro pro próximo cara que for dar manutenção nisso.
>
> ***
>
> Use qx ao invés de ` pra invocar comandos externos
>
> sub calcularDiaInicioHorarioVerao {
>    my $dia_inicio = qx{ cal 10 2013 | tail -4 | head -1 | cut -d' ' -f7 };
> }
>
> Considerações finais:
>
> 1) Seu código está até bem razoável. Compartimentarizado em funções que só
> fazem uma coisa. Ele está claro no que ele pretende fazer. Isso é muito bom.
> Té melhor que muito programador "experiente" que tem por aí.
>
> 2) Tem uns requintes de Perl 4, mas fazendo os ajustes indicados, que não
> são nada complicados, seu código vai rejuvenecer uns 20 anos!!!
>
> 3) Não é porque você executa comandos do Shell que o seu código Perl fica
> ruim. Nada disso. É parte da linguagem e perfeitamente normal,
> principalmente, porque você deixa bem claro o que você está fazendo e de
> forma organizada. Acessar o shell continua sendo elegante.
>
> Feio é fazer algazarra.
>
> Existem módulos pra rodar comandos externos, com mil funcionalidades, mas
> acredito que não são necessários no seu caso.
>
> 4) DateTime, pode se mais indicado do que calcular datas na mão, mas ele não
> é "Core" (http://perldoc.perl.org/corelist.html), portanto pode ser difícil
> de instalar no seu sistema com ambiente restrito. Você tem que medir se o
> custo de instalar vale o benefício que ele fornece ou ainda se o risco do
> seu código falhar é alto ou baixo. Isso é uma análise sua.
>
> Eventualmente eu pelo menos comentaria no código que o DateTime poderia ser
> uma solução mais adequada. Vai que o ambiente muda no futuro e ele possa ser
> instalado mais facilmente.
>
> 5) Tente escrever testes automatizados que validem a sua aplicação.
>
>
>
> Bom, espero que tenhamos te ajduado. Qualquer coisa avisa.
>
>
> []'s
>
>
>
>
>
>
>
>
>
> 2014-02-28 13:31 GMT-03:00 Bruno Buss <bruno.buss at gmail.com>:
>
>> Oi Geraldo,
>>
>> Respostas inline :-)
>>
>>
>> 2014-02-28 11:59 GMT-03:00 Geraldo Netto <geraldonetto at gmail.com>:
>>
>>> Bom Dia Pessoal!
>>>
>>> Consegui evoluir no código com a api do posix mesmo
>>> crio as datas com POSIX::strftime
>>> e calculo o horário de verão pegando a saida do comando cal no shell
>>>
>>> yep, eu sei que é feito, mas resolve o meu problema de um jeito rápido...
>>> por hora, a idéia é só gerar o "okay" da gerencia p/ matar umas 4
>>> versões shell que fazem o mesmo trabalho, mas precisam de alguns
>>> parâmetros diferentes e alguma intervenção humana especificamente no
>>> período de horário de verão
>>
>>
>> Thumbs up por resolver o problema! :D
>>
>> Entretanto, o que a galera quer passar aqui, e' que mesmo que você
>> realmente acredite que esta resolvendo seu problema de forma simples e
>> rápida agora... não esta'. Ou melhor, o jeito rápido agora *provavelmente*
>> ira' te causar uma baita dor de cabeça soon(tm).
>>
>> Tente utilizar o DateTime, e' uma solução ordens de grandeza melhor e não
>> e' tao difícil assim :-)
>>
>>>
>>>
>>> a minha dúvida é primária, suponho...
>>> mas eu não entendi o porque usar o shift
>>> se eu posso verificar com o defined() se o @_[<número>] está definido?
>>
>>
>> O shift serve para voce retirar e retornar o 1o elemento da lista de
>> argumentos/parâmetros que foi passada para sua função.
>>
>> E' uma das formas idiomáticas de se fazer isso, a outra seria "my ($v_a,
>> $v_b, $v_c) = @_;".
>> Pessoalmente prefiro com shift :-)
>>
>>>
>>>
>>> Aceito sugestões e Mais uma vez, Valeu mesmo pela força! :P
>>>
>>>
>>> BTW, código todo a seguir:
>>>
>>> #!/usr/bin/perl
>>>
>>> use strict;
>>> use warnings;
>>>
>>> use POSIX;
>>>
>>>
>>> # a inicia a data em 1900 entao, se for passado 95 => 1995
>>> sub calcularDeslocamentoAno {
>>>     die "ano invalido" unless defined(@_[0]) && return ($_[0] > 99 ?
>>> $_[0] - 1900 : $_[0]);
>>> }
>>
>>
>> Então para você o ano 50 e' o mesmo que o ano 1950? :P
>> Ou se eu passar para você o ano 1800, ele retorna -100.
>>
>> Outra coisa, você realmente não precisa colocar o return na mesma linha do
>> die...
>> Por exemplo:
>>
>> sub calcularDeslocamentoAno{
>>     my $ano = shift;
>>
>>     #Rejeitando coisas que nossa funcao nao sabe tratar.
>>     die "ano invalido" unless defined $ano && $ano >= 1900;
>>
>>     return $ano - 1900;
>> }
>>
>>>
>>>
>>> sub criarData {
>>>     die "parametros invalidos" unless (defined(@_[0]) &&
>>> defined(@_[1]) && defined(@_[2]));
>>>     #Usage: POSIX::strftime(fmt,             sec, min, hour, mday,
>>> mon, year, wday = -1, yday = -1, isdst = -1)
>>>     return POSIX::strftime("%Y,%m,%d", 0, 0, 0, @_[0], (@_[1] -1),
>>> &calcularDeslocamentoAno(@_[2]), 0, 0);
>>> }
>>
>>
>> Idealmente você estaria tratando:
>> * Se o 1o parâmetro e' um dia que esta' no mês (posso tentar usar stftime
>> passando o dia 31 de Fev?)
>> * Se o 1o parâmetro e' um dia valido at all (dia igual a 44 por exemplo).
>> * Lembrar que o dia e o mês são 0-based, ou seja Janeiro => 0, Fev => 1,
>> etc.
>> ...
>>
>> Voce tambem poderia fazer:
>> sub criarData {
>>     my ($dia, $mes, $ano) = @_;
>>     die "parametros invalidos" unless defined $dia   &&
>>                                                      defined $mes &&
>>                                                      defined $ano;
>>     ...
>> }
>>
>> Detalhe: O DateTime tem funções de formatação de data tao boas quanto ;-)
>>
>>>
>>>
>>> sub calcularDiaInicioHorarioVerao {
>>>     my $dia_inicio = `cal 10 2013 | tail -4 | head -1 | cut -d' ' -f7`;
>>> }
>>>
>>> sub calcularDiaFimHorarioVerao {
>>>     my $dia_fim = `cal 2 2014 | tail -4 | head -1 | cut -d' ' -f7`;
>>> }
>>
>>
>> Alguém já disse em substituir isso tudo por DateTime? :P
>>
>>>
>>>
>>> sub  trim {
>>>     my $s = shift;
>>>     $s =~ s/^\s+|\s+$//g;
>>>     return $s;
>>> }
>>>
>>> print &criarData(2, 5, 2014);
>>> print &trim($dia_inicio);
>>> print &trim($dia_fim);
>>
>>
>> Não sei exatamente qual Perl você ta usando, mas acredito que não e'
>> necessário prefixar as chamadas de funções com &. Inclusive isso e'
>> considerado não legal hoje em dia :-)
>>
>> [ ]'s
>>
>> PS: Utilize uma ferramenta tipo pastebin ou Gist (do GitHub) para copiar e
>> enviar codigos em listas de e-mail :-)
>>
>>>
>>>
>>> Geraldo Netto
>>> Sapere Aude => Non dvcor, dvco
>>> São Paulo, Brasil, -3gmt
>>> site: http://exdev.sf.net/
>>>
>>> 2014-02-26 23:41 GMT-03:00 Geraldo Netto <geraldonetto at gmail.com>:
>>> > Opa!
>>> >
>>> > Tudo okay Pessoal?
>>> >
>>> > Eu sou o Geraldo, um ghost reader da SPPM (e algumas outras PMs)
>>> > e eu ando trabalhando vagarosamente num projetinho
>>> > que eu dependo de verificação do horário de verão
>>> >
>>> > A idéia é separar o ano em 3 partes:
>>> >
>>> > fim do horário de verão (terceiro domingo de fevereiro)
>>> > fora do horário de verão
>>> > início do horário de verão (terceiro sábado de fevereiro)
>>> >
>>> > E baseado nisso, lançar um shell que vai receber o timezone, data de
>>> > início e de fim
>>> > p/ fazer a coleta de dados pelo hp openview (comando ovpmbatch)
>>> >
>>> > Só que...
>>> > -eu tenho um servidor tru64 (sem suporte)
>>> > -rodando perl 5.8 (2002 pelo o que o version diz...)
>>> > -sem sudo/root/possibilidade de instalação de pacotes de terceiros
>>> > -<inclua-aqui-todas-as-limitações-que-vocês-imaginarem-de-infra>
>>> > -meu "core business" é análise de desempenho de software,
>>> > então o código não pode ser muito "perlish"
>>> > porque alguém pode precisar dar manutenção depois de mim
>>> >
>>> > Embora eu ainda não tenha código real (só comecei a brincar)
>>> > Eu estou pensando em ir com a api do posix, especificamente a
>>> > função/método strftime
>>> >
>>> > Eventualmente vocês teriam alguma sugestão?
>>> >
>>> >
>>> > Grande Abraço!
>>> >
>>> > Geraldo Netto
>>> > Sapere Aude => Non dvcor, dvco
>>> > São Paulo, Brasil, -3gmt
>>> > site: http://exdev.sf.net/
>>> =begin disclaimer
>>>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>>  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>>> =end disclaimer
>>
>>
>>
>>
>> --
>> Bruno C. Buss
>> http://www.brunobuss.net
>>
>>
>> 2014-02-28 11:59 GMT-03:00 Geraldo Netto <geraldonetto at gmail.com>:
>>
>>> Bom Dia Pessoal!
>>>
>>> Consegui evoluir no código com a api do posix mesmo
>>> crio as datas com POSIX::strftime
>>> e calculo o horário de verão pegando a saida do comando cal no shell
>>>
>>> yep, eu sei que é feito, mas resolve o meu problema de um jeito rápido...
>>> por hora, a idéia é só gerar o "okay" da gerencia p/ matar umas 4
>>> versões shell que fazem o mesmo trabalho, mas precisam de alguns
>>> parâmetros diferentes e alguma intervenção humana especificamente no
>>> período de horário de verão
>>>
>>> a minha dúvida é primária, suponho...
>>> mas eu não entendi o porque usar o shift
>>> se eu posso verificar com o defined() se o @_[<número>] está definido?
>>>
>>> Aceito sugestões e Mais uma vez, Valeu mesmo pela força! :P
>>>
>>>
>>> BTW, código todo a seguir:
>>>
>>> #!/usr/bin/perl
>>>
>>> use strict;
>>> use warnings;
>>>
>>> use POSIX;
>>>
>>>
>>> # a inicia a data em 1900 entao, se for passado 95 => 1995
>>> sub calcularDeslocamentoAno {
>>>     die "ano invalido" unless defined(@_[0]) && return ($_[0] > 99 ?
>>> $_[0] - 1900 : $_[0]);
>>> }
>>>
>>> sub criarData {
>>>     die "parametros invalidos" unless (defined(@_[0]) &&
>>> defined(@_[1]) && defined(@_[2]));
>>>     #Usage: POSIX::strftime(fmt,             sec, min, hour, mday,
>>> mon, year, wday = -1, yday = -1, isdst = -1)
>>>     return POSIX::strftime("%Y,%m,%d", 0, 0, 0, @_[0], (@_[1] -1),
>>> &calcularDeslocamentoAno(@_[2]), 0, 0);
>>> }
>>>
>>> sub calcularDiaInicioHorarioVerao {
>>>     my $dia_inicio = `cal 10 2013 | tail -4 | head -1 | cut -d' ' -f7`;
>>> }
>>>
>>> sub calcularDiaFimHorarioVerao {
>>>     my $dia_fim = `cal 2 2014 | tail -4 | head -1 | cut -d' ' -f7`;
>>> }
>>>
>>> sub  trim {
>>>     my $s = shift;
>>>     $s =~ s/^\s+|\s+$//g;
>>>     return $s;
>>> }
>>>
>>> print &criarData(2, 5, 2014);
>>> print &trim($dia_inicio);
>>> print &trim($dia_fim);
>>>
>>> Geraldo Netto
>>> Sapere Aude => Non dvcor, dvco
>>> São Paulo, Brasil, -3gmt
>>> site: http://exdev.sf.net/
>>>
>>> 2014-02-26 23:41 GMT-03:00 Geraldo Netto <geraldonetto at gmail.com>:
>>> > Opa!
>>> >
>>> > Tudo okay Pessoal?
>>> >
>>> > Eu sou o Geraldo, um ghost reader da SPPM (e algumas outras PMs)
>>> > e eu ando trabalhando vagarosamente num projetinho
>>> > que eu dependo de verificação do horário de verão
>>> >
>>> > A idéia é separar o ano em 3 partes:
>>> >
>>> > fim do horário de verão (terceiro domingo de fevereiro)
>>> > fora do horário de verão
>>> > início do horário de verão (terceiro sábado de fevereiro)
>>> >
>>> > E baseado nisso, lançar um shell que vai receber o timezone, data de
>>> > início e de fim
>>> > p/ fazer a coleta de dados pelo hp openview (comando ovpmbatch)
>>> >
>>> > Só que...
>>> > -eu tenho um servidor tru64 (sem suporte)
>>> > -rodando perl 5.8 (2002 pelo o que o version diz...)
>>> > -sem sudo/root/possibilidade de instalação de pacotes de terceiros
>>> > -<inclua-aqui-todas-as-limitações-que-vocês-imaginarem-de-infra>
>>> > -meu "core business" é análise de desempenho de software,
>>> > então o código não pode ser muito "perlish"
>>> > porque alguém pode precisar dar manutenção depois de mim
>>> >
>>> > Embora eu ainda não tenha código real (só comecei a brincar)
>>> > Eu estou pensando em ir com a api do posix, especificamente a
>>> > função/método strftime
>>> >
>>> > Eventualmente vocês teriam alguma sugestão?
>>> >
>>> >
>>> > Grande Abraço!
>>> >
>>> > Geraldo Netto
>>> > Sapere Aude => Non dvcor, dvco
>>> > São Paulo, Brasil, -3gmt
>>> > site: http://exdev.sf.net/
>>> =begin disclaimer
>>>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>>  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>>> =end disclaimer
>>
>>
>>
>>
>> --
>> Bruno C. Buss
>> http://www.brunobuss.net
>>
>> =begin disclaimer
>>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>> =end disclaimer
>>
>
>
> =begin disclaimer
>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>  SaoPaulo-pm mailing list: SaoPaulo-pm at pm.org
>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
> =end disclaimer
>


More information about the SaoPaulo-pm mailing list