paulb@215 | 1 | #!/usr/bin/env python |
paulb@215 | 2 | |
paulb@215 | 3 | import libxml2dom |
paulb@215 | 4 | import calendar |
paulb@215 | 5 | |
paulb@215 | 6 | # Borrowed from calendar, but with a non-global first weekday variable. |
paulb@215 | 7 | |
paulb@215 | 8 | def monthcalendar(year, month, firstweekday=0): |
paulb@215 | 9 | """Return a matrix representing a month's calendar. |
paulb@215 | 10 | Each row represents a week; days outside this month are zero.""" |
paulb@215 | 11 | day1, ndays = calendar.monthrange(year, month) |
paulb@215 | 12 | rows = [] |
paulb@215 | 13 | r7 = range(7) |
paulb@215 | 14 | day = (firstweekday - day1 + 6) % 7 - 5 # for leading 0's in first week |
paulb@215 | 15 | while day <= ndays: |
paulb@215 | 16 | row = [0, 0, 0, 0, 0, 0, 0] |
paulb@215 | 17 | for i in r7: |
paulb@215 | 18 | if 1 <= day <= ndays: row[i] = day |
paulb@215 | 19 | day = day + 1 |
paulb@215 | 20 | rows.append(row) |
paulb@215 | 21 | return rows |
paulb@215 | 22 | |
paulb@217 | 23 | # Helper functions. |
paulb@217 | 24 | |
paulb@217 | 25 | def get_previous_year_and_month(year, month): |
paulb@217 | 26 | if month - 1 == 0: |
paulb@217 | 27 | return year - 1, 12 |
paulb@217 | 28 | else: |
paulb@217 | 29 | return year, month - 1 |
paulb@217 | 30 | |
paulb@217 | 31 | def get_next_year_and_month(year, month): |
paulb@217 | 32 | if month + 1 == 13: |
paulb@217 | 33 | return year + 1, 1 |
paulb@217 | 34 | else: |
paulb@217 | 35 | return year, month + 1 |
paulb@217 | 36 | |
paulb@215 | 37 | # XML production functions. |
paulb@215 | 38 | |
paulb@216 | 39 | def write_month_to_document(doc, root, year, month): |
paulb@215 | 40 | weeks = monthcalendar(year, month) |
paulb@216 | 41 | month_element = root.appendChild(doc.createElement("month")) |
paulb@217 | 42 | |
paulb@217 | 43 | # Add navigational attributes. |
paulb@217 | 44 | |
paulb@216 | 45 | month_element.setAttribute("number", str(month)) |
paulb@216 | 46 | month_element.setAttribute("year", str(year)) |
paulb@217 | 47 | yp, mp = get_previous_year_and_month(year, month) |
paulb@217 | 48 | month_element.setAttribute("number-previous", str(mp)) |
paulb@217 | 49 | month_element.setAttribute("year-previous", str(yp)) |
paulb@217 | 50 | yn, mn = get_next_year_and_month(year, month) |
paulb@217 | 51 | month_element.setAttribute("number-next", str(mn)) |
paulb@217 | 52 | month_element.setAttribute("year-next", str(yn)) |
paulb@217 | 53 | |
paulb@217 | 54 | # Add weeks and days. |
paulb@217 | 55 | |
paulb@216 | 56 | for numbers in weeks: |
paulb@215 | 57 | week_element = month_element.appendChild(doc.createElement("week")) |
paulb@216 | 58 | for number in numbers: |
paulb@215 | 59 | day_element = week_element.appendChild(doc.createElement("day")) |
paulb@216 | 60 | if number != 0: |
paulb@216 | 61 | day_element.setAttribute("date", "%04d%02d%02d" % (year, month, number)) |
paulb@216 | 62 | day_element.setAttribute("number", str(number)) |
paulb@215 | 63 | |
paulb@215 | 64 | def get_calendar_for_month(year, month): |
paulb@216 | 65 | doc = libxml2dom.createDocument(None, "calendar", None) |
paulb@216 | 66 | write_month_to_document(doc, doc.childNodes[-1], year, month) |
paulb@216 | 67 | return doc |
paulb@215 | 68 | |
paulb@215 | 69 | if __name__ == "__main__": |
paulb@215 | 70 | import sys |
paulb@215 | 71 | try: |
paulb@215 | 72 | print get_calendar_for_month(int(sys.argv[1]), int(sys.argv[2])).toString() |
paulb@215 | 73 | except (IndexError, ValueError): |
paulb@215 | 74 | print "Please specify a year and a month (numeric, 1-12)." |
paulb@215 | 75 | |
paulb@215 | 76 | # vim: tabstop=4 expandtab shiftwidth=4 |