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