paulb@215 | 1 | #!/usr/bin/env python |
paulb@215 | 2 | |
paulb@464 | 3 | """ |
paulb@464 | 4 | Copyright (C) 2005 Paul Boddie <paul@boddie.org.uk> |
paulb@464 | 5 | |
paulb@464 | 6 | Additional copyrights for the monthcalendar function: |
paulb@464 | 7 | |
paulb@464 | 8 | Copyright (c) 2001, 2002, 2003, 2004, 2005 Python Software Foundation. |
paulb@464 | 9 | Copyright (c) 2000 BeOpen.com. |
paulb@464 | 10 | Copyright (c) 1995-2001 Corporation for National Research Initiatives. |
paulb@464 | 11 | Copyright (c) 1991-1995 Stichting Mathematisch Centrum. |
paulb@464 | 12 | |
paulb@464 | 13 | This library is free software; you can redistribute it and/or |
paulb@464 | 14 | modify it under the terms of the GNU Lesser General Public |
paulb@464 | 15 | License as published by the Free Software Foundation; either |
paulb@464 | 16 | version 2.1 of the License, or (at your option) any later version. |
paulb@464 | 17 | |
paulb@464 | 18 | This library is distributed in the hope that it will be useful, |
paulb@464 | 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
paulb@464 | 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
paulb@464 | 21 | Lesser General Public License for more details. |
paulb@464 | 22 | |
paulb@464 | 23 | You should have received a copy of the GNU Lesser General Public |
paulb@464 | 24 | License along with this library; if not, write to the Free Software |
paulb@464 | 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
paulb@464 | 26 | """ |
paulb@464 | 27 | |
paulb@215 | 28 | import libxml2dom |
paulb@215 | 29 | import calendar |
paulb@215 | 30 | |
paulb@215 | 31 | # Borrowed from calendar, but with a non-global first weekday variable. |
paulb@215 | 32 | |
paulb@215 | 33 | def monthcalendar(year, month, firstweekday=0): |
paulb@215 | 34 | """Return a matrix representing a month's calendar. |
paulb@215 | 35 | Each row represents a week; days outside this month are zero.""" |
paulb@215 | 36 | day1, ndays = calendar.monthrange(year, month) |
paulb@215 | 37 | rows = [] |
paulb@215 | 38 | r7 = range(7) |
paulb@215 | 39 | day = (firstweekday - day1 + 6) % 7 - 5 # for leading 0's in first week |
paulb@215 | 40 | while day <= ndays: |
paulb@215 | 41 | row = [0, 0, 0, 0, 0, 0, 0] |
paulb@215 | 42 | for i in r7: |
paulb@215 | 43 | if 1 <= day <= ndays: row[i] = day |
paulb@215 | 44 | day = day + 1 |
paulb@215 | 45 | rows.append(row) |
paulb@215 | 46 | return rows |
paulb@215 | 47 | |
paulb@217 | 48 | # Helper functions. |
paulb@217 | 49 | |
paulb@217 | 50 | def get_previous_year_and_month(year, month): |
paulb@217 | 51 | if month - 1 == 0: |
paulb@217 | 52 | return year - 1, 12 |
paulb@217 | 53 | else: |
paulb@217 | 54 | return year, month - 1 |
paulb@217 | 55 | |
paulb@217 | 56 | def get_next_year_and_month(year, month): |
paulb@217 | 57 | if month + 1 == 13: |
paulb@217 | 58 | return year + 1, 1 |
paulb@217 | 59 | else: |
paulb@217 | 60 | return year, month + 1 |
paulb@217 | 61 | |
paulb@215 | 62 | # XML production functions. |
paulb@215 | 63 | |
paulb@216 | 64 | def write_month_to_document(doc, root, year, month): |
paulb@215 | 65 | weeks = monthcalendar(year, month) |
paulb@216 | 66 | month_element = root.appendChild(doc.createElement("month")) |
paulb@217 | 67 | |
paulb@217 | 68 | # Add navigational attributes. |
paulb@217 | 69 | |
paulb@216 | 70 | month_element.setAttribute("number", str(month)) |
paulb@216 | 71 | month_element.setAttribute("year", str(year)) |
paulb@217 | 72 | yp, mp = get_previous_year_and_month(year, month) |
paulb@217 | 73 | month_element.setAttribute("number-previous", str(mp)) |
paulb@217 | 74 | month_element.setAttribute("year-previous", str(yp)) |
paulb@217 | 75 | yn, mn = get_next_year_and_month(year, month) |
paulb@217 | 76 | month_element.setAttribute("number-next", str(mn)) |
paulb@217 | 77 | month_element.setAttribute("year-next", str(yn)) |
paulb@217 | 78 | |
paulb@217 | 79 | # Add weeks and days. |
paulb@217 | 80 | |
paulb@216 | 81 | for numbers in weeks: |
paulb@215 | 82 | week_element = month_element.appendChild(doc.createElement("week")) |
paulb@216 | 83 | for number in numbers: |
paulb@215 | 84 | day_element = week_element.appendChild(doc.createElement("day")) |
paulb@216 | 85 | if number != 0: |
paulb@216 | 86 | day_element.setAttribute("date", "%04d%02d%02d" % (year, month, number)) |
paulb@216 | 87 | day_element.setAttribute("number", str(number)) |
paulb@215 | 88 | |
paulb@215 | 89 | def get_calendar_for_month(year, month): |
paulb@216 | 90 | doc = libxml2dom.createDocument(None, "calendar", None) |
paulb@216 | 91 | write_month_to_document(doc, doc.childNodes[-1], year, month) |
paulb@216 | 92 | return doc |
paulb@215 | 93 | |
paulb@215 | 94 | if __name__ == "__main__": |
paulb@215 | 95 | import sys |
paulb@215 | 96 | try: |
paulb@215 | 97 | print get_calendar_for_month(int(sys.argv[1]), int(sys.argv[2])).toString() |
paulb@215 | 98 | except (IndexError, ValueError): |
paulb@215 | 99 | print "Please specify a year and a month (numeric, 1-12)." |
paulb@215 | 100 | |
paulb@215 | 101 | # vim: tabstop=4 expandtab shiftwidth=4 |