# Prompts the user for a year or a year and a month,
# the year being no earlier than 1753, and displays
# the calendar for the period requested in the style
# of the Unix cal command, but starting the week on Monday (not SUnday)


# Written by Eric Martin for COMP9021

field_width = 22


def calendar():
    month_names = ['January', 'February', 'March', 'April',
                   'May', 'June', 'July', 'August',
                   'September', 'October', 'November', 'December']
    month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

    print("I will display a calendar, either for a year "
          "or for a month in a year.\n"
          "The earliest year should be 1753.\n"
          "For the month, input at least the first three letters "
          "of the month's name.")
    correct_input = False
    month = 0
    while not correct_input:
        date = input('Input year, or year and month, or month and year: ')
        date = date.split()
        if len(date) == 0 or len(date) > 2:
            continue
        if len(date) == 1:
            try:
                year = int(date[0])
                correct_input = True
            except:
                print('Incorrect input. ', end = '')
            else:
                if year < 1753 or year > 9999999999999999:
                    print('Incorrect input. ', end = '')
                    correct_input = False
        else:
            date_0 = date[0].title()
            date_1 = date[1].title()
            try:
                month = date_0
                year = int(date_1)
            except:
                try:
                    month = date_1
                    year = int(date_0)
                except:
                    print('Incorrect input. ', end = '')
                    continue
            if len(month) < 3:
                print('Incorrect input. ', end = '')
                continue
            for i in range(12):
                if month_names[i].startswith(month):
                    month = i
                    correct_input = True
                    break

    # Number of days between 1 January 2000 and the requested date,
    # being 1 January of the requested year if no month has been input,
    # positive for a date after 1 January 2000, negative for a date
    # before 1 January 2000.
    # If a month of March or later has been input and the input year
    # is a leap year before 2000, then the assignment is incorrect
    # by one day, which is fixed in the following if statement.
    offset = (year - 2000) * 365 + \
                     (year - 1997) // 4 - \
                     (year - 1901) // 100 + \
                     (year - 1601) // 400 + \
                     sum(month_lengths[0 : month])
    if month > 2 and (year % 4 == 0 and year % 100 or year % 400 == 0):
        offset += 1
    # 1 January 2000 is a Saturday
    starting_day = (offset + 5) % 7
    if len(date) == 2:
        date = month_names[month] + ' ' + str(year)
        print(date.center(field_width))
        if month == 1 and (year % 4 == 0 and year % 100 or year % 400 == 0):
            nb_of_days = 29
        else:
            nb_of_days = month_lengths[month]
        for line in month_representation_lines(starting_day, nb_of_days):
            print(line)
    else:
        print(str(year).center(field_width * 3) + '\n')
        if year % 4 == 0 and year % 100 or year % 400 == 0:
            month_lengths[1] += 1
        months = [[month.center(field_width)] for month in month_names]
        for i in range(12):
            months[i].extend(month_representation_lines(starting_day,
                                                        month_lengths[i]))
            starting_day = (starting_day + month_lengths[i]) % 7
        groups_of_three_months = [months[3 * i : 3 * (i + 1)] for i in range(4)]
        for group_of_three_months in groups_of_three_months:
            for month in group_of_three_months:
                month.extend([' ' * field_width] *\
                          (max(map(len, group_of_three_months)) - len(month)))
                lines = map(''.join, zip(*group_of_three_months))
            for line in lines:
                print(line)


def month_representation_lines(starting_day, nb_of_days):
    lines = [' Mo Tu We Th Fr Sa Su ']
    line = ' ' * 3 * starting_day
    for i in range(1, nb_of_days + 1):
        line += "{0:3d}".format(i)
        starting_day = (starting_day + 1) % 7
        if starting_day == 0:
            lines.append(line + ' ')
            line = ''
    if line != '':
        line += ' ' * 3 * (7 - starting_day)
        lines.append(line + ' ')
    return lines
    

if __name__ == '__main__':
    calendar()


Resource created Monday 07 September 2015, 10:30:40 AM.

file: question_3.py


Back to top

COMP9021 15s2 (Principles of Programming) is powered by WebCMS3
CRICOS Provider No. 00098G