
Eu tenho uma tabela de fatos SQL que é usada para procurar uma data e retornar outra data.
O esquema da tabela é o seguinte:
TABLE date_lookup
(
pk_date DATE,
plus1_months DATE,
plus2_months DATE,
plus3_months DATE
);
UNIQUE INDEX on date_lookup(pk_date);
Eu tenho um arquivo de carregamento (delimitado por barra vertical) contendo datas de 28/01/2012 a 31/03/2014.
A seguir está um exemplo do arquivo de carregamento:
01-28-2012|02-28-2012|03-28-2012|04-28-2012|
01-29-2012|02-29-2012|03-29-2012|04-29-2012|
01-30-2012|02-29-2012|03-30-2012|04-30-2012|
01-31-2012|02-29-2012|03-31-2012|04-30-2012|
...
03-31-2014|04-30-2014|05-31-2014|06-30-2014|
As regras para esta tabela de fatos são:
IF pk_date has more than 28 days in its month
AND plus1, plus2 or plus3_months only has 28, 29 or 30 days
THEN let plus1, plus2 or plus3 equal the last day of the following month.
Minha pergunta é: É possível sed
gerar mais datas após 31/03/2014 seguindo as regras acima para meu arquivo de carregamento, ou devo escrever um programa para fazer isso?
Responder1
Duvido que sed
seja a ferramenta certa para o trabalho, neste caso. Eu acho que você provavelmente vai querer usar awk
, se já estiver familiarizado com awk
, caso contrário, escreva um programa.
Conheço um engenheiro que usou sed
e awk
criou arquivos de entrada MSC/NASTRAN, que tinham requisitos ainda mais rígidos do que os mencionados, mas ele estava bastante familiarizado com as ferramentas, portanto, mensagens de erro enigmáticas e pouco informativas não awk
o incomodavam.
Se você quiser fazer isso com awk
, meu conselho seria pré-processar a entrada para remover '-' e '|' personagens. Escreva o awk
programa em um arquivo separado. Use posições de campo de texto ($1, $2, $3...) e escreva instruções SQL INSERT para a saída. Serão necessárias várias tentativas, então automatize o máximo possível.
Responder2
Embora seja tecnicamente possível fazer aritmética de datas no sed, não é a ferramenta certa para o trabalho. Use uma ferramenta como awk ou perl que tenha aritmética de números inteiros incorporada.
Seu requisito é incomum para manipulações de datas, então você precisará de uma biblioteca avançada de manipulação de datas se não quiser codificar a aritmética de datas. PerlDate::Manip
tem funções como Date_DaysInMonth
.
#!/usr/bin/env perl
use strict;
use warnings;
use Date::Manip;
use List::Util qw(/./);
sub shift_month {
my ($delta, $y, $m, $d) = @_;
$m += $delta;
$y += $m / 12;
$m %= 12;
return ($y, $m, min($d, Date_DaysInMonth($m, $y)));
}
my $next_day = ParseDateDelta("1 day");
my ($cur, $end) = (ParseDate($ARGV[0]), ParseDate($ARGV[1]));
while (Date_Cmp($cur, $end) < 0) {
my @ymd = UnixDate($cur, qw(%Y %m %d));
foreach my $i (0..3) {
printf "%02d-%04d-%02d|", @{[shift_month($i, @ymd)]}[1, 0, 2];
}
$cur = DateCalc($cur, $next_day);
print "\n";
}