paulo1205
(usa Ubuntu)
Enviado em 17/05/2020 - 08:44h
paulo1205 escreveu:
Contudo, em outra janela eu estava fazendo uma implementação em Perl do algoritmo, e vi que ela teve resultados interessantes, que confirmam, inclusive, o erro relativamente pequeno mencionado acima. Quando ela ficar pronta, se alguém tiver interesse, posso postar aqui.
Segue a tal implementação. Ela faz contas a partir dos horários de referência para início de cada estação do ano no ano 2000 e da duração média do ano tropical, calculando para os anos subsequentes com base em extrapolação dos valores.
Conferindo com uma tabela impressa, vi que os erros ficaram na faixa de ±1h, o que eu acho que deve dar para o gasto. Afastando muito do ano de referência os erros devem ficar maiores.
#!/usr/bin/perl
# Em resposta a https://www.vivaolinux.com.br/topico/Shell-Script/Script-das-estacoes/
#
# Outros links, que serviram como referência:
# • https://en.wikipedia.org/wiki/Year#Gregorian_calendar
# • https://en.wikipedia.org/wiki/Tropical_year
# • https://en.wikipedia.org/wiki/Axial_precession
# • https://en.wikipedia.org/wiki/Astronomical_nutation
# • https://www.timeanddate.com/calendar/seasons.html?year=2000&n=161
use strict;
use POSIX;
use vars qw($T0 $TEM $TSJ $TES $TSD $SECONDS_IN_YEAR);
BEGIN {
# Altera temporariamente o fuso-horário para poder fixar UTC como referência.
my $saved_timezone=$ENV{TZ};
$ENV{TZ}="UTC";
tzset();
# Tempo de referência: 2000/01/01 00:00:00 UTC.
$T0=mktime(0, 0, 0, 1, 0, 100);
# Tempos relativos das efemérides no ano 2000 (todos os relógios em UTC).
$TEM=mktime(0, 35, 7, 20, 2, 100)-$T0; # Equinócio de março (2000/03/20 07:35)
$TSJ=mktime(0, 47, 1, 21, 5, 100)-$T0; # Solstício de junho (2000/06/21 01:47)
$TES=mktime(0, 27, 17, 22, 8, 100)-$T0; # Equinócio de setembro (2000/09/22 17:27)
$TSD=mktime(0, 37, 17, 21, 11, 100)-$T0; # Solstício de dezembro (2000/12/21 17:37)
# Duração do ano tropical médio no ano 2000.
#$days_in_year=365.2421896698;
$SECONDS_IN_YEAR=86400*365.2421896698;
# Restaura fuso-horário padrão.
if(defined($saved_timezone)){
$ENV{TZ}=$saved_timezone;
}
else{
delete($ENV{TZ});
}
tzset();
}
# Função que informa a estação aproximada, assumindo as referências do ano
# 2000 para as estações em cada ano. Isso tem erros, por causa dos movimentos
# de precessão (mais ou menos previsível) e nutação (mensurável, mas pouco
# previsível) da Terra e movimentos do próprio Sol, mas esse erro, dentro de
# intervalo pequeno de anos (por exemplo, menor que uns 50 anos) deve ficar
# dentro da faixa de ±60min.
#
# A função recebe o timestamp da hora de interesse (nº de segundos decorridos
# desde 1970/01/01 00:00:00 UTC, que é o formato padrão do UNIX e do C).
sub tell_season ($) {
my ($t_user)=@_;
my ($n_years, $year_offset);
$n_years=($t_user-$T0)/$SECONDS_IN_YEAR;
$year_offset=($n_years-floor($n_years))*$SECONDS_IN_YEAR;
return "verão" if $year_offset<$TEM || $year_offset>=$TSD;
return "outono" if $year_offset<$TSJ;
return "inverno" if $year_offset<$TES;
return "primavera";
}
# Mostra o modo de uso do programa.
sub usage (\*) {
my ($out)=@_;
print $out <<EOM;
Modo de uso: $0 [-H] ( -t | ( -p | -v | -o | -i ) AAAA | [data] )
-h | --help Mostra esta tela de ajuda.
-H Imprime a hora, além da data.
-t Imprime tabela com início de cada estação desde 2000 até 2050.
-p AAAA Mostra início da primavera no ano AAAA.
-v AAAA Mostra início do verão no ano AAAA.
-o AAAA Mostra início do outono no ano AAAA.
-i AAAA Mostra início do inverno no ano AAAA.
data Mostra a estação na data informada (default: data corrente).
Caso o campo "data" seja usado, ele deve estar no formato
[AAAA/]mm/dd[ HH:MM[:SS]]. Se o ano for omitido, assume-se o corrente.
Se a hora for omitida, assume-se 12:00. Se os segundos forem omitidos,
assume-se 00.
Para evitar grandes erros de precisão, os anos informados devem estar entre
2000 e 2050.
EOM
}
#################### PROGRAMA PRINCIPAL ####################
my ($table, $season, $year, $ts_fmt, $date);
$ts_fmt="%m/%d";
my @args=@ARGV;
my $arg;
while(defined($arg=shift(@args))){
if($arg eq "-h" || $arg eq "--help"){
usage(*STDOUT);
exit(0);
}
if($arg eq "-H"){
$ts_fmt="%m/%d %H:%M";
next;
}
if(!$table && !$season && !$date){
if($arg eq "-t"){
$table=1;
next;
}
if($arg eq "-p"){
$season=$TES;
}
elsif($arg eq "-v"){
$season=$TSD;
}
elsif($arg eq "-o"){
$season=$TEM;
}
elsif($arg eq "-i"){
$season=$TSJ;
}
if($season){
if(!($year=shift(@args)) || $year=~/\D/){
usage(*STDERR);
exit(1);
}
$year-=2000;
next;
}
if($arg=~/^((\d+)\/)?(0?[1-9]|1[012])\/(0?[1-9]|[12]\d|3[01])(\s+([01]?\d|2[0-3]):([0-5]?\d)(:([0-5]?\d|6[01]))?)?$/){
my ($sec, $min, $hour, $day, $mon, $year);
$sec=defined($9)? $9: 0;
$min=defined($5)? $7: 0;
$hour=defined($5)? $6: 12;
$day=$4;
$mon=$3-1;
$year=defined($1)? $2-1900: (localtime(time()))[5];
$date=mktime($sec, $min, $hour, $day, $mon, $year);
next;
}
}
usage(*STDERR);
exit(1);
}
if($table){
for(
my ($to, $ti, $tp, $tv)=($TEM+$T0, $TSJ+$T0, $TES+$T0, $TSD+$T0);
$to<=$T0+50*$SECONDS_IN_YEAR;
$to+=$SECONDS_IN_YEAR, $ti+=$SECONDS_IN_YEAR, $tp+=$SECONDS_IN_YEAR, $tv+=$SECONDS_IN_YEAR
){
print
strftime("%Y: $ts_fmt", localtime($to)),
strftime(" | $ts_fmt", localtime($ti)),
strftime(" | $ts_fmt", localtime($tp)),
strftime(" | $ts_fmt\n", localtime($tv))
;
}
}
elsif($season){
print strftime("%Y/$ts_fmt\n", localtime($T0+$season+$year*$SECONDS_IN_YEAR));
}
else{
$date=time() unless defined($date);
print strftime("%Y/$ts_fmt: ", localtime($date)), tell_season($date), "\n";
}
exit(0);
... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)