Prosty konsolowy kalendarz – cz.2

We wcześniejszym >>wpisie<< konsolowy kalendarz nie wykorzystuje bogactwa modułu calendar. Aby uprościć kod można wykorzystać 'gotowca’ czyli klasę TextCalendar z tego modułu. Dzięki temu można zdefiniować funkcję cal2(), którą można zaimportować z modułu cal2, bądź też wywołać z konsoli. Przy wywołaniu z konsoli musimy nadać plikowi prawa do wykonania (chmod +x cal2.py).

Uruchomienie pliku bez podania argumentów tzn. ./cal2.py spowoduje wyświetlenie w konsoli kalendarza dla bieżącego roku i miesiąca. Alternatywnie możemy uruchomić program z 2 argumentami: rok oraz miesiąc. Podanie innej liczby argumentów wywoła wyjątek TypeError.

#!/usr/bin/env python

import calendar

from datetime import datetime

import sys

def cal2(year=datetime.today().year, month=datetime.today().month):
    '''
    Simple console calendar.
    '''
    c = calendar
    text_calendar = c.TextCalendar(c.firstweekday())
    print(text_calendar.formatmonth(year, month))

if __name__ == '__main__':
    args = sys.argv[1:]
    if len(args) == 0:
        cal2()
    elif len(args) == 2:
        cal2(int(args[0]), int(args[1]))
    else:
        raise TypeError(
            'cal2() takes 2 arguments ({} given)'.format(len(args)))

Zamiast klasy TextCalendar możemy użyć klasy potomnej – LocaleTextCalendar i uzyskać napisy zgodne z lokalnymi ustawieniami językowymi.

Proste narzędzie do wyświetlania kalendarza

Program ten jest prostym odpowiednikiem konsolowego narzędzia cal, które wyświetla w konsoli kalendarz dla podanego roku i miesiąca.

Jeśli nie podano argumentów, domyślnie drukuje kalendarz dla bieżącego roku i miesiąca. /screenshot/

#!/usr/bin/env python

from datetime import datetime

from calendar import monthrange, weekheader, weekday

from sys import stdout


def cal(year=datetime.today().year, month=datetime.today().month):
    """
    Prints month calendar for given year and month.
    """

    this_year = year
    this_month = month

    # number of all days in month
    days_in_month = monthrange(this_year, this_month)[1]

    # which week day is the first day of month
    first_day_of_month = weekday(this_year, this_month, 1)

    # prints header of calendar (width 5)
    print(weekheader(5))

    # positioning loop
    # for proper position of the first element
    for i in range(first_day_of_month):
        stdout.write(6 * ' ')

    i = 1
    while i <= days_in_month:
        stdout.write(' {:>2}   '.format(i))
        # new line if sunday
        if weekday(this_year, this_month, i) == 6:
            print('')
        i += 1
    print('')

if __name__ == '__main__':
    cal()