1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
# ----------------------------------------------------------------------------
# Faz calculos com datas e/ou converte data->num e num->data.
# Que dia vai ser daqui 45 dias? Quantos dias ha entre duas datas? zzdata!
# Quando chamada com apenas um parametro funciona como conversor de data
# para numero inteiro (N dias passados desde Epoch) e vice-versa.
# A zzdata pode subtrair, ou somar meses e anos tambem. Eh so especificar!
# Obs.: Leva em conta os anos bissextos (Epoch = 01/01/1970, editavel)
# Opcoes:
# data|num data inicial.
# +|- operacao a realizar (adicao|subtracao).
# D|M|Y unidade em operacao com numero (D=dia, M=mes, Y=ano).
# Uso: zzdata2 data|num [+|- data|num [D|M|Y]]
# Ex.: zzdata2 22/12/1999 + 69
# zzdata2 hoje - 5
# zzdata2 01/03/2000 - 11/11/1999
# zzdata2 hoje - dd/mm/aaaa <---- use sua data de nascimento
# zzdata2 01/03/2000 - 1 M # subtrai 1 mes. resp: 01/02/2000
# zzdata2 30/03/2008 - 1 M # resp: 19/02/2008 (ano bissexto)
#
# Autor: Aurélio Marinho Jargas, www.aurelio.net, modificada por Lauro de Sá
# Desde: 2010-05-26
# Versão: 20091010
# Licença: GPLv2
# ----------------------------------------------------------------------------
# DESATIVADA: 2011-05-19 Funcionalidades implementadas na zzdata original.
zzdata2 ()
{
zzzz -h data2 $1 && return
local yyyy mm dd dias_ano data dias i n y op muda_ano
local epoch=1970
local primeira_data=1
local dias_mes='31 28 31 30 31 30 31 31 30 31 30 31'
local data1=$1
local operacao=$2
local data2=$3
local n1=$data1
local n2=$data2
local tipo=$4
# Verificacao dos parametros
# Alterado o numero de parametros para ate 4.
# Porem, para manter a compatibilidade com versoes anteriores, aceita-se 3.
# Ou seja, para somar ou subtrair dias nao precisa informar "d".
[ $# -eq 3 -o $# -eq 1 -o $# -eq 4 ] || { zztool uso data2; return 1; }
# Esse bloco gigante define $n1 e $n2 baseado nas datas $data1 e $data2.
# A data eh transformada em um numero inteiro (dias desde $epoch).
# Exemplo: 27/07/2007 -> 13721
# Este eh numero usado para fazer os calculos.
for data in $data1 $data2
do
dias=0 # Guarda o total que ira para $n1 e $n2
# Atalhos uteis para o dia atual
if [ "$data" = 'hoje' -o "$data" = 'today' ]
then
# Qual a data de hoje?
data=$(date +%d/%m/%Y)
[ "$primeira_data" ] && data1=$data || data2=$data
else
# Valida o formato da data
if ! ( zztool testa_data "$data" || zztool testa_numero "$data" )
then
echo "Data invalida '$data', deve ser dd/mm/aaaa"
return 1
fi
fi
# Se tem /, entao e uma data e deve ser transformado em numero
if zztool grep_var / "$data"
then
n=1
y=$epoch
yyyy=${data##*/}
mm=${data#*/}
mm=${mm%/*}
dd=${data%%/*}
# Retira o zero dos dias e meses menores que 10
mm=${mm#0}
dd=${dd#0}
# Define qual sera a operacao: adicao ou subtracao
op=+
[ $yyyy -lt $epoch ] && op=-
# Ano -> dias
while :
do
# Sim, os anos bissextos sao levados em conta!
dias_ano=365
zztool testa_ano_bissexto ${y} && dias_ano=366
# Vai somando (ou subtraindo) ate chegar no ano corrente
[ $y -eq $yyyy ] && break
dias=$((dias $op dias_ano))
y=$((y $op 1))
done
# Meses -> dias
for i in $dias_mes
do
[ $n -eq $mm ] && break
n=$((n+1))
# Fevereiro de ano bissexto tem 29 dias
[ $dias_ano -eq 366 -a $i -eq 28 ] && i=29
dias=$((dias+$i))
done
# Somando os dias da data aos anos+meses ja contados (-1)
dias=$((dias+dd-1))
[ "$primeira_data" ] && n1=$dias || n2=$dias
else
# Esta parte eh responsavel pela subtracao de meses ou anos.
# Para isto, o usuario deve informar o terceiro parametro
# como um numero.
if [ "$primeira_data" != 1 ] ; then
# Determinando o tipo de operacao (dia, mes, ou ano)
case "${tipo}" in
"m" | "M" | "y" | "Y")
data2=`zzdata "$n1"`
dd=`echo "$data2" | cut -c1-2`
mm=`echo "$data2" | cut -c4-5`
yyyy=`echo "$data2" | cut -c7-10`
i=1
while [ $i -le $n2 ]
do
case "${tipo}" in
"m" | "M")
muda_ano=1
[ $mm -eq 1 -a "$operacao" = "-" ] && muda_ano=0 mm="12"
[ $mm -eq 12 -a "$operacao" = "+" ] && muda_ano=0 mm="01"
if [ "$muda_ano" = 1 ] ; then
mm=`expr $mm $operacao 1`
[ $mm -lt 10 ] && mm="0$mm"
else
yyyy=`expr $yyyy $operacao 1`
fi
;;
"y" | "Y") yyyy=`expr $yyyy $operacao 1`;;
esac
i=$((i+1))
done
# Verifica mes de fevereiro.
if [ $mm -eq 2 -a $dd -gt 28 ] ; then
zztool testa_ano_bissexto "$yyyy" && dd="29" || dd="28"
fi
# Verifica se o dia 31 existe no mes.
if [ $dd -eq 31 ] ; then
case "${mm}" in
"04" | "06" | "09" | "11") dd="30";;
esac
fi
data1="$dd/$mm/$yyyy"
n1=`zzdata "$data1"`
data2=0
n2=0
;;
esac
fi
fi
primeira_data=
done
# Agora que ambas as datas sao numeros inteiros, a conta e feita
dias=$(($n1 $operacao $n2))
# Se as duas datas foram informadas como dd/mm/aaaa,
# o resultado e o proprio numero de dias, entao terminamos.
if [ "${data1##??/*}" = "${data2##??/*}" ]
then
echo $dias
return
fi
# Como nao caimos no IF anterior, entao o resultado sera uma data.
# e preciso converter o numero inteiro para dd/mm/aaaa.
y=$epoch
mm=1
dd=$((dias+1))
# Dias -> Ano
while :
do
# Novamente, o ano bissexto e levado em conta
dias_ano=365
zztool testa_ano_bissexto ${y} && dias_ano=366
# Vai descontando os dias de cada ano para saber quantos anos cabem
[ $dd -le $dias_ano ] && break
dd=$((dd-dias_ano))
y=$((y+1))
done
yyyy=$y
# Dias -> mes
for i in $dias_mes
do
# Fevereiro de ano bissexto tem 29 dias
[ $dias_ano -eq 366 -a $i -eq 28 ] && i=29
# Calcula quantos meses cabem nos dias que sobraram
[ $dd -le $i ] && break
dd=$((dd-i))
mm=$((mm+1))
done
# Restaura o zero dos meses menores que 10
[ $dd -le 9 ] && dd=0$dd
[ $mm -le 9 ] && mm=0$mm
# E finalmente mostra o resultado em formato de data
echo $dd/$mm/$yyyy
}
|