Creazione di un timestamp
È utile l’utilizzo del timestamp, ovvero la formattazione della data in una modalità particolarmente sintetica e ordinata per cifre più significative, cioè YYYYMMDDHHMMSS
TIMESTAMP=`date '+%Y%m%d%H%M%S'`
Epoch della data attuale
Ovvero il numero di secondi trascorsi dalla mezzanotte del 1° gennaio 1970, può essere generato in diversi modi, a seconda della versione del comando date
date +%s
date -u '+%S+%M*60+%H*3600+(%j-1)*86400+(%Y-1970)*31536000+\
((%Y-1969)/4)*86400'|bc
Oppure in perl:
/usr/bin/perl -e 'printf "%d\n", time;'
E anche in millisecondi
/usr/bin/perl -e 'use Time::HiRes qw(time);my $t = time;printf "%d%03d\n",$t,($t-int($t))*1000;'
Calcolo dell’epoch di una data
Esempio di calcolo dell’epoch del “01/01/2012 12.41.12”:
HOUR=12
MIN=41
SEC=11
DAY=01
MONTH=01
YEAR=2012
set -A MONTHS 0 0 31 59 90 120 151 181 212 243 273 304 334 365
echo "b=0;if(${MONTH}>2) if (${YEAR}%4==0) b=1; \
${SEC}+${MIN}*60+${HOUR}*3600+(${MONTHS[${MONTH}]} + ${DAY} + b-1)*86400+\
(${YEAR}-1970)*31536000+((${YEAR}-1969)/4)*86400" | bc
Conversione dell’epoch in data
Esempio di calcolo della data corrispondente all’epoch 1325421671:
echo 1325421671 |\
awk '{
e=$1;
split("0,365,730,1096,1461", ydq,",");
split("0,31,59,90,120,151,181,212,243,273,304,334,365",mml,",");
tot_m=int(e/60);sec=e-tot_m*60;
tot_h=int(tot_m/60);min=tot_m-tot_h*60;
tot_d=int(tot_h/24);hours=tot_h-tot_d*24;
tot_q=int(tot_d/1461);dqua=tot_d-tot_q*1461;
base_y=1970 + tot_q * 4;
for(i=0;i<4;i++){
if (dqua<ydq[i+1])break;
}
year=base_y + i - 1;
dyear=dqua - ydq[i] + 1;
leap=(year % 4)?0:1;
mmlp=0;
for(i=1;i<=12;i++)
{
mmll=(i>=2)?mml[i+1]+leap:mml[i+1];
if(mmll>=dyear){
month=i;
day=dyear-mmlp;
break;
}
mmlp=mmll;
}
printf "%02d/%02d/%04d %02d:%02d:%02d\n",day,month,year,hours,min,sec;
}'
Numeri di giorni dall’Inizio del Tempo Unix
DD=02
MM=05
YY=2012
set -A MONTHS 0 0 31 59 90 120 151 181 212 243 273 304 334 365
echo "b=0;
if(${MM}>2) if (${YY}%4==0) b=1;
(${MONTHS[${MM}]} + ${DD} + b-1)+(${YY}-1970)*365+((${YY}-1969)/4)" | bc
e inversamente, un valore calcolato con il comando precedente si trasforma di formato data con
echo 20000 |\
awk '{
e=$1;
split("0,365,730,1096,1461", ydq,",");
split("0,31,59,90,120,151,181,212,243,273,304,334,365",mml,",");
tot_d=e
tot_q=int(tot_d/1461);dqua=tot_d-tot_q*1461;
base_y=1970 + tot_q * 4;
for(i=0;i<4;i++){
if (dqua<ydq[i+1])break;
}
year=base_y + i - 1;
dyear=dqua - ydq[i] + 1;
leap=(year % 4)?0:1;
mmlp=0;
for(i=1;i<=12;i++)
{
mmll=(i>=2)?mml[i+1]+leap:mml[i+1];
if(mmll>=dyear){
month=i;
day=dyear-mmlp;
break;
}
mmlp=mmll;
}
printf "%02d/%02d/%04d\n",day,month,year;
}'
04/10/2024
Calcolo della Pasqua
Questo script implementa l’algoritmo per il calcolo della Pasqua Cristiana secondo il calendario gregoriano. Le quantità 24 e 5 in grassetto nelle formule valgono per gli anni compresi tra il 1900 e il 2099.
echo 2012 | awk '{
y=$1;
a=y%19;
b=y%4;
c=y%7;
d=(19*a + 24)%30;
e=(2*b + 4*c + 6*d + 5)%7;
if ((d + e) < 10){
h=3;
k=(d + e + 22);
}
else{
h=4;
k=(d + e - 9);
if (k==26) k=25;
if (k==25 && d==28 && e==6 && a>10) k=18;
}
printf "%02d/%02d/%04d\n",k,h,y;
}'
Calcolo del giorno precedente
daybefore()
{
DD=$( echo $1 | cut -c 1-2 )
MM=$( echo $1 | cut -c 3-4 )
YY=$( echo $1 | cut -c 5-8 )
LEAP=0
BIS=$(echo "$YY % 4"| bc)
test $BIS -eq 0 && LEAP=1
set -A MML 31 31 28 31 30 31 30 31 31 30 31 30 31
MML[2]=$(( LEAP + 28 ))
ND=$(( DD - 1 ))
NM=$MM
NY=$YY
test $ND -eq 0 && NM=$(( MM - 1 ))
test $ND -eq 0 && ND=${MML[NM]}
test $NM -eq 0 && NY=$((NY - 1 ))
test $NM -eq 0 && NM=12
printf "%02d%02d%04d\n" $ND $NM $NY
}
La funzione daybefore calcola il giorno precedente alla data passata come parametro
daybefore 01032012
Data di ieri:
daybefore $(date +%d%m%Y)
Calcolo del giorno della settimana
Viene restituito 0 per Domenica, 1 per Lunedì ecc.
Per la data odierna:
date +%u
Per una data qualunque:
DATA='02/05/2012'
read DD MM YY < <( echo $DATA | sed 'sx/x xg' )
echo "(6 - $( cal $MM $YY | awk 'NR==3' |wc -w ) + ( $DD % 7 ) ) %7" | bc
Validazione di una data
Sfruttando il comando cal è possibile verificare se una data è valida.
$ myDATE=22/07/2015
$ echo $myDATE |sed 's/\// /g'| xargs cal >/dev/null 2>/dev/null
$ echo $?
0
Nel caso di data non valida restituisce un codice di ritorno diverso da zero.
$ myDATE=33/07/2015
$ echo $myDATE |sed 's/\// /g'| xargs cal >/dev/null 2>/dev/null
$ echo $?
123