183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""Calendar printing functions 283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehNote when comparing these calendars to the ones printed by cal(1): By 483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdefault, these calendars have Monday as the first day of the week, and 583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehSunday as the last (the European convention). Use setfirstweekday() to 683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehset the first day of the week (0=Monday, 6=Sunday).""" 783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport sys 983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport datetime 1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport locale as _locale 1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh__all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday", 1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "firstweekday", "isleap", "leapdays", "weekday", "monthrange", 1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "monthcalendar", "prmonth", "month", "prcal", "calendar", 1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "timegm", "month_name", "month_abbr", "day_name", "day_abbr"] 1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Exception raised for bad input (with string parameter for details) 1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieherror = ValueError 1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Exceptions raised for bad input 2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass IllegalMonthError(ValueError): 2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, month): 2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.month = month 2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __str__(self): 2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "bad month number %r; must be 1-12" % self.month 2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass IllegalWeekdayError(ValueError): 2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, weekday): 3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.weekday = weekday 3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __str__(self): 3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "bad weekday number %r; must be 0 (Monday) to 6 (Sunday)" % self.weekday 3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Constants for months referenced later 3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehJanuary = 1 3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehFebruary = 2 3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Number of days per month (except for February in leap years) 4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehmdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] 4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# This module used to have hard-coded lists of day and month names, as 4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# English strings. The classes following emulate a read-only version of 4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# that, but supply localized names. Note that the values are computed 4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# fresh on each call, in case the user changes locale between calls. 4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass _localized_month: 4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _months = [datetime.date(2001, i+1, 1).strftime for i in range(12)] 5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _months.insert(0, lambda x: "") 5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, format): 5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.format = format 5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __getitem__(self, i): 5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh funcs = self._months[i] 5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if isinstance(i, slice): 5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return [f(self.format) for f in funcs] 5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return funcs(self.format) 6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __len__(self): 6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 13 6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass _localized_day: 6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # January 1, 2001, was a Monday. 6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _days = [datetime.date(2001, 1, i+1).strftime for i in range(7)] 7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, format): 7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.format = format 7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __getitem__(self, i): 7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh funcs = self._days[i] 7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if isinstance(i, slice): 7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return [f(self.format) for f in funcs] 7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return funcs(self.format) 8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __len__(self): 8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 7 8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Full and abbreviated names of weekdays 8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehday_name = _localized_day('%A') 8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehday_abbr = _localized_day('%a') 8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Full and abbreviated names of months (1-based arrays!!!) 9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehmonth_name = _localized_month('%B') 9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehmonth_abbr = _localized_month('%b') 9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Constants for weekdays 9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7) 9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef isleap(year): 9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Return True for leap years, False for non-leap years.""" 9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) 10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef leapdays(y1, y2): 10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Return number of leap years in range [y1, y2). 10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Assume y1 <= y2.""" 10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh y1 -= 1 10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh y2 -= 1 10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return (y2//4 - y1//4) - (y2//100 - y1//100) + (y2//400 - y1//400) 10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef weekday(year, month, day): 11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), 11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh day (1-31).""" 11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return datetime.date(year, month, day).weekday() 11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef monthrange(year, month): 11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for 11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh year, month.""" 11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not 1 <= month <= 12: 12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise IllegalMonthError(month) 12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh day1 = weekday(year, month, 1) 12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ndays = mdays[month] + (month == February and isleap(year)) 12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return day1, ndays 12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Calendar(object): 12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Base calendar class. This class doesn't do any formatting. It simply 12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh provides data to subclasses. 13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, firstweekday=0): 13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.firstweekday = firstweekday # 0 = Monday, 6 = Sunday 13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getfirstweekday(self): 13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._firstweekday % 7 13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def setfirstweekday(self, firstweekday): 13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._firstweekday = firstweekday 14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh firstweekday = property(getfirstweekday, setfirstweekday) 14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def iterweekdays(self): 14483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 14583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a iterator for one week of weekday numbers starting with the 14683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh configured first one. 14783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 14883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for i in range(self.firstweekday, self.firstweekday + 7): 14983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh yield i%7 15083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 15183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def itermonthdates(self, year, month): 15283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 15383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return an iterator for one month. The iterator will yield datetime.date 15483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh values and will always iterate through complete weeks, so it will yield 15583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dates outside the specified month. 15683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 15783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh date = datetime.date(year, month, 1) 15883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Go back to the beginning of the week 15983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh days = (date.weekday() - self.firstweekday) % 7 16083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh date -= datetime.timedelta(days=days) 16183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh oneday = datetime.timedelta(days=1) 16283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh while True: 16383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh yield date 16483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 16583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh date += oneday 16683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except OverflowError: 16783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Adding one day could fail after datetime.MAXYEAR 16883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh break 16983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if date.month != month and date.weekday() == self.firstweekday: 17083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh break 17183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 17283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def itermonthdays2(self, year, month): 17383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 17483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Like itermonthdates(), but will yield (day number, weekday number) 17583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh tuples. For days outside the specified month the day number is 0. 17683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 17783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for date in self.itermonthdates(year, month): 17883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if date.month != month: 17983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh yield (0, date.weekday()) 18083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 18183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh yield (date.day, date.weekday()) 18283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 18383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def itermonthdays(self, year, month): 18483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 18583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Like itermonthdates(), but will yield day numbers. For days outside 18683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh the specified month the day number is 0. 18783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 18883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for date in self.itermonthdates(year, month): 18983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if date.month != month: 19083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh yield 0 19183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 19283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh yield date.day 19383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 19483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def monthdatescalendar(self, year, month): 19583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 19683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a matrix (list of lists) representing a month's calendar. 19783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Each row represents a week; week entries are datetime.date values. 19883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 19983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dates = list(self.itermonthdates(year, month)) 20083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return [ dates[i:i+7] for i in range(0, len(dates), 7) ] 20183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 20283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def monthdays2calendar(self, year, month): 20383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 20483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a matrix representing a month's calendar. 20583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Each row represents a week; week entries are 20683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (day number, weekday number) tuples. Day numbers outside this month 20783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh are zero. 20883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 20983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh days = list(self.itermonthdays2(year, month)) 21083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return [ days[i:i+7] for i in range(0, len(days), 7) ] 21183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 21283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def monthdayscalendar(self, year, month): 21383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 21483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a matrix representing a month's calendar. 21583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Each row represents a week; days outside this month are zero. 21683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 21783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh days = list(self.itermonthdays(year, month)) 21883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return [ days[i:i+7] for i in range(0, len(days), 7) ] 21983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 22083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def yeardatescalendar(self, year, width=3): 22183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 22283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return the data for the specified year ready for formatting. The return 22383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh value is a list of month rows. Each month row contains upto width months. 22483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Each month contains between 4 and 6 weeks and each week contains 1-7 22583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh days. Days are datetime.date objects. 22683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 22783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh months = [ 22883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.monthdatescalendar(year, i) 22983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for i in range(January, January+12) 23083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ] 23183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return [months[i:i+width] for i in range(0, len(months), width) ] 23283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 23383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def yeardays2calendar(self, year, width=3): 23483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 23583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return the data for the specified year ready for formatting (similar to 23683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh yeardatescalendar()). Entries in the week lists are 23783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (day number, weekday number) tuples. Day numbers outside this month are 23883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh zero. 23983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 24083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh months = [ 24183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.monthdays2calendar(year, i) 24283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for i in range(January, January+12) 24383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ] 24483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return [months[i:i+width] for i in range(0, len(months), width) ] 24583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 24683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def yeardayscalendar(self, year, width=3): 24783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 24883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return the data for the specified year ready for formatting (similar to 24983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh yeardatescalendar()). Entries in the week lists are day numbers. 25083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Day numbers outside this month are zero. 25183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 25283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh months = [ 25383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.monthdayscalendar(year, i) 25483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for i in range(January, January+12) 25583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ] 25683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return [months[i:i+width] for i in range(0, len(months), width) ] 25783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 25883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 25983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass TextCalendar(Calendar): 26083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 26183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Subclass of Calendar that outputs a calendar as a simple plain text 26283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh similar to the UNIX program cal. 26383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 26483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 26583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def prweek(self, theweek, width): 26683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 26783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Print a single week (no newline). 26883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 26983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print self.formatweek(theweek, width), 27083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 27183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatday(self, day, weekday, width): 27283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 27383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Returns a formatted day. 27483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 27583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if day == 0: 27683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = '' 27783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 27883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = '%2i' % day # right-align single-digit days 27983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return s.center(width) 28083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 28183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatweek(self, theweek, width): 28283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 28383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Returns a single week in a string (no newline). 28483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 28583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return ' '.join(self.formatday(d, wd, width) for (d, wd) in theweek) 28683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 28783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatweekday(self, day, width): 28883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 28983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Returns a formatted week day name. 29083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 29183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if width >= 9: 29283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh names = day_name 29383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 29483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh names = day_abbr 29583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return names[day][:width].center(width) 29683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 29783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatweekheader(self, width): 29883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 29983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a header for a week. 30083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 30183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return ' '.join(self.formatweekday(i, width) for i in self.iterweekdays()) 30283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 30383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatmonthname(self, theyear, themonth, width, withyear=True): 30483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 30583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a formatted month name. 30683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 30783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = month_name[themonth] 30883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if withyear: 30983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = "%s %r" % (s, theyear) 31083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return s.center(width) 31183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 31283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def prmonth(self, theyear, themonth, w=0, l=0): 31383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 31483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Print a month's calendar. 31583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 31683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print self.formatmonth(theyear, themonth, w, l), 31783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 31883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatmonth(self, theyear, themonth, w=0, l=0): 31983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 32083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a month's calendar string (multi-line). 32183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 32283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh w = max(2, w) 32383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh l = max(1, l) 32483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = self.formatmonthname(theyear, themonth, 7 * (w + 1) - 1) 32583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = s.rstrip() 32683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s += '\n' * l 32783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s += self.formatweekheader(w).rstrip() 32883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s += '\n' * l 32983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for week in self.monthdays2calendar(theyear, themonth): 33083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s += self.formatweek(week, w).rstrip() 33183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s += '\n' * l 33283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return s 33383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 33483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatyear(self, theyear, w=2, l=1, c=6, m=3): 33583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 33683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Returns a year's calendar as a multi-line string. 33783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 33883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh w = max(2, w) 33983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh l = max(1, l) 34083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh c = max(2, c) 34183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh colwidth = (w + 1) * 7 - 1 34283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh v = [] 34383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a = v.append 34483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a(repr(theyear).center(colwidth*m+c*(m-1)).rstrip()) 34583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('\n'*l) 34683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh header = self.formatweekheader(w) 34783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for (i, row) in enumerate(self.yeardays2calendar(theyear, m)): 34883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # months in this row 34983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh months = range(m*i+1, min(m*(i+1)+1, 13)) 35083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('\n'*l) 35183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh names = (self.formatmonthname(theyear, k, colwidth, False) 35283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for k in months) 35383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a(formatstring(names, colwidth, c).rstrip()) 35483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('\n'*l) 35583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh headers = (header for k in months) 35683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a(formatstring(headers, colwidth, c).rstrip()) 35783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('\n'*l) 35883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # max number of weeks for this row 35983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh height = max(len(cal) for cal in row) 36083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for j in range(height): 36183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh weeks = [] 36283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for cal in row: 36383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if j >= len(cal): 36483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh weeks.append('') 36583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 36683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh weeks.append(self.formatweek(cal[j], w)) 36783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a(formatstring(weeks, colwidth, c).rstrip()) 36883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('\n' * l) 36983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return ''.join(v) 37083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 37183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def pryear(self, theyear, w=0, l=0, c=6, m=3): 37283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Print a year's calendar.""" 37383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print self.formatyear(theyear, w, l, c, m) 37483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 37583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 37683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass HTMLCalendar(Calendar): 37783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 37883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh This calendar returns complete HTML pages. 37983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 38083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 38183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # CSS classes for the day <td>s 38283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cssclasses = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"] 38383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 38483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatday(self, day, weekday): 38583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 38683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a day as a table cell. 38783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 38883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if day == 0: 38983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return '<td class="noday"> </td>' # day outside month 39083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 39183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return '<td class="%s">%d</td>' % (self.cssclasses[weekday], day) 39283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 39383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatweek(self, theweek): 39483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 39583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a complete week as a table row. 39683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 39783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = ''.join(self.formatday(d, wd) for (d, wd) in theweek) 39883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return '<tr>%s</tr>' % s 39983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 40083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatweekday(self, day): 40183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 40283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a weekday name as a table header. 40383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 40483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return '<th class="%s">%s</th>' % (self.cssclasses[day], day_abbr[day]) 40583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 40683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatweekheader(self): 40783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 40883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a header for a week as a table row. 40983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 41083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = ''.join(self.formatweekday(i) for i in self.iterweekdays()) 41183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return '<tr>%s</tr>' % s 41283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 41383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatmonthname(self, theyear, themonth, withyear=True): 41483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 41583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a month name as a table row. 41683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 41783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if withyear: 41883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = '%s %s' % (month_name[themonth], theyear) 41983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 42083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = '%s' % month_name[themonth] 42183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return '<tr><th colspan="7" class="month">%s</th></tr>' % s 42283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 42383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatmonth(self, theyear, themonth, withyear=True): 42483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 42583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a formatted month as a table. 42683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 42783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh v = [] 42883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a = v.append 42983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<table border="0" cellpadding="0" cellspacing="0" class="month">') 43083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('\n') 43183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a(self.formatmonthname(theyear, themonth, withyear=withyear)) 43283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('\n') 43383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a(self.formatweekheader()) 43483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('\n') 43583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for week in self.monthdays2calendar(theyear, themonth): 43683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a(self.formatweek(week)) 43783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('\n') 43883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('</table>') 43983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('\n') 44083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return ''.join(v) 44183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 44283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatyear(self, theyear, width=3): 44383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 44483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a formatted year as a table of tables. 44583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 44683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh v = [] 44783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a = v.append 44883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh width = max(width, 1) 44983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<table border="0" cellpadding="0" cellspacing="0" class="year">') 45083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('\n') 45183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<tr><th colspan="%d" class="year">%s</th></tr>' % (width, theyear)) 45283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for i in range(January, January+12, width): 45383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # months in this row 45483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh months = range(i, min(i+width, 13)) 45583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<tr>') 45683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for m in months: 45783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<td>') 45883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a(self.formatmonth(theyear, m, withyear=False)) 45983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('</td>') 46083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('</tr>') 46183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('</table>') 46283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return ''.join(v) 46383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 46483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatyearpage(self, theyear, width=3, css='calendar.css', encoding=None): 46583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 46683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return a formatted year as a complete HTML page. 46783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 46883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if encoding is None: 46983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh encoding = sys.getdefaultencoding() 47083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh v = [] 47183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a = v.append 47283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<?xml version="1.0" encoding="%s"?>\n' % encoding) 47383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n') 47483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<html>\n') 47583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<head>\n') 47683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<meta http-equiv="Content-Type" content="text/html; charset=%s" />\n' % encoding) 47783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if css is not None: 47883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<link rel="stylesheet" type="text/css" href="%s" />\n' % css) 47983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<title>Calendar for %d</title>\n' % theyear) 48083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('</head>\n') 48183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('<body>\n') 48283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a(self.formatyear(theyear, width)) 48383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('</body>\n') 48483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh a('</html>\n') 48583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return ''.join(v).encode(encoding, "xmlcharrefreplace") 48683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 48783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 48883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass TimeEncoding: 48983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, locale): 49083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.locale = locale 49183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 49283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __enter__(self): 49383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.oldlocale = _locale.getlocale(_locale.LC_TIME) 49483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _locale.setlocale(_locale.LC_TIME, self.locale) 49583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return _locale.getlocale(_locale.LC_TIME)[1] 49683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 49783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __exit__(self, *args): 49883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _locale.setlocale(_locale.LC_TIME, self.oldlocale) 49983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 50083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 50183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass LocaleTextCalendar(TextCalendar): 50283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 50383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh This class can be passed a locale name in the constructor and will return 50483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh month and weekday names in the specified locale. If this locale includes 50583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh an encoding all strings containing month and weekday names will be returned 50683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh as unicode. 50783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 50883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 50983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, firstweekday=0, locale=None): 51083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh TextCalendar.__init__(self, firstweekday) 51183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if locale is None: 51283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh locale = _locale.getdefaultlocale() 51383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.locale = locale 51483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 51583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatweekday(self, day, width): 51683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh with TimeEncoding(self.locale) as encoding: 51783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if width >= 9: 51883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh names = day_name 51983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 52083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh names = day_abbr 52183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh name = names[day] 52283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if encoding is not None: 52383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh name = name.decode(encoding) 52483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return name[:width].center(width) 52583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 52683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatmonthname(self, theyear, themonth, width, withyear=True): 52783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh with TimeEncoding(self.locale) as encoding: 52883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = month_name[themonth] 52983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if encoding is not None: 53083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = s.decode(encoding) 53183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if withyear: 53283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = "%s %r" % (s, theyear) 53383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return s.center(width) 53483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 53583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 53683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass LocaleHTMLCalendar(HTMLCalendar): 53783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 53883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh This class can be passed a locale name in the constructor and will return 53983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh month and weekday names in the specified locale. If this locale includes 54083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh an encoding all strings containing month and weekday names will be returned 54183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh as unicode. 54283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 54383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, firstweekday=0, locale=None): 54483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh HTMLCalendar.__init__(self, firstweekday) 54583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if locale is None: 54683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh locale = _locale.getdefaultlocale() 54783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.locale = locale 54883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 54983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatweekday(self, day): 55083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh with TimeEncoding(self.locale) as encoding: 55183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = day_abbr[day] 55283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if encoding is not None: 55383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = s.decode(encoding) 55483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return '<th class="%s">%s</th>' % (self.cssclasses[day], s) 55583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 55683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def formatmonthname(self, theyear, themonth, withyear=True): 55783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh with TimeEncoding(self.locale) as encoding: 55883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = month_name[themonth] 55983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if encoding is not None: 56083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = s.decode(encoding) 56183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if withyear: 56283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = '%s %s' % (s, theyear) 56383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return '<tr><th colspan="7" class="month">%s</th></tr>' % s 56483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 56583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 56683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Support for old module level interface 56783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehc = TextCalendar() 56883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 56983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfirstweekday = c.getfirstweekday 57083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 57183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef setfirstweekday(firstweekday): 57283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 57383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh firstweekday.__index__ 57483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except AttributeError: 57583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise IllegalWeekdayError(firstweekday) 57683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not MONDAY <= firstweekday <= SUNDAY: 57783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise IllegalWeekdayError(firstweekday) 57883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh c.firstweekday = firstweekday 57983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 58083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehmonthcalendar = c.monthdayscalendar 58183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehprweek = c.prweek 58283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehweek = c.formatweek 58383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehweekheader = c.formatweekheader 58483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehprmonth = c.prmonth 58583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehmonth = c.formatmonth 58683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehcalendar = c.formatyear 58783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehprcal = c.pryear 58883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 58983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 59083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Spacing of month columns for multi-column year calendar 59183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh_colwidth = 7*3 - 1 # Amount printed by prweek() 59283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh_spacing = 6 # Number of spaces between columns 59383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 59483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 59583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef format(cols, colwidth=_colwidth, spacing=_spacing): 59683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Prints multi-column formatting for year calendars""" 59783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print formatstring(cols, colwidth, spacing) 59883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 59983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 60083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef formatstring(cols, colwidth=_colwidth, spacing=_spacing): 60183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Returns a string formatted from n strings, centered within n columns.""" 60283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh spacing *= ' ' 60383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return spacing.join(c.center(colwidth) for c in cols) 60483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 60583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 60683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehEPOCH = 1970 60783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh_EPOCH_ORD = datetime.date(EPOCH, 1, 1).toordinal() 60883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 60983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 61083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef timegm(tuple): 61183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Unrelated but handy function to calculate Unix timestamp from GMT.""" 61283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh year, month, day, hour, minute, second = tuple[:6] 61383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh days = datetime.date(year, month, 1).toordinal() - _EPOCH_ORD + day - 1 61483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh hours = days*24 + hour 61583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh minutes = hours*60 + minute 61683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh seconds = minutes*60 + second 61783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return seconds 61883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 61983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 62083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef main(args): 62183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import optparse 62283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser = optparse.OptionParser(usage="usage: %prog [options] [year [month]]") 62383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser.add_option( 62483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "-w", "--width", 62583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dest="width", type="int", default=2, 62683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh help="width of date column (default 2, text only)" 62783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 62883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser.add_option( 62983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "-l", "--lines", 63083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dest="lines", type="int", default=1, 63183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh help="number of lines for each week (default 1, text only)" 63283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 63383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser.add_option( 63483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "-s", "--spacing", 63583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dest="spacing", type="int", default=6, 63683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh help="spacing between months (default 6, text only)" 63783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 63883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser.add_option( 63983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "-m", "--months", 64083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dest="months", type="int", default=3, 64183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh help="months per row (default 3, text only)" 64283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 64383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser.add_option( 64483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "-c", "--css", 64583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dest="css", default="calendar.css", 64683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh help="CSS to use for page (html only)" 64783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 64883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser.add_option( 64983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "-L", "--locale", 65083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dest="locale", default=None, 65183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh help="locale to be used from month and weekday names" 65283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 65383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser.add_option( 65483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "-e", "--encoding", 65583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dest="encoding", default=None, 65683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh help="Encoding to use for output" 65783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 65883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser.add_option( 65983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "-t", "--type", 66083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dest="type", default="text", 66183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh choices=("text", "html"), 66283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh help="output type (text or html)" 66383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 66483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 66583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (options, args) = parser.parse_args(args) 66683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 66783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if options.locale and not options.encoding: 66883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser.error("if --locale is specified --encoding is required") 66983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh sys.exit(1) 67083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 67183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh locale = options.locale, options.encoding 67283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 67383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if options.type == "html": 67483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if options.locale: 67583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cal = LocaleHTMLCalendar(locale=locale) 67683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 67783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cal = HTMLCalendar() 67883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh encoding = options.encoding 67983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if encoding is None: 68083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh encoding = sys.getdefaultencoding() 68183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh optdict = dict(encoding=encoding, css=options.css) 68283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if len(args) == 1: 68383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print cal.formatyearpage(datetime.date.today().year, **optdict) 68483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif len(args) == 2: 68583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print cal.formatyearpage(int(args[1]), **optdict) 68683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 68783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser.error("incorrect number of arguments") 68883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh sys.exit(1) 68983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 69083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if options.locale: 69183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cal = LocaleTextCalendar(locale=locale) 69283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 69383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cal = TextCalendar() 69483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh optdict = dict(w=options.width, l=options.lines) 69583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if len(args) != 3: 69683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh optdict["c"] = options.spacing 69783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh optdict["m"] = options.months 69883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if len(args) == 1: 69983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh result = cal.formatyear(datetime.date.today().year, **optdict) 70083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif len(args) == 2: 70183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh result = cal.formatyear(int(args[1]), **optdict) 70283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif len(args) == 3: 70383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh result = cal.formatmonth(int(args[1]), int(args[2]), **optdict) 70483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 70583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parser.error("incorrect number of arguments") 70683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh sys.exit(1) 70783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if options.encoding: 70883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh result = result.encode(options.encoding) 70983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print result 71083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 71183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 71283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehif __name__ == "__main__": 71383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh main(sys.argv) 714