calendar - Lavorare con le Date

Scopo: Il modulo calendar implementa le classi per lavorare con le date per gestire valori relativi ad anno/mese/settimana.

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

Esempi Di Formattazione

Il metodo prmonth() è una semplice funzione che produce un output di testo formattato per un mese.

# calendar_textcalendar.py

import calendar

c = calendar.TextCalendar(calendar.MONDAY)
c.prmonth(2015, 7)

L'esempio configura TextCalendar in modo che inizi le settimane di Domenica, secondo la convenzione Americana. La convenzione predefinita in uso per l'Europa stabilisce l'inizio della settimana di Lunedì (gli esempi sono stati modificati in questo senso dal traduttore - N.d.T.).

L'output è tipo questo:

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

Una tabella simile in formato HTML può essere prodotta con HTMLCalendar e formatmonth(). L'output fornito assomiglia grossomodo a quello della versione in testo semplice, ma è incapsulato in tag HTML. Ogni cella della tabella ha un attributo di classe che corrisponde al giorno della settimana, in modo che al codice HTML possa essere applicato uno stile tramite CSS.

Per produrre un output in formati diversi da quelli predefiniti disponibili, si utilizza calendar per calcolare le date e disporre i valori all'interno di settimane e mesi, quindi iterare sul risultato. I metodi di Calendar weekheader(), monthcalendar() e yeardays2calendar() sono particolarmente utili allo scopo.

La chiamata di yeardays2calendar() produce una sequenza di liste di "righe di mesi". Ciascuna lista include i mesi come un'altra lista di settimane. Le settimane sono liste di tuple composte da giorno del mese (1-31) e numero di giorno della settimana (0-6). I giorni che ricadono al di fuori del mese di riferimento hanno un numero di giorno del mese pari a 0.

# calendar_yeardays2calendar.py

import calendar
import pprint

cal = calendar.Calendar(calendar.MONDAY)

cal_data = cal.yeardays2calendar(2015, 3)
print('len(cal_data)      :', len(cal_data))

top_months = cal_data[0]
print('len(top_months)    :', len(top_months))

first_month = top_months[0]
print('len(first_month)   :', len(first_month))

print('first_month:')
pprint.pprint(first_month)

La chiamata di yeardays2calendar(2015, 3) ritorna i dati per il 2015, disposti con tre mesi per riga.

$ python3 calendar_yeardays2calendar.py

len(cal_data)      : 4
len(top_months)    : 3
len(first_month)   : 5
first_month:
[[(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), (0, 6)]]

Il seguente è equivalente ai dati utilizzati da formatyear().

# calendar_formatyear.py

import calendar

cal = calendar.TextCalendar(calendar.MONDAY)
print(cal.formatyear(2015, 2, 1, 1, 3))

Con gli stessi argomenti, formatyear() produce questo output:

$ python3 calendar_formatyear.py

                              2015

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

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

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

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

Agli attributi del modulo day_name, day_abbr, month_name e month_abbr sono utili per generare output con formattazione personalizzata (ad esempio per includere collegamenti nell'output HTML). Essi sono configurati automaticamente per la localizzazione corrente.

Localizzazione

Per produrre un calendario formattato per una localizzazione diversa da quella predefinita, si utilizza LocaleTextCalendar oppure LocaleHTMLCalendar.

# calendar_locale.py

import calendar

c = calendar.LocaleTextCalendar(locale='en_US')
c.prmonth(2015, 7)

print()

c = calendar.LocaleTextCalendar(locale='fr_FR')
c.prmonth(2015, 7)

Il primo giorno della settimana non fa parte delle impostazioni di localizzazione, ed il valore è preso dall'argomento della classe Calendar esattamente come con il normale TextCalendar.

$ python3 calendar_locale.py

     July 2015
Mo Tu We Th Fr Sa Su
       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

    juillet 2015
Lu Ma Me Je Ve Sa Di
       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

Calcoli sulle Date

Sebbene il modulo calendar si focalizzi principalmente nello stampare interi calendari in vari formati, esso fornisce anche utili funzioni per lavorare con le date in altri modi, tipo il calcolare 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 utilizza il valore restituito da monthcalendar().

# calendar_monthcalendar.py

import calendar
import pprint

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

Alcuni giorni hanno un valore di 0. Sono quei giorni della settimana che si sovrappongono al mese passato come argomento ma sono parte di un altro mese.

$ python3 calendar_monthcalendar.py

[[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]]

Il primo giorno del mese predefinito è lunedì. E' possibile modificarlo chiamando setfirstweekday(), tuttavia visto che il modulo calendar comprende costanti per indicizzare gli intervalli di date ritornate da monthcalendar(), è più conveniente saltare questo passo in questa situazione.

Per calcolare le date degli incontri del gruppo per il 2015, considerando il secondo giovedì di ogni mese, i valori 0 indicano se il giovedì della prima settimana sia incluso nel mese (o se il mese inizia, ad esempio, il venerdì).

# calendar_secondthursday.py

import calendar

# Show every month
for month in range(1, 13):

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

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

    print('{:>3}: {:>2}'.format(calendar.month_abbr[month],
                                meeting_date))

Quindi il calendario degli incontri per il 2015 era:

$ python3 calendar_secondthursday.py

Jan:  8
Feb: 12
Mar: 12
Apr:  9
May: 14
Jun: 11
Jul:  9
Aug: 13
Sep: 10
Oct:  8
Nov: 12
Dec: 10

Vedere anche:

calendar
La documentazione della libreria standard per questo modulo.
datetime
Manipola valori di data, compresi timestamp e fusi orari