def tisk_kalendare(mesic, rok):
    """
    tisk kalendáře

    pro zadaný měsíc vytiskne kalendář v tradičním týdenním
    uspořádání
    """
    # tisk hlavičky
    print('--------------------')
    print(jmeno_mesice(mesic), rok)
    print()
    # přeskočení dní z minulého měsíce
    # (v pondělí je juliánské datum dělitelné 7)
    preskocit = jul_datum(1, mesic, rok) % 7
    for i in range(preskocit):
        tisk_dne(0)
    # tisk jednotlivých dní měsíce 
    for i in range(1, dni_mesice(mesic, rok) + 1):
        tisk_dne(i)
        # po neděli odřádkujeme (další týden na nový řádek)
        if (preskocit + i) % 7 == 0:
            print()
    # odřádkování pokud měsíc nekončí nedělí
    if (preskocit + i) % 7 != 0:
        print()
    # tisk patičky
    print('--------------------')

def jul_datum(den, mesic, rok):
    """
    výpočet juliánského data

    pro zadaný den, měsíc a rok vypočte juliánské datum (JDN),
    předpokládá vstupní parametry dle gregoriánského kalendáře
    (datum musí být platné, parametry kladné int)
    viz. https://cs.wikipedia.org/wiki/Juli%C3%A1nsk%C3%A9_datum
    """
    if mesic <= 2:
        r = rok + 4799
        n = mesic + 9
    else:
        r = rok + 4800
        n = mesic - 3
    e = den + (153 * n + 2) // 5
    # návratová hodnota typu int
    return e + 365 * r + r // 4 - r // 100 + r // 400 - 32045

def prestupny_rok(rok):
    """
    určení přestupného roku

    pro zadaný rok dle gregoriánského kalendáře určí,
    zda se jedná o přestupný rok
    návratová hodnota - bool (True pro přestupný rok)
    """
    if rok % 400 == 0:
        return True
    elif rok % 100 == 0:
        return False
    else:
        return rok % 4 == 0

def dni_mesice(mesic, rok):
    """
    určení počtu dní v měsíci
    
    pro zadaný měsíc určí počet dní (pro únor uvažuje 
    přestupné roky)
    """
    if (mesic < 8 and mesic % 2 == 1) \
            or (mesic >= 8 and mesic % 2 == 0):
        return 31
    elif mesic == 2:
        if prestupny_rok(rok):
            return 29
        else:
            return 28
    else:
        return 30

def tisk_dne(den):
    """
    formátovaný tisk jednoho dne

    vytiskne jeden den tak, aby se zachovalo formátování
    kalendáře
    pro nulový argument pouze tiskne správný počet mezer
    """
    if den == 0:
        print('   ', end = '')
    elif den < 10:
        print(' ', den, ' ', sep = '', end = '')
    else:
        print(den, ' ', sep = '', end = '')
      
def jmeno_mesice(mesic):
    "vrátí jméno měsíce jako řetězec"
    if mesic == 1:
        return 'leden'
    elif mesic == 2:
        return 'únor'
    elif mesic == 3:
        return 'březen'
    elif mesic == 4:
        return 'duben'
    elif mesic == 5:
        return 'květen'
    elif mesic == 6:
        return 'červen'
    elif mesic == 7:
        return 'červenec'
    elif mesic == 8:
        return 'srpen'
    elif mesic == 9:
        return 'září'
    elif mesic == 10:
        return 'říjen'
    elif mesic == 11:
        return 'listopad'
    else:
        return 'prosinec'

def platne_datum(den, mesic, rok):
    """
    ověří platnost data

    ověří se, že zadané datum je podle gregoriánského
    kalendáře platné (zjednodušeně uvažuje rok >= 1600)
    návratová hodnota: bool
    """
    if rok < 1600:
        return False # kontrola roku selhala
    if mesic < 1 or mesic > 12:
        return False # kontrola měsíce selhala
    if den < 1 or den > dni_mesice(mesic, rok):
        return False # kontrola dne selhala
    return True # datum je platné

def tyden_roku(den, mesic, rok):
    """
    tyden roku pro zadaný den

    určí týden roku, do kterého patří zadaný den
    dle ISO 8601 (1. týden obsahuje 4. leden resp.
    první čtvrtek roku)
    návratová hodnota: int - číslo týdne (0 pro 
    poslední týden minulého roku)
    """
    jdn_4_1 = jul_datum(4, 1, rok) # JDN pro 4. leden
    jdn = jul_datum(den, mesic, rok) # JDN zadaného dne
    den_4_1 = jdn_4_1 % 7 # den v týdnu pro 4. leden
    # JDN začátku týdne s 4. lednem
    start_tyden1 = jdn_4_1 - den_4_1
    if jdn < start_tyden1: # poslední týden minulého roku
        return 0
    else: # určí počet celých uplynulých týdnu + 1
        return (jdn - start_tyden1) // 7 + 1

# hlavní program
if __name__ == "__main__":
    for rok in range(2015, 2025):
        tisk_kalendare(1, rok)
        print("1.1.", rok, " t", tyden_roku(1, 1, rok), sep = "")
        print("4.1.", rok, " t", tyden_roku(4, 1, rok), sep = "")
        print("10.1.", rok, " t", tyden_roku(10, 1, rok), sep = "")
        print("15.1.", rok, " t", tyden_roku(15, 1, rok), sep = "")
        print("31.1.", rok, " t", tyden_roku(31, 1, rok), sep = "")

