symbian-qemu-0.9.1-12/python-win32-2.6.1/lib/calendar.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """Calendar printing functions
       
     2 
       
     3 Note when comparing these calendars to the ones printed by cal(1): By
       
     4 default, these calendars have Monday as the first day of the week, and
       
     5 Sunday as the last (the European convention). Use setfirstweekday() to
       
     6 set the first day of the week (0=Monday, 6=Sunday)."""
       
     7 
       
     8 import sys
       
     9 import datetime
       
    10 import locale as _locale
       
    11 
       
    12 __all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday",
       
    13            "firstweekday", "isleap", "leapdays", "weekday", "monthrange",
       
    14            "monthcalendar", "prmonth", "month", "prcal", "calendar",
       
    15            "timegm", "month_name", "month_abbr", "day_name", "day_abbr"]
       
    16 
       
    17 # Exception raised for bad input (with string parameter for details)
       
    18 error = ValueError
       
    19 
       
    20 # Exceptions raised for bad input
       
    21 class IllegalMonthError(ValueError):
       
    22     def __init__(self, month):
       
    23         self.month = month
       
    24     def __str__(self):
       
    25         return "bad month number %r; must be 1-12" % self.month
       
    26 
       
    27 
       
    28 class IllegalWeekdayError(ValueError):
       
    29     def __init__(self, weekday):
       
    30         self.weekday = weekday
       
    31     def __str__(self):
       
    32         return "bad weekday number %r; must be 0 (Monday) to 6 (Sunday)" % self.weekday
       
    33 
       
    34 
       
    35 # Constants for months referenced later
       
    36 January = 1
       
    37 February = 2
       
    38 
       
    39 # Number of days per month (except for February in leap years)
       
    40 mdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
       
    41 
       
    42 # This module used to have hard-coded lists of day and month names, as
       
    43 # English strings.  The classes following emulate a read-only version of
       
    44 # that, but supply localized names.  Note that the values are computed
       
    45 # fresh on each call, in case the user changes locale between calls.
       
    46 
       
    47 class _localized_month:
       
    48 
       
    49     _months = [datetime.date(2001, i+1, 1).strftime for i in range(12)]
       
    50     _months.insert(0, lambda x: "")
       
    51 
       
    52     def __init__(self, format):
       
    53         self.format = format
       
    54 
       
    55     def __getitem__(self, i):
       
    56         funcs = self._months[i]
       
    57         if isinstance(i, slice):
       
    58             return [f(self.format) for f in funcs]
       
    59         else:
       
    60             return funcs(self.format)
       
    61 
       
    62     def __len__(self):
       
    63         return 13
       
    64 
       
    65 
       
    66 class _localized_day:
       
    67 
       
    68     # January 1, 2001, was a Monday.
       
    69     _days = [datetime.date(2001, 1, i+1).strftime for i in range(7)]
       
    70 
       
    71     def __init__(self, format):
       
    72         self.format = format
       
    73 
       
    74     def __getitem__(self, i):
       
    75         funcs = self._days[i]
       
    76         if isinstance(i, slice):
       
    77             return [f(self.format) for f in funcs]
       
    78         else:
       
    79             return funcs(self.format)
       
    80 
       
    81     def __len__(self):
       
    82         return 7
       
    83 
       
    84 
       
    85 # Full and abbreviated names of weekdays
       
    86 day_name = _localized_day('%A')
       
    87 day_abbr = _localized_day('%a')
       
    88 
       
    89 # Full and abbreviated names of months (1-based arrays!!!)
       
    90 month_name = _localized_month('%B')
       
    91 month_abbr = _localized_month('%b')
       
    92 
       
    93 # Constants for weekdays
       
    94 (MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7)
       
    95 
       
    96 
       
    97 def isleap(year):
       
    98     """Return 1 for leap years, 0 for non-leap years."""
       
    99     return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
       
   100 
       
   101 
       
   102 def leapdays(y1, y2):
       
   103     """Return number of leap years in range [y1, y2).
       
   104        Assume y1 <= y2."""
       
   105     y1 -= 1
       
   106     y2 -= 1
       
   107     return (y2//4 - y1//4) - (y2//100 - y1//100) + (y2//400 - y1//400)
       
   108 
       
   109 
       
   110 def weekday(year, month, day):
       
   111     """Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12),
       
   112        day (1-31)."""
       
   113     return datetime.date(year, month, day).weekday()
       
   114 
       
   115 
       
   116 def monthrange(year, month):
       
   117     """Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for
       
   118        year, month."""
       
   119     if not 1 <= month <= 12:
       
   120         raise IllegalMonthError(month)
       
   121     day1 = weekday(year, month, 1)
       
   122     ndays = mdays[month] + (month == February and isleap(year))
       
   123     return day1, ndays
       
   124 
       
   125 
       
   126 class Calendar(object):
       
   127     """
       
   128     Base calendar class. This class doesn't do any formatting. It simply
       
   129     provides data to subclasses.
       
   130     """
       
   131 
       
   132     def __init__(self, firstweekday=0):
       
   133         self.firstweekday = firstweekday # 0 = Monday, 6 = Sunday
       
   134 
       
   135     def getfirstweekday(self):
       
   136         return self._firstweekday % 7
       
   137 
       
   138     def setfirstweekday(self, firstweekday):
       
   139         self._firstweekday = firstweekday
       
   140 
       
   141     firstweekday = property(getfirstweekday, setfirstweekday)
       
   142 
       
   143     def iterweekdays(self):
       
   144         """
       
   145         Return a iterator for one week of weekday numbers starting with the
       
   146         configured first one.
       
   147         """
       
   148         for i in range(self.firstweekday, self.firstweekday + 7):
       
   149             yield i%7
       
   150 
       
   151     def itermonthdates(self, year, month):
       
   152         """
       
   153         Return an iterator for one month. The iterator will yield datetime.date
       
   154         values and will always iterate through complete weeks, so it will yield
       
   155         dates outside the specified month.
       
   156         """
       
   157         date = datetime.date(year, month, 1)
       
   158         # Go back to the beginning of the week
       
   159         days = (date.weekday() - self.firstweekday) % 7
       
   160         date -= datetime.timedelta(days=days)
       
   161         oneday = datetime.timedelta(days=1)
       
   162         while True:
       
   163             yield date
       
   164             date += oneday
       
   165             if date.month != month and date.weekday() == self.firstweekday:
       
   166                 break
       
   167 
       
   168     def itermonthdays2(self, year, month):
       
   169         """
       
   170         Like itermonthdates(), but will yield (day number, weekday number)
       
   171         tuples. For days outside the specified month the day number is 0.
       
   172         """
       
   173         for date in self.itermonthdates(year, month):
       
   174             if date.month != month:
       
   175                 yield (0, date.weekday())
       
   176             else:
       
   177                 yield (date.day, date.weekday())
       
   178 
       
   179     def itermonthdays(self, year, month):
       
   180         """
       
   181         Like itermonthdates(), but will yield day numbers. For days outside
       
   182         the specified month the day number is 0.
       
   183         """
       
   184         for date in self.itermonthdates(year, month):
       
   185             if date.month != month:
       
   186                 yield 0
       
   187             else:
       
   188                 yield date.day
       
   189 
       
   190     def monthdatescalendar(self, year, month):
       
   191         """
       
   192         Return a matrix (list of lists) representing a month's calendar.
       
   193         Each row represents a week; week entries are datetime.date values.
       
   194         """
       
   195         dates = list(self.itermonthdates(year, month))
       
   196         return [ dates[i:i+7] for i in range(0, len(dates), 7) ]
       
   197 
       
   198     def monthdays2calendar(self, year, month):
       
   199         """
       
   200         Return a matrix representing a month's calendar.
       
   201         Each row represents a week; week entries are
       
   202         (day number, weekday number) tuples. Day numbers outside this month
       
   203         are zero.
       
   204         """
       
   205         days = list(self.itermonthdays2(year, month))
       
   206         return [ days[i:i+7] for i in range(0, len(days), 7) ]
       
   207 
       
   208     def monthdayscalendar(self, year, month):
       
   209         """
       
   210         Return a matrix representing a month's calendar.
       
   211         Each row represents a week; days outside this month are zero.
       
   212         """
       
   213         days = list(self.itermonthdays(year, month))
       
   214         return [ days[i:i+7] for i in range(0, len(days), 7) ]
       
   215 
       
   216     def yeardatescalendar(self, year, width=3):
       
   217         """
       
   218         Return the data for the specified year ready for formatting. The return
       
   219         value is a list of month rows. Each month row contains upto width months.
       
   220         Each month contains between 4 and 6 weeks and each week contains 1-7
       
   221         days. Days are datetime.date objects.
       
   222         """
       
   223         months = [
       
   224             self.monthdatescalendar(year, i)
       
   225             for i in range(January, January+12)
       
   226         ]
       
   227         return [months[i:i+width] for i in range(0, len(months), width) ]
       
   228 
       
   229     def yeardays2calendar(self, year, width=3):
       
   230         """
       
   231         Return the data for the specified year ready for formatting (similar to
       
   232         yeardatescalendar()). Entries in the week lists are
       
   233         (day number, weekday number) tuples. Day numbers outside this month are
       
   234         zero.
       
   235         """
       
   236         months = [
       
   237             self.monthdays2calendar(year, i)
       
   238             for i in range(January, January+12)
       
   239         ]
       
   240         return [months[i:i+width] for i in range(0, len(months), width) ]
       
   241 
       
   242     def yeardayscalendar(self, year, width=3):
       
   243         """
       
   244         Return the data for the specified year ready for formatting (similar to
       
   245         yeardatescalendar()). Entries in the week lists are day numbers.
       
   246         Day numbers outside this month are zero.
       
   247         """
       
   248         months = [
       
   249             self.monthdayscalendar(year, i)
       
   250             for i in range(January, January+12)
       
   251         ]
       
   252         return [months[i:i+width] for i in range(0, len(months), width) ]
       
   253 
       
   254 
       
   255 class TextCalendar(Calendar):
       
   256     """
       
   257     Subclass of Calendar that outputs a calendar as a simple plain text
       
   258     similar to the UNIX program cal.
       
   259     """
       
   260 
       
   261     def prweek(self, theweek, width):
       
   262         """
       
   263         Print a single week (no newline).
       
   264         """
       
   265         print self.formatweek(theweek, width),
       
   266 
       
   267     def formatday(self, day, weekday, width):
       
   268         """
       
   269         Returns a formatted day.
       
   270         """
       
   271         if day == 0:
       
   272             s = ''
       
   273         else:
       
   274             s = '%2i' % day             # right-align single-digit days
       
   275         return s.center(width)
       
   276 
       
   277     def formatweek(self, theweek, width):
       
   278         """
       
   279         Returns a single week in a string (no newline).
       
   280         """
       
   281         return ' '.join(self.formatday(d, wd, width) for (d, wd) in theweek)
       
   282 
       
   283     def formatweekday(self, day, width):
       
   284         """
       
   285         Returns a formatted week day name.
       
   286         """
       
   287         if width >= 9:
       
   288             names = day_name
       
   289         else:
       
   290             names = day_abbr
       
   291         return names[day][:width].center(width)
       
   292 
       
   293     def formatweekheader(self, width):
       
   294         """
       
   295         Return a header for a week.
       
   296         """
       
   297         return ' '.join(self.formatweekday(i, width) for i in self.iterweekdays())
       
   298 
       
   299     def formatmonthname(self, theyear, themonth, width, withyear=True):
       
   300         """
       
   301         Return a formatted month name.
       
   302         """
       
   303         s = month_name[themonth]
       
   304         if withyear:
       
   305             s = "%s %r" % (s, theyear)
       
   306         return s.center(width)
       
   307 
       
   308     def prmonth(self, theyear, themonth, w=0, l=0):
       
   309         """
       
   310         Print a month's calendar.
       
   311         """
       
   312         print self.formatmonth(theyear, themonth, w, l),
       
   313 
       
   314     def formatmonth(self, theyear, themonth, w=0, l=0):
       
   315         """
       
   316         Return a month's calendar string (multi-line).
       
   317         """
       
   318         w = max(2, w)
       
   319         l = max(1, l)
       
   320         s = self.formatmonthname(theyear, themonth, 7 * (w + 1) - 1)
       
   321         s = s.rstrip()
       
   322         s += '\n' * l
       
   323         s += self.formatweekheader(w).rstrip()
       
   324         s += '\n' * l
       
   325         for week in self.monthdays2calendar(theyear, themonth):
       
   326             s += self.formatweek(week, w).rstrip()
       
   327             s += '\n' * l
       
   328         return s
       
   329 
       
   330     def formatyear(self, theyear, w=2, l=1, c=6, m=3):
       
   331         """
       
   332         Returns a year's calendar as a multi-line string.
       
   333         """
       
   334         w = max(2, w)
       
   335         l = max(1, l)
       
   336         c = max(2, c)
       
   337         colwidth = (w + 1) * 7 - 1
       
   338         v = []
       
   339         a = v.append
       
   340         a(repr(theyear).center(colwidth*m+c*(m-1)).rstrip())
       
   341         a('\n'*l)
       
   342         header = self.formatweekheader(w)
       
   343         for (i, row) in enumerate(self.yeardays2calendar(theyear, m)):
       
   344             # months in this row
       
   345             months = range(m*i+1, min(m*(i+1)+1, 13))
       
   346             a('\n'*l)
       
   347             names = (self.formatmonthname(theyear, k, colwidth, False)
       
   348                      for k in months)
       
   349             a(formatstring(names, colwidth, c).rstrip())
       
   350             a('\n'*l)
       
   351             headers = (header for k in months)
       
   352             a(formatstring(headers, colwidth, c).rstrip())
       
   353             a('\n'*l)
       
   354             # max number of weeks for this row
       
   355             height = max(len(cal) for cal in row)
       
   356             for j in range(height):
       
   357                 weeks = []
       
   358                 for cal in row:
       
   359                     if j >= len(cal):
       
   360                         weeks.append('')
       
   361                     else:
       
   362                         weeks.append(self.formatweek(cal[j], w))
       
   363                 a(formatstring(weeks, colwidth, c).rstrip())
       
   364                 a('\n' * l)
       
   365         return ''.join(v)
       
   366 
       
   367     def pryear(self, theyear, w=0, l=0, c=6, m=3):
       
   368         """Print a year's calendar."""
       
   369         print self.formatyear(theyear, w, l, c, m)
       
   370 
       
   371 
       
   372 class HTMLCalendar(Calendar):
       
   373     """
       
   374     This calendar returns complete HTML pages.
       
   375     """
       
   376 
       
   377     # CSS classes for the day <td>s
       
   378     cssclasses = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
       
   379 
       
   380     def formatday(self, day, weekday):
       
   381         """
       
   382         Return a day as a table cell.
       
   383         """
       
   384         if day == 0:
       
   385             return '<td class="noday">&nbsp;</td>' # day outside month
       
   386         else:
       
   387             return '<td class="%s">%d</td>' % (self.cssclasses[weekday], day)
       
   388 
       
   389     def formatweek(self, theweek):
       
   390         """
       
   391         Return a complete week as a table row.
       
   392         """
       
   393         s = ''.join(self.formatday(d, wd) for (d, wd) in theweek)
       
   394         return '<tr>%s</tr>' % s
       
   395 
       
   396     def formatweekday(self, day):
       
   397         """
       
   398         Return a weekday name as a table header.
       
   399         """
       
   400         return '<th class="%s">%s</th>' % (self.cssclasses[day], day_abbr[day])
       
   401 
       
   402     def formatweekheader(self):
       
   403         """
       
   404         Return a header for a week as a table row.
       
   405         """
       
   406         s = ''.join(self.formatweekday(i) for i in self.iterweekdays())
       
   407         return '<tr>%s</tr>' % s
       
   408 
       
   409     def formatmonthname(self, theyear, themonth, withyear=True):
       
   410         """
       
   411         Return a month name as a table row.
       
   412         """
       
   413         if withyear:
       
   414             s = '%s %s' % (month_name[themonth], theyear)
       
   415         else:
       
   416             s = '%s' % month_name[themonth]
       
   417         return '<tr><th colspan="7" class="month">%s</th></tr>' % s
       
   418 
       
   419     def formatmonth(self, theyear, themonth, withyear=True):
       
   420         """
       
   421         Return a formatted month as a table.
       
   422         """
       
   423         v = []
       
   424         a = v.append
       
   425         a('<table border="0" cellpadding="0" cellspacing="0" class="month">')
       
   426         a('\n')
       
   427         a(self.formatmonthname(theyear, themonth, withyear=withyear))
       
   428         a('\n')
       
   429         a(self.formatweekheader())
       
   430         a('\n')
       
   431         for week in self.monthdays2calendar(theyear, themonth):
       
   432             a(self.formatweek(week))
       
   433             a('\n')
       
   434         a('</table>')
       
   435         a('\n')
       
   436         return ''.join(v)
       
   437 
       
   438     def formatyear(self, theyear, width=3):
       
   439         """
       
   440         Return a formatted year as a table of tables.
       
   441         """
       
   442         v = []
       
   443         a = v.append
       
   444         width = max(width, 1)
       
   445         a('<table border="0" cellpadding="0" cellspacing="0" class="year">')
       
   446         a('\n')
       
   447         a('<tr><th colspan="%d" class="year">%s</th></tr>' % (width, theyear))
       
   448         for i in range(January, January+12, width):
       
   449             # months in this row
       
   450             months = range(i, min(i+width, 13))
       
   451             a('<tr>')
       
   452             for m in months:
       
   453                 a('<td>')
       
   454                 a(self.formatmonth(theyear, m, withyear=False))
       
   455                 a('</td>')
       
   456             a('</tr>')
       
   457         a('</table>')
       
   458         return ''.join(v)
       
   459 
       
   460     def formatyearpage(self, theyear, width=3, css='calendar.css', encoding=None):
       
   461         """
       
   462         Return a formatted year as a complete HTML page.
       
   463         """
       
   464         if encoding is None:
       
   465             encoding = sys.getdefaultencoding()
       
   466         v = []
       
   467         a = v.append
       
   468         a('<?xml version="1.0" encoding="%s"?>\n' % encoding)
       
   469         a('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n')
       
   470         a('<html>\n')
       
   471         a('<head>\n')
       
   472         a('<meta http-equiv="Content-Type" content="text/html; charset=%s" />\n' % encoding)
       
   473         if css is not None:
       
   474             a('<link rel="stylesheet" type="text/css" href="%s" />\n' % css)
       
   475         a('<title>Calendar for %d</title>\n' % theyear)
       
   476         a('</head>\n')
       
   477         a('<body>\n')
       
   478         a(self.formatyear(theyear, width))
       
   479         a('</body>\n')
       
   480         a('</html>\n')
       
   481         return ''.join(v).encode(encoding, "xmlcharrefreplace")
       
   482 
       
   483 
       
   484 class TimeEncoding:
       
   485     def __init__(self, locale):
       
   486         self.locale = locale
       
   487 
       
   488     def __enter__(self):
       
   489         self.oldlocale = _locale.setlocale(_locale.LC_TIME, self.locale)
       
   490         return _locale.getlocale(_locale.LC_TIME)[1]
       
   491 
       
   492     def __exit__(self, *args):
       
   493         _locale.setlocale(_locale.LC_TIME, self.oldlocale)
       
   494 
       
   495 
       
   496 class LocaleTextCalendar(TextCalendar):
       
   497     """
       
   498     This class can be passed a locale name in the constructor and will return
       
   499     month and weekday names in the specified locale. If this locale includes
       
   500     an encoding all strings containing month and weekday names will be returned
       
   501     as unicode.
       
   502     """
       
   503 
       
   504     def __init__(self, firstweekday=0, locale=None):
       
   505         TextCalendar.__init__(self, firstweekday)
       
   506         if locale is None:
       
   507             locale = _locale.getdefaultlocale()
       
   508         self.locale = locale
       
   509 
       
   510     def formatweekday(self, day, width):
       
   511         with TimeEncoding(self.locale) as encoding:
       
   512             if width >= 9:
       
   513                 names = day_name
       
   514             else:
       
   515                 names = day_abbr
       
   516             name = names[day]
       
   517             if encoding is not None:
       
   518                 name = name.decode(encoding)
       
   519             return name[:width].center(width)
       
   520 
       
   521     def formatmonthname(self, theyear, themonth, width, withyear=True):
       
   522         with TimeEncoding(self.locale) as encoding:
       
   523             s = month_name[themonth]
       
   524             if encoding is not None:
       
   525                 s = s.decode(encoding)
       
   526             if withyear:
       
   527                 s = "%s %r" % (s, theyear)
       
   528             return s.center(width)
       
   529 
       
   530 
       
   531 class LocaleHTMLCalendar(HTMLCalendar):
       
   532     """
       
   533     This class can be passed a locale name in the constructor and will return
       
   534     month and weekday names in the specified locale. If this locale includes
       
   535     an encoding all strings containing month and weekday names will be returned
       
   536     as unicode.
       
   537     """
       
   538     def __init__(self, firstweekday=0, locale=None):
       
   539         HTMLCalendar.__init__(self, firstweekday)
       
   540         if locale is None:
       
   541             locale = _locale.getdefaultlocale()
       
   542         self.locale = locale
       
   543 
       
   544     def formatweekday(self, day):
       
   545         with TimeEncoding(self.locale) as encoding:
       
   546             s = day_abbr[day]
       
   547             if encoding is not None:
       
   548                 s = s.decode(encoding)
       
   549             return '<th class="%s">%s</th>' % (self.cssclasses[day], s)
       
   550 
       
   551     def formatmonthname(self, theyear, themonth, withyear=True):
       
   552         with TimeEncoding(self.locale) as encoding:
       
   553             s = month_name[themonth]
       
   554             if encoding is not None:
       
   555                 s = s.decode(encoding)
       
   556             if withyear:
       
   557                 s = '%s %s' % (s, theyear)
       
   558             return '<tr><th colspan="7" class="month">%s</th></tr>' % s
       
   559 
       
   560 
       
   561 # Support for old module level interface
       
   562 c = TextCalendar()
       
   563 
       
   564 firstweekday = c.getfirstweekday
       
   565 
       
   566 def setfirstweekday(firstweekday):
       
   567     if not MONDAY <= firstweekday <= SUNDAY:
       
   568         raise IllegalWeekdayError(firstweekday)
       
   569     c.firstweekday = firstweekday
       
   570 
       
   571 monthcalendar = c.monthdayscalendar
       
   572 prweek = c.prweek
       
   573 week = c.formatweek
       
   574 weekheader = c.formatweekheader
       
   575 prmonth = c.prmonth
       
   576 month = c.formatmonth
       
   577 calendar = c.formatyear
       
   578 prcal = c.pryear
       
   579 
       
   580 
       
   581 # Spacing of month columns for multi-column year calendar
       
   582 _colwidth = 7*3 - 1         # Amount printed by prweek()
       
   583 _spacing = 6                # Number of spaces between columns
       
   584 
       
   585 
       
   586 def format(cols, colwidth=_colwidth, spacing=_spacing):
       
   587     """Prints multi-column formatting for year calendars"""
       
   588     print formatstring(cols, colwidth, spacing)
       
   589 
       
   590 
       
   591 def formatstring(cols, colwidth=_colwidth, spacing=_spacing):
       
   592     """Returns a string formatted from n strings, centered within n columns."""
       
   593     spacing *= ' '
       
   594     return spacing.join(c.center(colwidth) for c in cols)
       
   595 
       
   596 
       
   597 EPOCH = 1970
       
   598 _EPOCH_ORD = datetime.date(EPOCH, 1, 1).toordinal()
       
   599 
       
   600 
       
   601 def timegm(tuple):
       
   602     """Unrelated but handy function to calculate Unix timestamp from GMT."""
       
   603     year, month, day, hour, minute, second = tuple[:6]
       
   604     days = datetime.date(year, month, 1).toordinal() - _EPOCH_ORD + day - 1
       
   605     hours = days*24 + hour
       
   606     minutes = hours*60 + minute
       
   607     seconds = minutes*60 + second
       
   608     return seconds
       
   609 
       
   610 
       
   611 def main(args):
       
   612     import optparse
       
   613     parser = optparse.OptionParser(usage="usage: %prog [options] [year [month]]")
       
   614     parser.add_option(
       
   615         "-w", "--width",
       
   616         dest="width", type="int", default=2,
       
   617         help="width of date column (default 2, text only)"
       
   618     )
       
   619     parser.add_option(
       
   620         "-l", "--lines",
       
   621         dest="lines", type="int", default=1,
       
   622         help="number of lines for each week (default 1, text only)"
       
   623     )
       
   624     parser.add_option(
       
   625         "-s", "--spacing",
       
   626         dest="spacing", type="int", default=6,
       
   627         help="spacing between months (default 6, text only)"
       
   628     )
       
   629     parser.add_option(
       
   630         "-m", "--months",
       
   631         dest="months", type="int", default=3,
       
   632         help="months per row (default 3, text only)"
       
   633     )
       
   634     parser.add_option(
       
   635         "-c", "--css",
       
   636         dest="css", default="calendar.css",
       
   637         help="CSS to use for page (html only)"
       
   638     )
       
   639     parser.add_option(
       
   640         "-L", "--locale",
       
   641         dest="locale", default=None,
       
   642         help="locale to be used from month and weekday names"
       
   643     )
       
   644     parser.add_option(
       
   645         "-e", "--encoding",
       
   646         dest="encoding", default=None,
       
   647         help="Encoding to use for output"
       
   648     )
       
   649     parser.add_option(
       
   650         "-t", "--type",
       
   651         dest="type", default="text",
       
   652         choices=("text", "html"),
       
   653         help="output type (text or html)"
       
   654     )
       
   655 
       
   656     (options, args) = parser.parse_args(args)
       
   657 
       
   658     if options.locale and not options.encoding:
       
   659         parser.error("if --locale is specified --encoding is required")
       
   660         sys.exit(1)
       
   661 
       
   662     locale = options.locale, options.encoding
       
   663 
       
   664     if options.type == "html":
       
   665         if options.locale:
       
   666             cal = LocaleHTMLCalendar(locale=locale)
       
   667         else:
       
   668             cal = HTMLCalendar()
       
   669         encoding = options.encoding
       
   670         if encoding is None:
       
   671             encoding = sys.getdefaultencoding()
       
   672         optdict = dict(encoding=encoding, css=options.css)
       
   673         if len(args) == 1:
       
   674             print cal.formatyearpage(datetime.date.today().year, **optdict)
       
   675         elif len(args) == 2:
       
   676             print cal.formatyearpage(int(args[1]), **optdict)
       
   677         else:
       
   678             parser.error("incorrect number of arguments")
       
   679             sys.exit(1)
       
   680     else:
       
   681         if options.locale:
       
   682             cal = LocaleTextCalendar(locale=locale)
       
   683         else:
       
   684             cal = TextCalendar()
       
   685         optdict = dict(w=options.width, l=options.lines)
       
   686         if len(args) != 3:
       
   687             optdict["c"] = options.spacing
       
   688             optdict["m"] = options.months
       
   689         if len(args) == 1:
       
   690             result = cal.formatyear(datetime.date.today().year, **optdict)
       
   691         elif len(args) == 2:
       
   692             result = cal.formatyear(int(args[1]), **optdict)
       
   693         elif len(args) == 3:
       
   694             result = cal.formatmonth(int(args[1]), int(args[2]), **optdict)
       
   695         else:
       
   696             parser.error("incorrect number of arguments")
       
   697             sys.exit(1)
       
   698         if options.encoding:
       
   699             result = result.encode(options.encoding)
       
   700         print result
       
   701 
       
   702 
       
   703 if __name__ == "__main__":
       
   704     main(sys.argv)