Età - Compleanni

Gli argomenti di questa pagina

  • Calcolo età
  • Calcolo per compleanno
  • Calcoli per età in anni, mesi, giorni ed età media dei contatti
  • Compleanni recenti (prima versione con solo MYSQL)
  • Compleanni recenti (seconda versione con solo MYSQL)
  • Compleanni recenti con MYSQL e PHP

Calcolo età

Ci sono svariati metodi per calcolare una età in anni e qui di seguito ne ho scelti due.
Il primo esempio si basa su semplici calcoli matematici su due date.
Il secondo esempio usa la funzione MYSQL TIMESTAMPDIFF() che restituisce la differenza fra due date. Questa funzione accetta un terzo argomento che indica quale unità di misura deve essere usata nel mostrare il risultato restituito.

Mostra gli anni dei miei contatti

Questi due esempi li mostro affiancati per poter studiare più agevolmente il resultset ottenuto. Queste le due query

Calcolo basato sulla semplice differenza fra i tre elementi visualizzati ed isolati separatamente nella tabella qui sopra Calcolo basato sulla funzione TIMESTAMPDIFF() che, tra i suoi argomenti, ammette l'unità di tempo che si deve restituire eseguendo la differenza tra due date.
1
2
3
4
5
6
7
8
9
10
<?php
$Query 
"SELECT cognome, nome, 
DATE_FORMAT( data_nascita, '%d-%m-%Y' ) AS nato, 
(DATE_FORMAT( CURDATE( ) , '%Y' ) 
- DATE_FORMAT( data_nascita, '%Y' ) 
- DATE_FORMAT( CURDATE( ) , '00-%m-%d' )) AS eta
FROM sql_agenda
ORDER BY eta DESC
"
;
?>
1
2
3
4
5
6
7
8
<?php
$Query 
"SELECT cognome, nome, 
DATE_FORMAT( data_nascita, '%d-%m-%Y' ) AS nato, 
TIMESTAMPDIFF(YEAR, data_nascita, CURDATE( )) AS eta
FROM sql_agenda
ORDER BY eta DESC
"
;
?>

Nei due resultset mostrati qui di seguito si notano delle differenze solo in alcuni record. Facendo riferimento alla data odierna 29.05.2022 notiamo che il primo resultset non è affidabile quando la data in esame ha il mese superiore a quello della data corrente.
In questi casi gli anni restituiti risultano di un anno superiore a quelli effettivi.

103 record trovati
20 record visualizzati
cognome nome nato eta
pinco pallino 01-01-1934 88
Uberti Federico 12-01-1947 75
Forlini Andrea 24-12-1948 74
giulio cesare 10-04-1950 72
Vitulano Vincenzo 15-02-1951 71
Deiana Alberino 05-05-1951 71
Biancarosa Francesca 05-09-1956 66
Zuna Clotilde 15-08-1961 61
Costanza Antonietta 11-11-1966 56
Daniel Nicola 21-02-1977 45
Pasotti Alessio 14-11-1987 35
Calvi Giovanni 26-07-1987 35
Poggi Giuseppe 25-01-1987 35
Borsotti Mirella 19-07-1987 35
Odelli Giuseppe 16-07-1987 35
Edelvisi Maurizio 02-07-1987 35
Cancellieri Marco 16-07-1987 35
Querio Angela 30-04-1987 35
Bazzotti Pietro 17-07-1987 35
Curti Oreste 26-06-1988 34
... ... ... ...
103 record trovati
20 record visualizzati
cognome nome nato eta
pinco pallino 01-01-1934 88
Uberti Federico 12-01-1947 75
Forlini Andrea 24-12-1948 73
giulio cesare 10-04-1950 72
Vitulano Vincenzo 15-02-1951 71
Deiana Alberino 05-05-1951 71
Biancarosa Francesca 05-09-1956 65
Zuna Clotilde 15-08-1961 60
Costanza Antonietta 11-11-1966 55
Daniel Nicola 21-02-1977 45
Poggi Giuseppe 25-01-1987 35
Querio Angela 30-04-1987 35
Borsotti Mirella 19-07-1987 34
Cecire Valentina 02-05-1988 34
Calvi Giovanni 26-07-1987 34
Odelli Giuseppe 16-07-1987 34
Bazzotti Pietro 17-07-1987 34
Edelvisi Maurizio 02-07-1987 34
Cancellieri Marco 16-07-1987 34
Ravizzola Stefano 16-04-1988 34
... ... ... ...

Qui di segiito mostro i passaggi usati per eseguire i calcoli sulle date per calcolare l'età conoscendo la data di nascita.

Mostra i passaggi eseguiti per il calcolo matematico

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$Query 
"SELECT 
DATE_FORMAT( data_nascita, '%d-%m-%Y' ) AS nato, 
DATE_FORMAT( CURDATE( ) , '%Y' ) AS AnnoAdesso,  
DATE_FORMAT( data_nascita, '%Y' ) AS AnnoStorico, 
DATE_FORMAT( CURDATE( ) , '00-%m-%d' ) AS MeseGiornoAdesso, 
DATE_FORMAT( CURDATE( ) , '%Y' ) 
- DATE_FORMAT( data_nascita, '%Y' ) 
- DATE_FORMAT( CURDATE( ) , '00-%m-%d' ) AS eta 
FROM sql_agenda 
ORDER BY eta DESC
"
;
?>
103 record trovati
20 record visualizzati
nato AnnoAdesso AnnoStorico MeseGiornoAdesso eta
01-01-1934 2022 1934 00-05-29 88
12-01-1947 2022 1947 00-05-29 75
24-12-1948 2022 1948 00-05-29 74
10-04-1950 2022 1950 00-05-29 72
15-02-1951 2022 1951 00-05-29 71
05-05-1951 2022 1951 00-05-29 71
05-09-1956 2022 1956 00-05-29 66
15-08-1961 2022 1961 00-05-29 61
11-11-1966 2022 1966 00-05-29 56
21-02-1977 2022 1977 00-05-29 45
14-11-1987 2022 1987 00-05-29 35
26-07-1987 2022 1987 00-05-29 35
25-01-1987 2022 1987 00-05-29 35
19-07-1987 2022 1987 00-05-29 35
16-07-1987 2022 1987 00-05-29 35
02-07-1987 2022 1987 00-05-29 35
16-07-1987 2022 1987 00-05-29 35
30-04-1987 2022 1987 00-05-29 35
17-07-1987 2022 1987 00-05-29 35
26-06-1988 2022 1988 00-05-29 34
... ... ... ... ...

Calcolo per compleanno

La seguente Query è la più semplice ma la più diretta. E' nella clausola WHERE che vengono confrontati il giorno corrente col giorno della tabella ed il mese corrente col mese della tabella.
In questa Query non viene usata nessuna funzione specifica, ma nella clausola WHERE vengono confrontati il giorno corrente col giorno letta dalla tabella e il mese corrente con quello letto dalla tabella.

Controlla se oggi qualcuno dei miei contatti compie gli anni

1
2
3
4
5
6
7
8
<?php
$Query 
"SELECT cognome, nome, 
DATE_FORMAT( data_nascita, '%d-%m-%Y' ) AS nato  
FROM sql_agenda 
WHERE DAYOFMONTH(NOW()) = DAYOFMONTH(data_nascita) 
AND MONTH(NOW()) = MONTH(data_nascita)
"
;
?>
0 record trovati
Oggi, 29.05.2022, nessun compleanno

Calcoli per età in anni, mesi, giorni ed età media dei contatti

Qui di seguito un paio di esempi per eseguire dei calcoli complessi in MYSQL

Calcola l'età dei contatti in anni, mesi, giorni

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$Query 
"SELECT cognome, nome, DATE_FORMAT( data_nascita, '%d-%m-%Y' ) AS nato,
    CONCAT( YEAR( CURRENT_DATE ) - YEAR( data_nascita ) - ( DATE_FORMAT( CURRENT_DATE, '%m-%d' ) < DATE_FORMAT( data_nascita, '%m-%d' ) ) , ' a ',
    IF( MONTH( CURRENT_DATE ) - MONTH( data_nascita ) >=0, 
        MONTH( CURRENT_DATE ) - MONTH( data_nascita ) - ( DAY( CURRENT_DATE ) < DAY( data_nascita ) ) , 
        12 + MONTH( CURRENT_DATE ) - MONTH( data_nascita ) - ( DAY( CURRENT_DATE ) < DAY( data_nascita ) ) ) , ' m ',
    IF( DAY( CURRENT_DATE ) - DAY( data_nascita ) >=0, 
        DAY( CURRENT_DATE ) - DAY( data_nascita ) , 
        IF( DAY( data_nascita ) > DAY( LAST_DAY( CURRENT_DATE - INTERVAL 1 MONTH ) ) , 
            DAY( CURRENT_DATE ) , 
            DAY( LAST_DAY( CURRENT_DATE - INTERVAL 1 MONTH ) ) - DAY( data_nascita ) + DAY( CURRENT_DATE ) ) ) , ' d' ) AS Eta
FROM sql_agenda
ORDER BY data_nascita 
"
;
?>
103 record trovati
20 record visualizzati
cognome nome nato Eta
pinco pallino 01-01-1934 88 a 4 m 28 d
Uberti Federico 12-01-1947 75 a 4 m 17 d
Forlini Andrea 24-12-1948 73 a 5 m 5 d
giulio cesare 10-04-1950 72 a 1 m 19 d
Vitulano Vincenzo 15-02-1951 71 a 3 m 14 d
Deiana Alberino 05-05-1951 71 a 0 m 24 d
Biancarosa Francesca 05-09-1956 65 a 8 m 24 d
Zuna Clotilde 15-08-1961 60 a 9 m 14 d
Costanza Antonietta 11-11-1966 55 a 6 m 18 d
Daniel Nicola 21-02-1977 45 a 3 m 8 d
Poggi Giuseppe 25-01-1987 35 a 4 m 4 d
Querio Angela 30-04-1987 35 a 0 m 29 d
Edelvisi Maurizio 02-07-1987 34 a 10 m 27 d
Odelli Giuseppe 16-07-1987 34 a 10 m 13 d
Cancellieri Marco 16-07-1987 34 a 10 m 13 d
Bazzotti Pietro 17-07-1987 34 a 10 m 12 d
Borsotti Mirella 19-07-1987 34 a 10 m 10 d
Calvi Giovanni 26-07-1987 34 a 10 m 3 d
Pasotti Alessio 14-11-1987 34 a 6 m 15 d
Margarino Ambrogio 21-03-1988 34 a 2 m 8 d
... ... ... ...

Qui di seguito un paio di esempi per eseguire dei calcoli complessi in MYSQL

Calcola età media dei contatti

1
2
3
4
5
6
7
8
9
10
<?php
$Query 
"SELECT AVG( ( 12 * ( YEAR( CURRENT_DATE ) - YEAR( data_nascita ) - (
    DATE_FORMAT( CURRENT_DATE, '%m-%d' ) < DATE_FORMAT( data_nascita, '%m-%d' ) ) ) + 
        IF( MONTH( CURRENT_DATE ) - MONTH( data_nascita ) >= 0, 
            MONTH( CURRENT_DATE ) - MONTH( data_nascita ) - ( DAY( CURRENT_DATE ) < DAY( data_nascita ) ) , 
            12 + MONTH( CURRENT_DATE ) - MONTH( data_nascita ) - ( DAY( CURRENT_DATE ) < DAY( data_nascita ) ) ) ) /12
) AS EtaMedia
FROM sql_agenda
"
;
?>
1 record letti
EtaMedia
27.63673139

Compleanni recenti (prima versione con solo MYSQL)

Un po' più complesso è la ricerca dei compleanni recenti, ossia quelli già avvenuti e quelli che verranno in un periodo di tempo prestabilito.
In questa Query usiamo la funzione DATEDIFF() che dovrebbe restituire la differenza in giorni tra le date in tabella e la data corrente.
Ma a noi non interessa la differenza in giorni tra la data di nascita e la data corrente che è poco indicativa e poco interessante. Quel che ci interessa è ottenere un numero di giorni che intercorrono tra il compleanno e la data corrente.
Per ottenere un numero ragionevole di giorni trascorsi o mancanti per un determinato compleanno è necessario trasformare le date in tabella sostituendo il loro anno con l'anno della data corrente. Questo compito lo assolve l'istruzione complessa che troviamo sia nella SELECT per creare il campo 'diff' sia nella WHERE:

DATE_FORMAT(data_nascita + INTERVAL YEAR(CURDATE()) - YEAR(data_nascita) YEAR,'%Y-%m-%d')

Questa istruzione trasforma le date della tabella in:
2022-03-03
2022-03-20
2022-04-05
ecc.
Con questa nuova situazione usando la funzione DATEDIFF() tra la data corrente e la nuova data così trasformata si ottengono i giorni trascorsi o mancanti per un determinato compleanno e non i giorni trascorsi dalla data di nascita. Questa la Query:

Mostra i compleanni recenti, passati e futuri, entro un intervallo indicato: primo metodo

1
2
3
4
5
6
7
8
9
<?php
$Query 
"SELECT DATE_FORMAT(data_nascita,'%d-%m-%Y') AS nato, 
DATE_FORMAT(data_nascita + INTERVAL YEAR(CURDATE()) - YEAR(data_nascita) YEAR,'%Y-%m-%d') AS solo_per_test, 
DATEDIFF(CURDATE(), DATE_FORMAT(data_nascita + INTERVAL YEAR(CURDATE()) - YEAR(data_nascita) YEAR,'%Y-%m-%d')) as diff 
FROM sql_agenda 
WHERE DATEDIFF(CURDATE(), DATE_FORMAT(data_nascita + INTERVAL YEAR(CURDATE()) - YEAR(data_nascita) YEAR,'%Y-%m-%d')) BETWEEN -30 AND 30  
ORDER BY diff DESC
"
;
?>

Questo è il risultato che si ottiene oggi che è 29.05.2022.
I numeri che si leggono nella colonna diff, perciò, sono i giorni. Quelli positivi sono giorni trascorsi, quelli negativi sono giorni mancanti. Se il giorno del compleanno coincide col giorno della data corrente, nella colonna diff si otterrà 0 (zero).

22 record letti
nato solo_per_test diff
30-04-1987 2022-04-30 29
02-05-2003 2022-05-02 27
02-05-2009 2022-05-02 27
02-05-1988 2022-05-02 27
05-05-1951 2022-05-05 24
08-05-2009 2022-05-08 21
08-05-2009 2022-05-08 21
10-05-1995 2022-05-10 19
10-05-2009 2022-05-10 19
11-05-1988 2022-05-11 18
13-05-2009 2022-05-13 16
15-05-2009 2022-05-15 14
18-05-1988 2022-05-18 11
21-05-2009 2022-05-21 8
21-05-1999 2022-05-21 8
22-05-1993 2022-05-22 7
06-06-1998 2022-06-06 -8
06-06-2004 2022-06-06 -8
06-06-2005 2022-06-06 -8
22-06-1994 2022-06-22 -24
26-06-1997 2022-06-26 -28
26-06-1988 2022-06-26 -28

Compleanni recenti (seconda versione con solo MYSQL)

Con questa seconda Query viene eseguita la stessa operazione ma, anzichè sommare e poi sottrarre lo stesso valore di anno come è stato fatto sopra usando più funzioni MYSQL, la data da confrontare con la data corrente viene creata col solo concatenamento usando la funzione CONCAT() come visibile nell''esempio qui sotto.
Questa soluzione mi è stata fornita nel forum 'html.it'.

Mostra i compleanni recenti, passati e futuri, entro un intervallo indicato: secondo metodo

1
2
3
4
5
6
7
8
9
<?php
$Query 
"SELECT DATE_FORMAT(data_nascita,'%d-%m-%Y') AS nato, 
CONCAT(YEAR(NOW()), DATE_FORMAT(data_nascita, '-%m-%d')) AS solo_per_test, 
DATEDIFF(CURDATE(), CONCAT(YEAR(NOW()), DATE_FORMAT(data_nascita, '-%m-%d'))) as diff 
FROM sql_agenda 
WHERE DATEDIFF(CURDATE(), CONCAT(YEAR(NOW()), DATE_FORMAT(data_nascita, '-%m-%d'))) BETWEEN -30 AND 30  
ORDER BY diff DESC
"
;
?>

Questo è il risultato che si ottiene oggi che è 29.05.2022.
Il resultset che si ottiene con questa seconda Query è identico a quello mostrato nell'esempio precedente. Infatti la colonna 'solo_per_test' sulla quale viene eseguita la funzione DATEDIFF() è identica a quella del primo esempio.

22 record letti
nato solo_per_test diff
30-04-1987 2022-04-30 29
02-05-2003 2022-05-02 27
02-05-2009 2022-05-02 27
02-05-1988 2022-05-02 27
05-05-1951 2022-05-05 24
08-05-2009 2022-05-08 21
08-05-2009 2022-05-08 21
10-05-1995 2022-05-10 19
10-05-2009 2022-05-10 19
11-05-1988 2022-05-11 18
13-05-2009 2022-05-13 16
15-05-2009 2022-05-15 14
18-05-1988 2022-05-18 11
21-05-2009 2022-05-21 8
21-05-1999 2022-05-21 8
22-05-1993 2022-05-22 7
06-06-1998 2022-06-06 -8
06-06-2004 2022-06-06 -8
06-06-2005 2022-06-06 -8
22-06-1994 2022-06-22 -24
26-06-1997 2022-06-26 -28
26-06-1988 2022-06-26 -28

Compleanni recenti con MYSQL e PHP

In quest'altro esempio uso un altro approccio mi avvalgo della collaborazione tra MYSQL e PHP.
La Query fatta al DB si limita ad estrarre solo frazioni delle date in tabella che poi vengono manipolate dal PHP per ottenere i giorni passati o mancanti dal compleanno alla data corrente.

La Query e lo script PHP per eseguire la Query e leggere il resultset sono lievemente diversi da quelli appena usati.
In questo caso la Query restituisce al PHP il giorno, mese, anno della data di nascita e quelli della data corrente. Sarà poi compito del PHP eseguire i suoi calcoli.

Restituisci il giorno, mese, anno della data di nascita e quelli della data corrente per calcolare i compleanni recenti col PHP

1
2
3
4
5
6
7
8
9
10
11
<?php
$Query 
"SELECT id, cognome, nome, 
DATE_FORMAT(data_nascita,'%d-%m-%Y') AS nato,
DATE_FORMAT(data_nascita, '%d') as giorno_nasc,
DATE_FORMAT(data_nascita, '%m') as mese_nasc,
DATE_FORMAT(CURDATE(), '%d') as giorno_corr,
DATE_FORMAT(CURDATE(), '%m') as mese_corr,
DATE_FORMAT(CURDATE(), '%Y') as anno_corr
FROM sql_agenda 
"
;
?>

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
<?php
include ('res/db_login.php');
if (!
$link mysql_connect($Host$User$Password)) {
    echo 
mysql_error() . "<br />\n";
} else {
    if (!
mysql_select_db($DBName$link)) {
        echo 
mysql_error() . "<br />\n";
    } else {
        
mysql_set_charset("utf8");
        
$result mysql_query($Query);
        if (!
$result) {
            echo 
mysql_error() . "<br />\n";
        } else {
            
$numfields mysql_num_fields($result);
            
$fields = array();
            for (
$i=0$i $numfields$i++) {
                
$fields[] = mysql_field_name($result$i);
            }
            
$diff 30;
            echo 
"Ricerca compleanni in intervallo di +/- " $diff " giorni<br />\n";
            echo 
"<table class=\"tabella_it\">\n";
            echo 
"<tr>\n";
            echo 
"<th>ID</th>\n";
            echo 
"<th>cognome</th>\n";
            echo 
"<th>nome</th>\n";
            echo 
"<th>data nscita</th>\n";
            echo 
"<th>Compleanni vicini</th>\n";
            echo 
"</tr>\n";
            
$error TRUE;
            
//    ################################################################################
            
while ($row mysql_fetch_array($result)) {
                
$time1 mktime(0,0,0,$row['mese_nasc'],$row['giorno_nasc'],$row['anno_corr']);
                
$time2 mktime(0,0,0,$row['mese_corr'],$row['giorno_corr'],$row['anno_corr']);
                
$secDif $time1-$time2;
                
$date_diff  floor(($secDif 60 60 24));
                
$mess "";
                if (
$date_diff && $date_diff $diff) {
                    
$mess "Prossimo compleanno tra " $date_diff " giorni";
                } elseif (
$date_diff && $date_diff $diff*-1) {
                    
$mess "Compleanno fatto da " $date_diff*-" giorni";
                } elseif (
$date_diff == 0) {
                    
$mess "Il compleanno è oggi";
                }
                if (
$mess != "") {
                    
$error FALSE;
                    echo 
"<tr>\n";
                    echo 
"<td>" $row['id'] . "</td>\n";
                    echo 
"<td>" $row['cognome'] . "</td>\n";
                    echo 
"<td>" $row['nome'] . "</td>\n";
                    echo 
"<td>" $row['nato'] . "</td>\n";
                    echo 
"<td>" $mess "</td>\n";
                    echo 
"</tr>\n";
                }
            }
            
//    ################################################################################
            
if ($error) {
                echo 
"<tr>\n";
                echo 
"<td colspan=\"5\">Nessun compleanno recente</td>\n";
                echo 
"</tr>\n";
            }
            echo 
"</table>\n";
        }
    }
}
mysql_close ($link); 
?>

Per ottenere un risultato più ordinato è necessario lavorare maggiormente nel codice PHP.

Ricerca compleanni in intervallo di +/- 30 giorni
ID cognome nome data nscita Compleanni vicini
4 Di Maggio Mario 21-05-2009 Compleanno fatto da 8 giorni
11 Curti Oreste 26-06-1988 Prossimo compleanno tra 28 giorni
13 Franchinotti Anna 10-05-2009 Compleanno fatto da 19 giorni
18 Scicchitano Pierluigi 02-05-2003 Compleanno fatto da 27 giorni
20 Traina Giovanni 06-06-2005 Prossimo compleanno tra 8 giorni
29 Sarmento Morena 21-05-1999 Compleanno fatto da 8 giorni
31 Limone Maria 02-05-2009 Compleanno fatto da 27 giorni
36 Bialetti Vincenzo 22-06-1994 Prossimo compleanno tra 24 giorni
39 Pasquone Maria 08-05-2009 Compleanno fatto da 21 giorni
43 Cecire Valentina 02-05-1988 Compleanno fatto da 27 giorni
45 Righello Armando 06-06-1998 Prossimo compleanno tra 8 giorni
46 Rosmunda Marina 13-05-2009 Compleanno fatto da 16 giorni
54 Serva Clemente 22-05-1993 Compleanno fatto da 7 giorni
55 Brunetti Pierpaolo 08-05-2009 Compleanno fatto da 21 giorni
61 Omede Rina 26-06-1997 Prossimo compleanno tra 28 giorni
70 Salazar Ornella 06-06-2004 Prossimo compleanno tra 8 giorni
75 Deiana Alberino 05-05-1951 Compleanno fatto da 24 giorni
78 Alama Ornella 11-05-1988 Compleanno fatto da 18 giorni
94 Querio Angela 30-04-1987 Compleanno fatto da 29 giorni
95 Baldoni Serena 18-05-1988 Compleanno fatto da 11 giorni
98 Lomo Dalia 15-05-2009 Compleanno fatto da 14 giorni
101 Oristano Gaby Bo 10-05-1995 Compleanno fatto da 19 giorni

 

 



settore tecnico il sito di lorettabweb il Forum di sostegno
il forum il forum il forum