calendar - Lavorare con le date

Scopo Il modulo calendar implementa le classi per lavorare con le date per gestire valori orientati ad anno/mese/settimana
Versione Python 1.4, con aggionamenti in 2.5

Il modulo calendar definisce la classe Calendar, che incapsula i calcoli per valori tipo le date delle settimane in certo mese od anno. Inoltre, le classi TextCalendar e HTMLCalendar possono produrre un output preformattato.

Esempi Di Formattazione

Un esempio molto semplice, che produce un output con testo formattato per questo mese con TextCalendar, usa il metodo prmonth()

import calendar

c = calendar.TextCalendar(calendar.SUNDAY)
c.prmonth(2007, 7)

E' stato detto a TextCalendar di iniziare le settimane dalla domenica, secondo la convenzione americana. Il comportamento predefinito è di iniziare con il lunedì, secondo la convenzione europea.

L'output risulta così:

$ python calendar_textcalendar.py
     July 2007
Su Mo Tu We Th Fr Sa
 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

L'output HTML per lo stesso periodo di tempo è leggermente diverso, visto che non c'è un metodo prmonth().

import calendar

c = calendar.HTMLCalendar(calendar.SUNDAY)
print c.formatmonth(2007, 7)

L'output interpretato sembra pressochè il medesimo, ma incapsulato nei tag HTML. Si può anche notare che ogni cella della tabella ha un attributo di classe che corrisponde al giorno della settimana.

$ python calendar_htmlcalendar.py
<table border="0" cellpadding="0" cellspacing="0" class="month">
<tr><th colspan="7" class="month">July 2007</th></tr>
<tr><th class="sun">Sun</th><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th></tr>
<tr><td class="sun">1</td><td class="mon">2</td><td class="tue">3</td><td class="wed">4</td><td class="thu">5</td><td class="fri">6</td><td class="sat">7</td></tr>
<tr><td class="sun">8</td><td class="mon">9</td><td class="tue">10</td><td class="wed">11</td><td class="thu">12</td><td class="fri">13</td><td class="sat">14</td></tr>
<tr><td class="sun">15</td><td class="mon">16</td><td class="tue">17</td><td class="wed">18</td><td class="thu">19</td><td class="fri">20</td><td class="sat">21</td></tr>
<tr><td class="sun">22</td><td class="mon">23</td><td class="tue">24</td><td class="wed">25</td><td class="thu">26</td><td class="fri">27</td><td class="sat">28</td></tr>
<tr><td class="sun">29</td><td class="mon">30</td><td class="tue">31</td><td class="noday">&nbsp;</td><td class="noday">&nbsp;</td><td class="noday">&nbsp;</td><td class="noday">&nbsp;</td></tr>
</table>

Se serve produrre un output in un formato diverso da quelli predefiniti, si può usare calendar per calcolare le date ed organizzare i valori in intervalli di settimane e mesi, e successivamente iterare con i valori autonomamente. I metodi weekheader(), monthcalendar() e yeardays2calendar() sono particolarmente utili per questo tipo di lavoro.

La chiamata di yeardays2calendar() fornisce una sequenza di liste di "righe di mesi". Ogni lista comprende i mesi come un'altra lista di settimane. Le settimane sono rappresentate in liste di tuple composte dal numero del giorno del mese (1-31) e dal numero della settimana (0-6). I giorni che si trovano al di fuori del mese hanno un il numero 0.

import calendar
import pprint

pprint.pprint(calendar.Calendar(calendar.SUNDAY).yeardays2calendar(2007, 2))

Chiamando yeardays2calendar(2007,2) si ottengono i dati per il 2007, disposti su due mesi per riga.

$ python calendar_yeardays2calendar.py
[[[[(0, 6), (1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5)],
   [(7, 6), (8, 0), (9, 1), (10, 2), (11, 3), (12, 4), (13, 5)],
   [(14, 6), (15, 0), (16, 1), (17, 2), (18, 3), (19, 4), (20, 5)],
   [(21, 6), (22, 0), (23, 1), (24, 2), (25, 3), (26, 4), (27, 5)],
   [(28, 6), (29, 0), (30, 1), (31, 2), (0, 3), (0, 4), (0, 5)]],
  [[(0, 6), (0, 0), (0, 1), (0, 2), (1, 3), (2, 4), (3, 5)],
   [(4, 6), (5, 0), (6, 1), (7, 2), (8, 3), (9, 4), (10, 5)],
   [(11, 6), (12, 0), (13, 1), (14, 2), (15, 3), (16, 4), (17, 5)],
   [(18, 6), (19, 0), (20, 1), (21, 2), (22, 3), (23, 4), (24, 5)],
   [(25, 6), (26, 0), (27, 1), (28, 2), (0, 3), (0, 4), (0, 5)]]],
 [[[(0, 6), (0, 0), (0, 1), (0, 2), (1, 3), (2, 4), (3, 5)],
   [(4, 6), (5, 0), (6, 1), (7, 2), (8, 3), (9, 4), (10, 5)],
   [(11, 6), (12, 0), (13, 1), (14, 2), (15, 3), (16, 4), (17, 5)],
   [(18, 6), (19, 0), (20, 1), (21, 2), (22, 3), (23, 4), (24, 5)],
   [(25, 6), (26, 0), (27, 1), (28, 2), (29, 3), (30, 4), (31, 5)]],
  [[(1, 6), (2, 0), (3, 1), (4, 2), (5, 3), (6, 4), (7, 5)],
   [(8, 6), (9, 0), (10, 1), (11, 2), (12, 3), (13, 4), (14, 5)],
   [(15, 6), (16, 0), (17, 1), (18, 2), (19, 3), (20, 4), (21, 5)],
   [(22, 6), (23, 0), (24, 1), (25, 2), (26, 3), (27, 4), (28, 5)],
   [(29, 6), (30, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]]],
 [[[(0, 6), (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)],
   [(6, 6), (7, 0), (8, 1), (9, 2), (10, 3), (11, 4), (12, 5)],
   [(13, 6), (14, 0), (15, 1), (16, 2), (17, 3), (18, 4), (19, 5)],
   [(20, 6), (21, 0), (22, 1), (23, 2), (24, 3), (25, 4), (26, 5)],
   [(27, 6), (28, 0), (29, 1), (30, 2), (31, 3), (0, 4), (0, 5)]],
  [[(0, 6), (0, 0), (0, 1), (0, 2), (0, 3), (1, 4), (2, 5)],
   [(3, 6), (4, 0), (5, 1), (6, 2), (7, 3), (8, 4), (9, 5)],
   [(10, 6), (11, 0), (12, 1), (13, 2), (14, 3), (15, 4), (16, 5)],
   [(17, 6), (18, 0), (19, 1), (20, 2), (21, 3), (22, 4), (23, 5)],
   [(24, 6), (25, 0), (26, 1), (27, 2), (28, 3), (29, 4), (30, 5)]]],
 [[[(1, 6), (2, 0), (3, 1), (4, 2), (5, 3), (6, 4), (7, 5)],
   [(8, 6), (9, 0), (10, 1), (11, 2), (12, 3), (13, 4), (14, 5)],
   [(15, 6), (16, 0), (17, 1), (18, 2), (19, 3), (20, 4), (21, 5)],
   [(22, 6), (23, 0), (24, 1), (25, 2), (26, 3), (27, 4), (28, 5)],
   [(29, 6), (30, 0), (31, 1), (0, 2), (0, 3), (0, 4), (0, 5)]],
  [[(0, 6), (0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5)],
   [(5, 6), (6, 0), (7, 1), (8, 2), (9, 3), (10, 4), (11, 5)],
   [(12, 6), (13, 0), (14, 1), (15, 2), (16, 3), (17, 4), (18, 5)],
   [(19, 6), (20, 0), (21, 1), (22, 2), (23, 3), (24, 4), (25, 5)],
   [(26, 6), (27, 0), (28, 1), (29, 2), (30, 3), (31, 4), (0, 5)]]],
 [[[(0, 6), (0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 5)],
   [(2, 6), (3, 0), (4, 1), (5, 2), (6, 3), (7, 4), (8, 5)],
   [(9, 6), (10, 0), (11, 1), (12, 2), (13, 3), (14, 4), (15, 5)],
   [(16, 6), (17, 0), (18, 1), (19, 2), (20, 3), (21, 4), (22, 5)],
   [(23, 6), (24, 0), (25, 1), (26, 2), (27, 3), (28, 4), (29, 5)],
   [(30, 6), (0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]],
  [[(0, 6), (1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5)],
   [(7, 6), (8, 0), (9, 1), (10, 2), (11, 3), (12, 4), (13, 5)],
   [(14, 6), (15, 0), (16, 1), (17, 2), (18, 3), (19, 4), (20, 5)],
   [(21, 6), (22, 0), (23, 1), (24, 2), (25, 3), (26, 4), (27, 5)],
   [(28, 6), (29, 0), (30, 1), (31, 2), (0, 3), (0, 4), (0, 5)]]],
 [[[(0, 6), (0, 0), (0, 1), (0, 2), (1, 3), (2, 4), (3, 5)],
   [(4, 6), (5, 0), (6, 1), (7, 2), (8, 3), (9, 4), (10, 5)],
   [(11, 6), (12, 0), (13, 1), (14, 2), (15, 3), (16, 4), (17, 5)],
   [(18, 6), (19, 0), (20, 1), (21, 2), (22, 3), (23, 4), (24, 5)],
   [(25, 6), (26, 0), (27, 1), (28, 2), (29, 3), (30, 4), (0, 5)]],
  [[(0, 6), (0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 5)],
   [(2, 6), (3, 0), (4, 1), (5, 2), (6, 3), (7, 4), (8, 5)],
   [(9, 6), (10, 0), (11, 1), (12, 2), (13, 3), (14, 4), (15, 5)],
   [(16, 6), (17, 0), (18, 1), (19, 2), (20, 3), (21, 4), (22, 5)],
   [(23, 6), (24, 0), (25, 1), (26, 2), (27, 3), (28, 4), (29, 5)],
   [(30, 6), (31, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]]]]

Questo è l'equivalente dei dati usati da formatyear()

import calendar

print calendar.TextCalendar(calendar.SUNDAY).formatyear(2007, 2, 1, 1, 2)

che con gli stessi parametri produce un output tipo:

$ python calendar_formatyear.py
                   2007

      January               February
Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa
    1  2  3  4  5  6               1  2  3
 7  8  9 10 11 12 13   4  5  6  7  8  9 10
14 15 16 17 18 19 20  11 12 13 14 15 16 17
21 22 23 24 25 26 27  18 19 20 21 22 23 24
28 29 30 31           25 26 27 28

       March                 April
Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa
             1  2  3   1  2  3  4  5  6  7
 4  5  6  7  8  9 10   8  9 10 11 12 13 14
11 12 13 14 15 16 17  15 16 17 18 19 20 21
18 19 20 21 22 23 24  22 23 24 25 26 27 28
25 26 27 28 29 30 31  29 30

        May                   June
Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa
       1  2  3  4  5                  1  2
 6  7  8  9 10 11 12   3  4  5  6  7  8  9
13 14 15 16 17 18 19  10 11 12 13 14 15 16
20 21 22 23 24 25 26  17 18 19 20 21 22 23
27 28 29 30 31        24 25 26 27 28 29 30

        July                 August
Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa
 1  2  3  4  5  6  7            1  2  3  4
 8  9 10 11 12 13 14   5  6  7  8  9 10 11
15 16 17 18 19 20 21  12 13 14 15 16 17 18
22 23 24 25 26 27 28  19 20 21 22 23 24 25
29 30 31              26 27 28 29 30 31

     September              October
Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa
                   1      1  2  3  4  5  6
 2  3  4  5  6  7  8   7  8  9 10 11 12 13
 9 10 11 12 13 14 15  14 15 16 17 18 19 20
16 17 18 19 20 21 22  21 22 23 24 25 26 27
23 24 25 26 27 28 29  28 29 30 31
30

      November              December
Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa
             1  2  3                     1
 4  5  6  7  8  9 10   2  3  4  5  6  7  8
11 12 13 14 15 16 17   9 10 11 12 13 14 15
18 19 20 21 22 23 24  16 17 18 19 20 21 22
25 26 27 28 29 30     23 24 25 26 27 28 29
                      30 31

Se per una qualche ragione si vuole formattare da soli l'output (ad esempio per includere collegamenti nell'output HTML), verranno utili gli attributi del modulo day_name, day_abbr, month_name e month_abbr. Essi sono automaticamente configurati secondo la localizzazione corrente.

Esempi Di Calcolo

Sebbene il modulo calendar si focalizzi principalmente sulla stampa di calendari completi in vari formati, fornisce anche delle funzioni utili per lavorare con le date in altri modi, tipo calcolare le date per un evento ricorrente. Ad esempio, il Python Atlanta User's Group si incontra il secondo giovedì di ogni mese. Per calcolare le date degli incontri per un anno, si potrebbe utilizzare il valore restituito da monthcalendar()

import calendar
import pprint

pprint.pprint(calendar.monthcalendar(2007, 7))

Notare che alcuni giorni hanno valore 0. Questi sono i giorni della settimana che si sovrappongono al mese considerato, ma che fanno parte di un altro mese.

$ python calendar_monthcalendar.py
[[0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0]]

Ricordare che, come valore predefinito, il primo giorno del mese è lunedì. E' possibile cambiarlo chiamando setfirstweekday(). D'altro canto, visto che il modulo calendar include delle costanti per indicizzare gli intervalli di date restituite da monthcalendar(), è molto più conveniente saltare quel passo in questo caso.

Per calcolare le date per gli incontri del PyATL per il 2007, sapendo che deve essere il secondo giovedì di ogni mese, possiamo usare i valori 0 per sapere se il giovedì della prima settimana è incluso nel mese (o se il mese inizia, ad esempio, il venerdì)

import calendar

# Mostra ogni mese
for month in range(1, 13):

    # Calcola le date di ogni settimana che si sovrappongono nel mese
    c = calendar.monthcalendar(2007, month)
    first_week = c[0]
    second_week = c[1]
    third_week = c[2]

    # Se c'è un giovedi' nella prima settimana, il secondo giovedi'
    # è nella seconda settimana. Altrimenti il secondo giovedi'
    # deve essere nella terza settimana.
    if first_week[calendar.THURSDAY]:
        meeting_date = second_week[calendar.THURSDAY]
    else:
        meeting_date = third_week[calendar.THURSDAY]

    print '%3s: %2s' % (month, meeting_date)

Quindi il calendario degli incontri del PyATL per il 2007 è:

$ python calendar_secondthursday.py
  1: 11
  2:  8
  3:  8
  4: 12
  5: 10
  6: 14
  7: 12
  8:  9
  9: 13
 10: 11
 11:  8
 12: 13

Vedere anche:

calendar
La documentazione della libreria standard per questo modulo.
time
Funzioni a basso livello sul tempo
datetime
Manipola valori di data, compresi timestamp e fusi orari