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