Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
calendar.py927 linesDownload Raw Back to Lib
1"""Calendar printing functions2 3Note when comparing these calendars to the ones printed by cal(1): By4default, these calendars have Monday as the first day of the week, and5Sunday as the last (the European convention). Use setfirstweekday() to6set the first day of the week (0=Monday, 6=Sunday)."""7 8import sys9import datetime10from enum import IntEnum, global_enum11import locale as _locale12from itertools import repeat13 14__all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday",15           "firstweekday", "isleap", "leapdays", "weekday", "monthrange",16           "monthcalendar", "prmonth", "month", "prcal", "calendar",17           "timegm", "month_name", "month_abbr", "day_name", "day_abbr",18           "Calendar", "TextCalendar", "HTMLCalendar", "LocaleTextCalendar",19           "LocaleHTMLCalendar", "weekheader",20           "Day", "Month", "JANUARY", "FEBRUARY", "MARCH",21           "APRIL", "MAY", "JUNE", "JULY",22           "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",23           "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY",24           "SATURDAY", "SUNDAY"]25 26# Exception raised for bad input (with string parameter for details)27error = ValueError28 29# Exceptions raised for bad input30# This is trick for backward compatibility. Since 3.13, we will raise IllegalMonthError instead of31# IndexError for bad month number(out of 1-12). But we can't remove IndexError for backward compatibility.32class IllegalMonthError(ValueError, IndexError):33    def __init__(self, month):34        self.month = month35    def __str__(self):36        return "bad month number %r; must be 1-12" % self.month37 38 39class IllegalWeekdayError(ValueError):40    def __init__(self, weekday):41        self.weekday = weekday42    def __str__(self):43        return "bad weekday number %r; must be 0 (Monday) to 6 (Sunday)" % self.weekday44 45 46def __getattr__(name):47    if name in ('January', 'February'):48        import warnings49        warnings.warn(f"The '{name}' attribute is deprecated, use '{name.upper()}' instead",50                      DeprecationWarning, stacklevel=2)51        if name == 'January':52            return 153        else:54            return 255 56    raise AttributeError(f"module '{__name__}' has no attribute '{name}'")57 58 59# Constants for months60@global_enum61class Month(IntEnum):62    JANUARY = 163    FEBRUARY = 264    MARCH = 365    APRIL = 466    MAY = 567    JUNE = 668    JULY = 769    AUGUST = 870    SEPTEMBER = 971    OCTOBER = 1072    NOVEMBER = 1173    DECEMBER = 1274 75 76# Constants for days77@global_enum78class Day(IntEnum):79    MONDAY = 080    TUESDAY = 181    WEDNESDAY = 282    THURSDAY = 383    FRIDAY = 484    SATURDAY = 585    SUNDAY = 686 87 88# Number of days per month (except for February in leap years)89mdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]90 91# This module used to have hard-coded lists of day and month names, as92# English strings.  The classes following emulate a read-only version of93# that, but supply localized names.  Note that the values are computed94# fresh on each call, in case the user changes locale between calls.95 96class _localized_month:97 98    _months = [datetime.date(2001, i+1, 1).strftime for i in range(12)]99    _months.insert(0, lambda x: "")100 101    def __init__(self, format):102        self.format = format103 104    def __getitem__(self, i):105        funcs = self._months[i]106        if isinstance(i, slice):107            return [f(self.format) for f in funcs]108        else:109            return funcs(self.format)110 111    def __len__(self):112        return 13113 114 115class _localized_day:116 117    # January 1, 2001, was a Monday.118    _days = [datetime.date(2001, 1, i+1).strftime for i in range(7)]119 120    def __init__(self, format):121        self.format = format122 123    def __getitem__(self, i):124        funcs = self._days[i]125        if isinstance(i, slice):126            return [f(self.format) for f in funcs]127        else:128            return funcs(self.format)129 130    def __len__(self):131        return 7132 133 134# Full and abbreviated names of weekdays135day_name = _localized_day('%A')136day_abbr = _localized_day('%a')137 138# Full and abbreviated names of months (1-based arrays!!!)139month_name = _localized_month('%B')140month_abbr = _localized_month('%b')141 142 143def isleap(year):144    """Return True for leap years, False for non-leap years."""145    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)146 147 148def leapdays(y1, y2):149    """Return number of leap years in range [y1, y2).150       Assume y1 <= y2."""151    y1 -= 1152    y2 -= 1153    return (y2//4 - y1//4) - (y2//100 - y1//100) + (y2//400 - y1//400)154 155 156def weekday(year, month, day):157    """Return weekday (0-6 ~ Mon-Sun) for year, month (1-12), day (1-31)."""158    if not datetime.MINYEAR <= year <= datetime.MAXYEAR:159        year = 2000 + year % 400160    return Day(datetime.date(year, month, day).weekday())161 162 163def _validate_month(month):164    if not 1 <= month <= 12:165        raise IllegalMonthError(month)166 167def monthrange(year, month):168    """Return weekday of first day of month (0-6 ~ Mon-Sun)169       and number of days (28-31) for year, month."""170    _validate_month(month)171    day1 = weekday(year, month, 1)172    ndays = mdays[month] + (month == FEBRUARY and isleap(year))173    return day1, ndays174 175 176def _monthlen(year, month):177    return mdays[month] + (month == FEBRUARY and isleap(year))178 179 180def _prevmonth(year, month):181    if month == 1:182        return year-1, 12183    else:184        return year, month-1185 186 187def _nextmonth(year, month):188    if month == 12:189        return year+1, 1190    else:191        return year, month+1192 193 194class Calendar(object):195    """196    Base calendar class. This class doesn't do any formatting. It simply197    provides data to subclasses.198    """199 200    def __init__(self, firstweekday=0):201        self.firstweekday = firstweekday # 0 = Monday, 6 = Sunday202 203    def getfirstweekday(self):204        return self._firstweekday % 7205 206    def setfirstweekday(self, firstweekday):207        self._firstweekday = firstweekday208 209    firstweekday = property(getfirstweekday, setfirstweekday)210 211    def iterweekdays(self):212        """213        Return an iterator for one week of weekday numbers starting with the214        configured first one.215        """216        for i in range(self.firstweekday, self.firstweekday + 7):217            yield i%7218 219    def itermonthdates(self, year, month):220        """221        Return an iterator for one month. The iterator will yield datetime.date222        values and will always iterate through complete weeks, so it will yield223        dates outside the specified month.224        """225        for y, m, d in self.itermonthdays3(year, month):226            yield datetime.date(y, m, d)227 228    def itermonthdays(self, year, month):229        """230        Like itermonthdates(), but will yield day numbers. For days outside231        the specified month the day number is 0.232        """233        day1, ndays = monthrange(year, month)234        days_before = (day1 - self.firstweekday) % 7235        yield from repeat(0, days_before)236        yield from range(1, ndays + 1)237        days_after = (self.firstweekday - day1 - ndays) % 7238        yield from repeat(0, days_after)239 240    def itermonthdays2(self, year, month):241        """242        Like itermonthdates(), but will yield (day number, weekday number)243        tuples. For days outside the specified month the day number is 0.244        """245        for i, d in enumerate(self.itermonthdays(year, month), self.firstweekday):246            yield d, i % 7247 248    def itermonthdays3(self, year, month):249        """250        Like itermonthdates(), but will yield (year, month, day) tuples.  Can be251        used for dates outside of datetime.date range.252        """253        day1, ndays = monthrange(year, month)254        days_before = (day1 - self.firstweekday) % 7255        days_after = (self.firstweekday - day1 - ndays) % 7256        y, m = _prevmonth(year, month)257        end = _monthlen(y, m) + 1258        for d in range(end-days_before, end):259            yield y, m, d260        for d in range(1, ndays + 1):261            yield year, month, d262        y, m = _nextmonth(year, month)263        for d in range(1, days_after + 1):264            yield y, m, d265 266    def itermonthdays4(self, year, month):267        """268        Like itermonthdates(), but will yield (year, month, day, day_of_week) tuples.269        Can be used for dates outside of datetime.date range.270        """271        for i, (y, m, d) in enumerate(self.itermonthdays3(year, month)):272            yield y, m, d, (self.firstweekday + i) % 7273 274    def monthdatescalendar(self, year, month):275        """276        Return a matrix (list of lists) representing a month's calendar.277        Each row represents a week; week entries are datetime.date values.278        """279        dates = list(self.itermonthdates(year, month))280        return [ dates[i:i+7] for i in range(0, len(dates), 7) ]281 282    def monthdays2calendar(self, year, month):283        """284        Return a matrix representing a month's calendar.285        Each row represents a week; week entries are286        (day number, weekday number) tuples. Day numbers outside this month287        are zero.288        """289        days = list(self.itermonthdays2(year, month))290        return [ days[i:i+7] for i in range(0, len(days), 7) ]291 292    def monthdayscalendar(self, year, month):293        """294        Return a matrix representing a month's calendar.295        Each row represents a week; days outside this month are zero.296        """297        days = list(self.itermonthdays(year, month))298        return [ days[i:i+7] for i in range(0, len(days), 7) ]299 300    def yeardatescalendar(self, year, width=3):301        """302        Return the data for the specified year ready for formatting. The return303        value is a list of month rows. Each month row contains up to width months.304        Each month contains between 4 and 6 weeks and each week contains 1-7305        days. Days are datetime.date objects.306        """307        months = [self.monthdatescalendar(year, m) for m in Month]308        return [months[i:i+width] for i in range(0, len(months), width) ]309 310    def yeardays2calendar(self, year, width=3):311        """312        Return the data for the specified year ready for formatting (similar to313        yeardatescalendar()). Entries in the week lists are314        (day number, weekday number) tuples. Day numbers outside this month are315        zero.316        """317        months = [self.monthdays2calendar(year, m) for m in Month]318        return [months[i:i+width] for i in range(0, len(months), width) ]319 320    def yeardayscalendar(self, year, width=3):321        """322        Return the data for the specified year ready for formatting (similar to323        yeardatescalendar()). Entries in the week lists are day numbers.324        Day numbers outside this month are zero.325        """326        months = [self.monthdayscalendar(year, m) for m in Month]327        return [months[i:i+width] for i in range(0, len(months), width) ]328 329 330class TextCalendar(Calendar):331    """332    Subclass of Calendar that outputs a calendar as a simple plain text333    similar to the UNIX program cal.334    """335 336    def prweek(self, theweek, width):337        """338        Print a single week (no newline).339        """340        print(self.formatweek(theweek, width), end='')341 342    def formatday(self, day, weekday, width):343        """344        Returns a formatted day.345        """346        if day == 0:347            s = ''348        else:349            s = '%2i' % day             # right-align single-digit days350        return s.center(width)351 352    def formatweek(self, theweek, width):353        """354        Returns a single week in a string (no newline).355        """356        return ' '.join(self.formatday(d, wd, width) for (d, wd) in theweek)357 358    def formatweekday(self, day, width):359        """360        Returns a formatted week day name.361        """362        if width >= 9:363            names = day_name364        else:365            names = day_abbr366        return names[day][:width].center(width)367 368    def formatweekheader(self, width):369        """370        Return a header for a week.371        """372        return ' '.join(self.formatweekday(i, width) for i in self.iterweekdays())373 374    def formatmonthname(self, theyear, themonth, width, withyear=True):375        """376        Return a formatted month name.377        """378        _validate_month(themonth)379 380        s = month_name[themonth]381        if withyear:382            s = "%s %r" % (s, theyear)383        return s.center(width)384 385    def prmonth(self, theyear, themonth, w=0, l=0):386        """387        Print a month's calendar.388        """389        print(self.formatmonth(theyear, themonth, w, l), end='')390 391    def formatmonth(self, theyear, themonth, w=0, l=0):392        """393        Return a month's calendar string (multi-line).394        """395        w = max(2, w)396        l = max(1, l)397        s = self.formatmonthname(theyear, themonth, 7 * (w + 1) - 1)398        s = s.rstrip()399        s += '\n' * l400        s += self.formatweekheader(w).rstrip()401        s += '\n' * l402        for week in self.monthdays2calendar(theyear, themonth):403            s += self.formatweek(week, w).rstrip()404            s += '\n' * l405        return s406 407    def formatyear(self, theyear, w=2, l=1, c=6, m=3):408        """409        Returns a year's calendar as a multi-line string.410        """411        w = max(2, w)412        l = max(1, l)413        c = max(2, c)414        colwidth = (w + 1) * 7 - 1415        v = []416        a = v.append417        a(repr(theyear).center(colwidth*m+c*(m-1)).rstrip())418        a('\n'*l)419        header = self.formatweekheader(w)420        for (i, row) in enumerate(self.yeardays2calendar(theyear, m)):421            # months in this row422            months = range(m*i+1, min(m*(i+1)+1, 13))423            a('\n'*l)424            names = (self.formatmonthname(theyear, k, colwidth, False)425                     for k in months)426            a(formatstring(names, colwidth, c).rstrip())427            a('\n'*l)428            headers = (header for k in months)429            a(formatstring(headers, colwidth, c).rstrip())430            a('\n'*l)431 432            # max number of weeks for this row433            height = max(len(cal) for cal in row)434            for j in range(height):435                weeks = []436                for cal in row:437                    if j >= len(cal):438                        weeks.append('')439                    else:440                        weeks.append(self.formatweek(cal[j], w))441                a(formatstring(weeks, colwidth, c).rstrip())442                a('\n' * l)443        return ''.join(v)444 445    def pryear(self, theyear, w=0, l=0, c=6, m=3):446        """Print a year's calendar."""447        print(self.formatyear(theyear, w, l, c, m), end='')448 449 450class HTMLCalendar(Calendar):451    """452    This calendar returns complete HTML pages.453    """454 455    # CSS classes for the day <td>s456    cssclasses = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]457 458    # CSS classes for the day <th>s459    cssclasses_weekday_head = cssclasses460 461    # CSS class for the days before and after current month462    cssclass_noday = "noday"463 464    # CSS class for the month's head465    cssclass_month_head = "month"466 467    # CSS class for the month468    cssclass_month = "month"469 470    # CSS class for the year's table head471    cssclass_year_head = "year"472 473    # CSS class for the whole year table474    cssclass_year = "year"475 476    def formatday(self, day, weekday):477        """478        Return a day as a table cell.479        """480        if day == 0:481            # day outside month482            return '<td class="%s">&nbsp;</td>' % self.cssclass_noday483        else:484            return '<td class="%s">%d</td>' % (self.cssclasses[weekday], day)485 486    def formatweek(self, theweek):487        """488        Return a complete week as a table row.489        """490        s = ''.join(self.formatday(d, wd) for (d, wd) in theweek)491        return '<tr>%s</tr>' % s492 493    def formatweekday(self, day):494        """495        Return a weekday name as a table header.496        """497        return '<th class="%s">%s</th>' % (498            self.cssclasses_weekday_head[day], day_abbr[day])499 500    def formatweekheader(self):501        """502        Return a header for a week as a table row.503        """504        s = ''.join(self.formatweekday(i) for i in self.iterweekdays())505        return '<tr>%s</tr>' % s506 507    def formatmonthname(self, theyear, themonth, withyear=True):508        """509        Return a month name as a table row.510        """511        _validate_month(themonth)512        if withyear:513            s = '%s %s' % (month_name[themonth], theyear)514        else:515            s = '%s' % month_name[themonth]516        return '<tr><th colspan="7" class="%s">%s</th></tr>' % (517            self.cssclass_month_head, s)518 519    def formatmonth(self, theyear, themonth, withyear=True):520        """521        Return a formatted month as a table.522        """523        v = []524        a = v.append525        a('<table border="0" cellpadding="0" cellspacing="0" class="%s">' % (526            self.cssclass_month))527        a('\n')528        a(self.formatmonthname(theyear, themonth, withyear=withyear))529        a('\n')530        a(self.formatweekheader())531        a('\n')532        for week in self.monthdays2calendar(theyear, themonth):533            a(self.formatweek(week))534            a('\n')535        a('</table>')536        a('\n')537        return ''.join(v)538 539    def formatyear(self, theyear, width=3):540        """541        Return a formatted year as a table of tables.542        """543        v = []544        a = v.append545        width = max(width, 1)546        a('<table border="0" cellpadding="0" cellspacing="0" class="%s">' %547          self.cssclass_year)548        a('\n')549        a('<tr><th colspan="%d" class="%s">%s</th></tr>' % (550            width, self.cssclass_year_head, theyear))551        for i in range(JANUARY, JANUARY+12, width):552            # months in this row553            months = range(i, min(i+width, 13))554            a('<tr>')555            for m in months:556                a('<td>')557                a(self.formatmonth(theyear, m, withyear=False))558                a('</td>')559            a('</tr>')560        a('</table>')561        return ''.join(v)562 563    def formatyearpage(self, theyear, width=3, css='calendar.css', encoding=None):564        """565        Return a formatted year as a complete HTML page.566        """567        if encoding is None:568            encoding = sys.getdefaultencoding()569        v = []570        a = v.append571        a('<?xml version="1.0" encoding="%s"?>\n' % encoding)572        a('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n')573        a('<html>\n')574        a('<head>\n')575        a('<meta http-equiv="Content-Type" content="text/html; charset=%s" />\n' % encoding)576        if css is not None:577            a('<link rel="stylesheet" type="text/css" href="%s" />\n' % css)578        a('<title>Calendar for %d</title>\n' % theyear)579        a('</head>\n')580        a('<body>\n')581        a(self.formatyear(theyear, width))582        a('</body>\n')583        a('</html>\n')584        return ''.join(v).encode(encoding, "xmlcharrefreplace")585 586 587class different_locale:588    def __init__(self, locale):589        self.locale = locale590        self.oldlocale = None591 592    def __enter__(self):593        self.oldlocale = _locale.setlocale(_locale.LC_TIME, None)594        _locale.setlocale(_locale.LC_TIME, self.locale)595 596    def __exit__(self, *args):597        _locale.setlocale(_locale.LC_TIME, self.oldlocale)598 599 600def _get_default_locale():601    locale = _locale.setlocale(_locale.LC_TIME, None)602    if locale == "C":603        with different_locale(""):604            # The LC_TIME locale does not seem to be configured:605            # get the user preferred locale.606            locale = _locale.setlocale(_locale.LC_TIME, None)607    return locale608 609 610class LocaleTextCalendar(TextCalendar):611    """612    This class can be passed a locale name in the constructor and will return613    month and weekday names in the specified locale.614    """615 616    def __init__(self, firstweekday=0, locale=None):617        TextCalendar.__init__(self, firstweekday)618        if locale is None:619            locale = _get_default_locale()620        self.locale = locale621 622    def formatweekday(self, day, width):623        with different_locale(self.locale):624            return super().formatweekday(day, width)625 626    def formatmonthname(self, theyear, themonth, width, withyear=True):627        with different_locale(self.locale):628            return super().formatmonthname(theyear, themonth, width, withyear)629 630 631class LocaleHTMLCalendar(HTMLCalendar):632    """633    This class can be passed a locale name in the constructor and will return634    month and weekday names in the specified locale.635    """636    def __init__(self, firstweekday=0, locale=None):637        HTMLCalendar.__init__(self, firstweekday)638        if locale is None:639            locale = _get_default_locale()640        self.locale = locale641 642    def formatweekday(self, day):643        with different_locale(self.locale):644            return super().formatweekday(day)645 646    def formatmonthname(self, theyear, themonth, withyear=True):647        with different_locale(self.locale):648            return super().formatmonthname(theyear, themonth, withyear)649 650 651class _CLIDemoCalendar(TextCalendar):652    def __init__(self, highlight_day=None, *args, **kwargs):653        super().__init__(*args, **kwargs)654        self.highlight_day = highlight_day655 656    def formatweek(self, theweek, width, *, highlight_day=None):657        """658        Returns a single week in a string (no newline).659        """660        if highlight_day:661            from _colorize import get_colors662 663            ansi = get_colors()664            highlight = f"{ansi.BLACK}{ansi.BACKGROUND_YELLOW}"665            reset = ansi.RESET666        else:667            highlight = reset = ""668 669        return ' '.join(670            (671                f"{highlight}{self.formatday(d, wd, width)}{reset}"672                if d == highlight_day673                else self.formatday(d, wd, width)674            )675            for (d, wd) in theweek676        )677 678    def formatmonth(self, theyear, themonth, w=0, l=0):679        """680        Return a month's calendar string (multi-line).681        """682        if (683            self.highlight_day684            and self.highlight_day.year == theyear685            and self.highlight_day.month == themonth686        ):687            highlight_day = self.highlight_day.day688        else:689            highlight_day = None690        w = max(2, w)691        l = max(1, l)692        s = self.formatmonthname(theyear, themonth, 7 * (w + 1) - 1)693        s = s.rstrip()694        s += '\n' * l695        s += self.formatweekheader(w).rstrip()696        s += '\n' * l697        for week in self.monthdays2calendar(theyear, themonth):698            s += self.formatweek(week, w, highlight_day=highlight_day).rstrip()699            s += '\n' * l700        return s701 702    def formatyear(self, theyear, w=2, l=1, c=6, m=3):703        """704        Returns a year's calendar as a multi-line string.705        """706        w = max(2, w)707        l = max(1, l)708        c = max(2, c)709        colwidth = (w + 1) * 7 - 1710        v = []711        a = v.append712        a(repr(theyear).center(colwidth*m+c*(m-1)).rstrip())713        a('\n'*l)714        header = self.formatweekheader(w)715        for (i, row) in enumerate(self.yeardays2calendar(theyear, m)):716            # months in this row717            months = range(m*i+1, min(m*(i+1)+1, 13))718            a('\n'*l)719            names = (self.formatmonthname(theyear, k, colwidth, False)720                     for k in months)721            a(formatstring(names, colwidth, c).rstrip())722            a('\n'*l)723            headers = (header for k in months)724            a(formatstring(headers, colwidth, c).rstrip())725            a('\n'*l)726 727            if (728                self.highlight_day729                and self.highlight_day.year == theyear730                and self.highlight_day.month in months731            ):732                month_pos = months.index(self.highlight_day.month)733            else:734                month_pos = None735 736            # max number of weeks for this row737            height = max(len(cal) for cal in row)738            for j in range(height):739                weeks = []740                for k, cal in enumerate(row):741                    if j >= len(cal):742                        weeks.append('')743                    else:744                        day = (745                            self.highlight_day.day if k == month_pos else None746                        )747                        weeks.append(748                            self.formatweek(cal[j], w, highlight_day=day)749                        )750                a(formatstring(weeks, colwidth, c).rstrip())751                a('\n' * l)752        return ''.join(v)753 754 755class _CLIDemoLocaleCalendar(LocaleTextCalendar, _CLIDemoCalendar):756    def __init__(self, highlight_day=None, *args, **kwargs):757        super().__init__(*args, **kwargs)758        self.highlight_day = highlight_day759 760 761# Support for old module level interface762c = TextCalendar()763 764firstweekday = c.getfirstweekday765 766def setfirstweekday(firstweekday):767    if not MONDAY <= firstweekday <= SUNDAY:768        raise IllegalWeekdayError(firstweekday)769    c.firstweekday = firstweekday770 771monthcalendar = c.monthdayscalendar772prweek = c.prweek773week = c.formatweek774weekheader = c.formatweekheader775prmonth = c.prmonth776month = c.formatmonth777calendar = c.formatyear778prcal = c.pryear779 780 781# Spacing of month columns for multi-column year calendar782_colwidth = 7*3 - 1         # Amount printed by prweek()783_spacing = 6                # Number of spaces between columns784 785 786def format(cols, colwidth=_colwidth, spacing=_spacing):787    """Prints multi-column formatting for year calendars"""788    print(formatstring(cols, colwidth, spacing))789 790 791def formatstring(cols, colwidth=_colwidth, spacing=_spacing):792    """Returns a string formatted from n strings, centered within n columns."""793    spacing *= ' '794    return spacing.join(c.center(colwidth) for c in cols)795 796 797EPOCH = 1970798_EPOCH_ORD = datetime.date(EPOCH, 1, 1).toordinal()799 800 801def timegm(tuple):802    """Unrelated but handy function to calculate Unix timestamp from GMT."""803    year, month, day, hour, minute, second = tuple[:6]804    days = datetime.date(year, month, 1).toordinal() - _EPOCH_ORD + day - 1805    hours = days*24 + hour806    minutes = hours*60 + minute807    seconds = minutes*60 + second808    return seconds809 810 811def main(args=None):812    import argparse813    parser = argparse.ArgumentParser(color=True)814    textgroup = parser.add_argument_group('text only arguments')815    htmlgroup = parser.add_argument_group('html only arguments')816    textgroup.add_argument(817        "-w", "--width",818        type=int, default=2,819        help="width of date column (default 2)"820    )821    textgroup.add_argument(822        "-l", "--lines",823        type=int, default=1,824        help="number of lines for each week (default 1)"825    )826    textgroup.add_argument(827        "-s", "--spacing",828        type=int, default=6,829        help="spacing between months (default 6)"830    )831    textgroup.add_argument(832        "-m", "--months",833        type=int, default=3,834        help="months per row (default 3)"835    )836    htmlgroup.add_argument(837        "-c", "--css",838        default="calendar.css",839        help="CSS to use for page"840    )841    parser.add_argument(842        "-L", "--locale",843        default=None,844        help="locale to use for month and weekday names"845    )846    parser.add_argument(847        "-e", "--encoding",848        default=None,849        help="encoding to use for output"850    )851    parser.add_argument(852        "-t", "--type",853        default="text",854        choices=("text", "html"),855        help="output type (text or html)"856    )857    parser.add_argument(858        "-f", "--first-weekday",859        type=int, default=0,860        help="weekday (0 is Monday, 6 is Sunday) to start each week (default 0)"861    )862    parser.add_argument(863        "year",864        nargs='?', type=int,865        help="year number"866    )867    parser.add_argument(868        "month",869        nargs='?', type=int,870        help="month number (1-12, text only)"871    )872 873    options = parser.parse_args(args)874 875    if options.locale and not options.encoding:876        parser.error("if --locale is specified --encoding is required")877        sys.exit(1)878 879    locale = options.locale, options.encoding880    today = datetime.date.today()881 882    if options.type == "html":883        if options.month:884            parser.error("incorrect number of arguments")885            sys.exit(1)886        if options.locale:887            cal = LocaleHTMLCalendar(locale=locale)888        else:889            cal = HTMLCalendar()890        cal.setfirstweekday(options.first_weekday)891        encoding = options.encoding892        if encoding is None:893            encoding = sys.getdefaultencoding()894        optdict = dict(encoding=encoding, css=options.css)895        write = sys.stdout.buffer.write896        if options.year is None:897            write(cal.formatyearpage(today.year, **optdict))898        else:899            write(cal.formatyearpage(options.year, **optdict))900    else:901        if options.locale:902            cal = _CLIDemoLocaleCalendar(highlight_day=today, locale=locale)903        else:904            cal = _CLIDemoCalendar(highlight_day=today)905        cal.setfirstweekday(options.first_weekday)906        optdict = dict(w=options.width, l=options.lines)907        if options.month is None:908            optdict["c"] = options.spacing909            optdict["m"] = options.months910        else:911            _validate_month(options.month)912        if options.year is None:913            result = cal.formatyear(today.year, **optdict)914        elif options.month is None:915            result = cal.formatyear(options.year, **optdict)916        else:917            result = cal.formatmonth(options.year, options.month, **optdict)918        write = sys.stdout.write919        if options.encoding:920            result = result.encode(options.encoding)921            write = sys.stdout.buffer.write922        write(result)923 924 925if __name__ == "__main__":926    main()927 
codekingpro/portable-devtools · Team Ai