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