#include <stdlib.h>
#include <ctype.h>
#include <time.h>
/*==============================================================================
Analizza la stringa puntata dal parametro s e ne immette le componenti giorno,
mese e anno agli indirizzi puntati rispettivamente da gPtr, mPtr e aPtr.
Il formato considera l'ordine 1) giorno, 2) mese e 3) anno, e ammette separatori
di qualsiasi tipo (vengono infatti ignorati tutti i caratteri non numerici
precedenti o interposti tra i dati significativi).
Ne consegue che, ad esempio...
"jdf24pp12/sfe2006pa" => 24/12/2006
Se l'anno viene omesso, la funzione impiega l'anno tratto dalla data di sistema.
Ad esempio, se oggi e' il 10/7/2017...
"12/5" => 12/5/2017
Se vengono omessi il mese e l'anno, la funzione impiega il mese e l'anno tratti
dalla data di sistema.
Ad esempio, se oggi e' il 10/07/2017...
"12" => 12/7/2017
Se l'anno viene espresso con meno di quattro cifre, la funzione "presume" che un
anno espresso a una o due cifre appartenga al terzo millennio (2000), mentre un
anno espresso a tre cifre appartenga al secondo millennio (1000).
Ad esempio...
"24/12/05" => 24/12/2005
"24/12/905" => 24/12/1905
Se il mese non e' compreso nell'ambito 1-12 la data viene rigettata.
Se il giorno non e' compreso nell'ambito tipico del mese indicato (considerando,
per il mese di febbraio, la bisestilita') la data viene rigettata.
Se la funzione ha successo e la data immessa e' accettata, viene restituito 1.
In caso d'errore o di data inaccettabile, la funzione restituisce 0.
==============================================================================*/
int interpreta_data( const char *s, int *gPtr, int *mPtr, int *aPtr ) {
if( s && *s && gPtr && mPtr && aPtr ) { /* verifica i parametri */
long g, m, a;
long estrai_numero_positivo( const char **s ) {
if( **s ) {
char *fine; /* richiesto da strtol() */
long n; /* il numero letto con strtol() */
/* elimina i caratteri non numerici iniziali */
while( **s && !isdigit(**s) ) ++(*s);
n = strtol( *s, &fine, 10 ); /* tenta di leggere il numero */
if( *s == fine ) return -1; /* -1: errore */
*s = fine; /* aggiorna il puntatore alla stringa */
return n;
} else return -1; /* -1: errore */
}
/* legge i dati numerici dalla stringa */
g = estrai_numero_positivo( &s );
m = estrai_numero_positivo( &s );
a = estrai_numero_positivo( &s );
/* controlla la validita' dei dati letti */
if( g<0 || m<0 || a<0 ) { /* ci sono dati non espressi? */
time_t t;
/* se il giorno non e' espresso, errore */
if( g<0 ) return 0; /* 0: errore */
t = time(NULL); /* occorre leggere la data di sistema */
/* se il mese non e' espresso usa il mese di sistema */
if( m<0 ) m = localtime(&t)->tm_mon+1;
/* se l'anno non e' espresso usa l'anno di sistema */
if( a<0 ) a = localtime(&t)->tm_year+1900;
}
int bisestile( long a ) { /* a: anno */
if( a > 1582 ) /* calendario gregoriano */
return (!(a%400)) || ( (!(a%4)) && (a%100) );
else /* calendario giuliano (non fa la verifica dei 400 anni) */
return (!(a%4)) && (a%100);
}
if( a<100 ) /* se l'anno <100 */
a += 2000; /* presume il terzo millennio (2000) */
else if( a<1000 ) /* se l'anno <100 */
a += 1000; /* presume il secondo millennio (1000) */
switch( m ) { /* verifica gli intervalli dei valori per il giorno */
case 2:
if( g>0 && g<(29+bisestile(a)) )
break;
else return 0; /* 0: errore */
case 4: case 6: case 9: case 11:
if( g>0 && g<31 )
break;
else return 0; /* 0: errore */
default:
if( g>0 && g<32 )
break;
else return 0; /* 0: errore */
}
*gPtr = g; /* i dati sono validi, */
*mPtr = m; /* comunichiamoli al chiamante */
*aPtr = a;
return 1; /* 1: tutto bene */
}
return 0; /* 0: errore */
}