import calendar
import unittest
from test import support
from test.script_helper import assert_python_ok
import time
import locale
result_2004_text = """
                                  2004
      January                   February                   March
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
          1  2  3  4                         1       1  2  3  4  5  6  7
 5  6  7  8  9 10 11       2  3  4  5  6  7  8       8  9 10 11 12 13 14
12 13 14 15 16 17 18       9 10 11 12 13 14 15      15 16 17 18 19 20 21
19 20 21 22 23 24 25      16 17 18 19 20 21 22      22 23 24 25 26 27 28
26 27 28 29 30 31         23 24 25 26 27 28 29      29 30 31
       April                      May                       June
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
          1  2  3  4                      1  2          1  2  3  4  5  6
 5  6  7  8  9 10 11       3  4  5  6  7  8  9       7  8  9 10 11 12 13
12 13 14 15 16 17 18      10 11 12 13 14 15 16      14 15 16 17 18 19 20
19 20 21 22 23 24 25      17 18 19 20 21 22 23      21 22 23 24 25 26 27
26 27 28 29 30            24 25 26 27 28 29 30      28 29 30
                          31
        July                     August                  September
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
          1  2  3  4                         1             1  2  3  4  5
 5  6  7  8  9 10 11       2  3  4  5  6  7  8       6  7  8  9 10 11 12
12 13 14 15 16 17 18       9 10 11 12 13 14 15      13 14 15 16 17 18 19
19 20 21 22 23 24 25      16 17 18 19 20 21 22      20 21 22 23 24 25 26
26 27 28 29 30 31         23 24 25 26 27 28 29      27 28 29 30
                          30 31
      October                   November                  December
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
             1  2  3       1  2  3  4  5  6  7             1  2  3  4  5
 4  5  6  7  8  9 10       8  9 10 11 12 13 14       6  7  8  9 10 11 12
11 12 13 14 15 16 17      15 16 17 18 19 20 21      13 14 15 16 17 18 19
18 19 20 21 22 23 24      22 23 24 25 26 27 28      20 21 22 23 24 25 26
25 26 27 28 29 30 31      29 30                     27 28 29 30 31
"""
result_2004_html = """
| 2004 | 
|---|
| 
| January | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 |  |  |  | 1 | 2 | 3 | 4 |  | 5 | 6 | 7 | 8 | 9 | 10 | 11 |  | 12 | 13 | 14 | 15 | 16 | 17 | 18 |  | 19 | 20 | 21 | 22 | 23 | 24 | 25 |  | 26 | 27 | 28 | 29 | 30 | 31 |  |  | 
| February | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 |  |  |  |  |  |  | 1 |  | 2 | 3 | 4 | 5 | 6 | 7 | 8 |  | 9 | 10 | 11 | 12 | 13 | 14 | 15 |  | 16 | 17 | 18 | 19 | 20 | 21 | 22 |  | 23 | 24 | 25 | 26 | 27 | 28 | 29 |  | 
| March | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |  | 8 | 9 | 10 | 11 | 12 | 13 | 14 |  | 15 | 16 | 17 | 18 | 19 | 20 | 21 |  | 22 | 23 | 24 | 25 | 26 | 27 | 28 |  | 29 | 30 | 31 |  |  |  |  |  | 
| 
| April | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 |  |  |  | 1 | 2 | 3 | 4 |  | 5 | 6 | 7 | 8 | 9 | 10 | 11 |  | 12 | 13 | 14 | 15 | 16 | 17 | 18 |  | 19 | 20 | 21 | 22 | 23 | 24 | 25 |  | 26 | 27 | 28 | 29 | 30 |  |  |  | 
| May | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 |  |  |  |  |  | 1 | 2 |  | 3 | 4 | 5 | 6 | 7 | 8 | 9 |  | 10 | 11 | 12 | 13 | 14 | 15 | 16 |  | 17 | 18 | 19 | 20 | 21 | 22 | 23 |  | 24 | 25 | 26 | 27 | 28 | 29 | 30 |  | 31 |  |  |  |  |  |  |  | 
| June | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 |  | 1 | 2 | 3 | 4 | 5 | 6 |  | 7 | 8 | 9 | 10 | 11 | 12 | 13 |  | 14 | 15 | 16 | 17 | 18 | 19 | 20 |  | 21 | 22 | 23 | 24 | 25 | 26 | 27 |  | 28 | 29 | 30 |  |  |  |  |  | 
| 
| July | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 |  |  |  | 1 | 2 | 3 | 4 |  | 5 | 6 | 7 | 8 | 9 | 10 | 11 |  | 12 | 13 | 14 | 15 | 16 | 17 | 18 |  | 19 | 20 | 21 | 22 | 23 | 24 | 25 |  | 26 | 27 | 28 | 29 | 30 | 31 |  |  | 
| August | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 |  |  |  |  |  |  | 1 |  | 2 | 3 | 4 | 5 | 6 | 7 | 8 |  | 9 | 10 | 11 | 12 | 13 | 14 | 15 |  | 16 | 17 | 18 | 19 | 20 | 21 | 22 |  | 23 | 24 | 25 | 26 | 27 | 28 | 29 |  | 30 | 31 |  |  |  |  |  |  | 
| September | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 |  |  | 1 | 2 | 3 | 4 | 5 |  | 6 | 7 | 8 | 9 | 10 | 11 | 12 |  | 13 | 14 | 15 | 16 | 17 | 18 | 19 |  | 20 | 21 | 22 | 23 | 24 | 25 | 26 |  | 27 | 28 | 29 | 30 |  |  |  |  | 
| 
| October | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 |  |  |  |  | 1 | 2 | 3 |  | 4 | 5 | 6 | 7 | 8 | 9 | 10 |  | 11 | 12 | 13 | 14 | 15 | 16 | 17 |  | 18 | 19 | 20 | 21 | 22 | 23 | 24 |  | 25 | 26 | 27 | 28 | 29 | 30 | 31 |  | 
| November | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |  | 8 | 9 | 10 | 11 | 12 | 13 | 14 |  | 15 | 16 | 17 | 18 | 19 | 20 | 21 |  | 22 | 23 | 24 | 25 | 26 | 27 | 28 |  | 29 | 30 |  |  |  |  |  |  | 
| December | 
|---|
 | Mon | Tue | Wed | Thu | Fri | Sat | Sun | 
|---|
 |  |  | 1 | 2 | 3 | 4 | 5 |  | 6 | 7 | 8 | 9 | 10 | 11 | 12 |  | 13 | 14 | 15 | 16 | 17 | 18 | 19 |  | 20 | 21 | 22 | 23 | 24 | 25 | 26 |  | 27 | 28 | 29 | 30 | 31 |  |  |  | 
"""
class OutputTestCase(unittest.TestCase):
    def normalize_calendar(self, s):
        # Filters out locale dependent strings
        def neitherspacenordigit(c):
            return not c.isspace() and not c.isdigit()
        lines = []
        for line in s.splitlines(keepends=False):
            # Drop texts, as they are locale dependent
            if line and not filter(neitherspacenordigit, line):
                lines.append(line)
        return lines
    def test_output(self):
        self.assertEqual(
            self.normalize_calendar(calendar.calendar(2004)),
            self.normalize_calendar(result_2004_text)
        )
    def test_output_textcalendar(self):
        self.assertEqual(
            calendar.TextCalendar().formatyear(2004).strip(),
            result_2004_text.strip()
        )
    def test_output_htmlcalendar(self):
        encoding = 'ascii'
        cal = calendar.HTMLCalendar()
        self.assertEqual(
            cal.formatyearpage(2004, encoding=encoding).strip(b' \t\n'),
            result_2004_html.strip(' \t\n').encode(encoding)
        )
class CalendarTestCase(unittest.TestCase):
    def test_isleap(self):
        # Make sure that the return is right for a few years, and
        # ensure that the return values are 1 or 0, not just true or
        # false (see SF bug #485794).  Specific additional tests may
        # be appropriate; this tests a single "cycle".
        self.assertEqual(calendar.isleap(2000), 1)
        self.assertEqual(calendar.isleap(2001), 0)
        self.assertEqual(calendar.isleap(2002), 0)
        self.assertEqual(calendar.isleap(2003), 0)
    def test_setfirstweekday(self):
        self.assertRaises(TypeError, calendar.setfirstweekday, 'flabber')
        self.assertRaises(ValueError, calendar.setfirstweekday, -1)
        self.assertRaises(ValueError, calendar.setfirstweekday, 200)
        orig = calendar.firstweekday()
        calendar.setfirstweekday(calendar.SUNDAY)
        self.assertEqual(calendar.firstweekday(), calendar.SUNDAY)
        calendar.setfirstweekday(calendar.MONDAY)
        self.assertEqual(calendar.firstweekday(), calendar.MONDAY)
        calendar.setfirstweekday(orig)
    def test_enumerateweekdays(self):
        self.assertRaises(IndexError, calendar.day_abbr.__getitem__, -10)
        self.assertRaises(IndexError, calendar.day_name.__getitem__, 10)
        self.assertEqual(len([d for d in calendar.day_abbr]), 7)
    def test_days(self):
        for attr in "day_name", "day_abbr":
            value = getattr(calendar, attr)
            self.assertEqual(len(value), 7)
            self.assertEqual(len(value[:]), 7)
            # ensure they're all unique
            self.assertEqual(len(set(value)), 7)
            # verify it "acts like a sequence" in two forms of iteration
            self.assertEqual(value[::-1], list(reversed(value)))
    def test_months(self):
        for attr in "month_name", "month_abbr":
            value = getattr(calendar, attr)
            self.assertEqual(len(value), 13)
            self.assertEqual(len(value[:]), 13)
            self.assertEqual(value[0], "")
            # ensure they're all unique
            self.assertEqual(len(set(value)), 13)
            # verify it "acts like a sequence" in two forms of iteration
            self.assertEqual(value[::-1], list(reversed(value)))
    def test_localecalendars(self):
        # ensure that Locale{Text,HTML}Calendar resets the locale properly
        # (it is still not thread-safe though)
        old_october = calendar.TextCalendar().formatmonthname(2010, 10, 10)
        try:
            calendar.LocaleTextCalendar(locale='').formatmonthname(2010, 10, 10)
        except locale.Error:
            # cannot set the system default locale -- skip rest of test
            return
        calendar.LocaleHTMLCalendar(locale='').formatmonthname(2010, 10)
        new_october = calendar.TextCalendar().formatmonthname(2010, 10, 10)
        self.assertEqual(old_october, new_october)
class MonthCalendarTestCase(unittest.TestCase):
    def setUp(self):
        self.oldfirstweekday = calendar.firstweekday()
        calendar.setfirstweekday(self.firstweekday)
    def tearDown(self):
        calendar.setfirstweekday(self.oldfirstweekday)
    def check_weeks(self, year, month, weeks):
        cal = calendar.monthcalendar(year, month)
        self.assertEqual(len(cal), len(weeks))
        for i in range(len(weeks)):
            self.assertEqual(weeks[i], sum(day != 0 for day in cal[i]))
class MondayTestCase(MonthCalendarTestCase):
    firstweekday = calendar.MONDAY
    def test_february(self):
        # A 28-day february starting on monday (7+7+7+7 days)
        self.check_weeks(1999, 2, (7, 7, 7, 7))
        # A 28-day february starting on tuesday (6+7+7+7+1 days)
        self.check_weeks(2005, 2, (6, 7, 7, 7, 1))
        # A 28-day february starting on sunday (1+7+7+7+6 days)
        self.check_weeks(1987, 2, (1, 7, 7, 7, 6))
        # A 29-day february starting on monday (7+7+7+7+1 days)
        self.check_weeks(1988, 2, (7, 7, 7, 7, 1))
        # A 29-day february starting on tuesday (6+7+7+7+2 days)
        self.check_weeks(1972, 2, (6, 7, 7, 7, 2))
        # A 29-day february starting on sunday (1+7+7+7+7 days)
        self.check_weeks(2004, 2, (1, 7, 7, 7, 7))
    def test_april(self):
        # A 30-day april starting on monday (7+7+7+7+2 days)
        self.check_weeks(1935, 4, (7, 7, 7, 7, 2))
        # A 30-day april starting on tuesday (6+7+7+7+3 days)
        self.check_weeks(1975, 4, (6, 7, 7, 7, 3))
        # A 30-day april starting on sunday (1+7+7+7+7+1 days)
        self.check_weeks(1945, 4, (1, 7, 7, 7, 7, 1))
        # A 30-day april starting on saturday (2+7+7+7+7 days)
        self.check_weeks(1995, 4, (2, 7, 7, 7, 7))
        # A 30-day april starting on friday (3+7+7+7+6 days)
        self.check_weeks(1994, 4, (3, 7, 7, 7, 6))
    def test_december(self):
        # A 31-day december starting on monday (7+7+7+7+3 days)
        self.check_weeks(1980, 12, (7, 7, 7, 7, 3))
        # A 31-day december starting on tuesday (6+7+7+7+4 days)
        self.check_weeks(1987, 12, (6, 7, 7, 7, 4))
        # A 31-day december starting on sunday (1+7+7+7+7+2 days)
        self.check_weeks(1968, 12, (1, 7, 7, 7, 7, 2))
        # A 31-day december starting on thursday (4+7+7+7+6 days)
        self.check_weeks(1988, 12, (4, 7, 7, 7, 6))
        # A 31-day december starting on friday (3+7+7+7+7 days)
        self.check_weeks(2017, 12, (3, 7, 7, 7, 7))
        # A 31-day december starting on saturday (2+7+7+7+7+1 days)
        self.check_weeks(2068, 12, (2, 7, 7, 7, 7, 1))
class SundayTestCase(MonthCalendarTestCase):
    firstweekday = calendar.SUNDAY
    def test_february(self):
        # A 28-day february starting on sunday (7+7+7+7 days)
        self.check_weeks(2009, 2, (7, 7, 7, 7))
        # A 28-day february starting on monday (6+7+7+7+1 days)
        self.check_weeks(1999, 2, (6, 7, 7, 7, 1))
        # A 28-day february starting on saturday (1+7+7+7+6 days)
        self.check_weeks(1997, 2, (1, 7, 7, 7, 6))
        # A 29-day february starting on sunday (7+7+7+7+1 days)
        self.check_weeks(2004, 2, (7, 7, 7, 7, 1))
        # A 29-day february starting on monday (6+7+7+7+2 days)
        self.check_weeks(1960, 2, (6, 7, 7, 7, 2))
        # A 29-day february starting on saturday (1+7+7+7+7 days)
        self.check_weeks(1964, 2, (1, 7, 7, 7, 7))
    def test_april(self):
        # A 30-day april starting on sunday (7+7+7+7+2 days)
        self.check_weeks(1923, 4, (7, 7, 7, 7, 2))
        # A 30-day april starting on monday (6+7+7+7+3 days)
        self.check_weeks(1918, 4, (6, 7, 7, 7, 3))
        # A 30-day april starting on saturday (1+7+7+7+7+1 days)
        self.check_weeks(1950, 4, (1, 7, 7, 7, 7, 1))
        # A 30-day april starting on friday (2+7+7+7+7 days)
        self.check_weeks(1960, 4, (2, 7, 7, 7, 7))
        # A 30-day april starting on thursday (3+7+7+7+6 days)
        self.check_weeks(1909, 4, (3, 7, 7, 7, 6))
    def test_december(self):
        # A 31-day december starting on sunday (7+7+7+7+3 days)
        self.check_weeks(2080, 12, (7, 7, 7, 7, 3))
        # A 31-day december starting on monday (6+7+7+7+4 days)
        self.check_weeks(1941, 12, (6, 7, 7, 7, 4))
        # A 31-day december starting on saturday (1+7+7+7+7+2 days)
        self.check_weeks(1923, 12, (1, 7, 7, 7, 7, 2))
        # A 31-day december starting on wednesday (4+7+7+7+6 days)
        self.check_weeks(1948, 12, (4, 7, 7, 7, 6))
        # A 31-day december starting on thursday (3+7+7+7+7 days)
        self.check_weeks(1927, 12, (3, 7, 7, 7, 7))
        # A 31-day december starting on friday (2+7+7+7+7+1 days)
        self.check_weeks(1995, 12, (2, 7, 7, 7, 7, 1))
class TimegmTestCase(unittest.TestCase):
    TIMESTAMPS = [0, 10, 100, 1000, 10000, 100000, 1000000,
                  1234567890, 1262304000, 1275785153,]
    def test_timegm(self):
        for secs in self.TIMESTAMPS:
            tuple = time.gmtime(secs)
            self.assertEqual(secs, calendar.timegm(tuple))
class MonthRangeTestCase(unittest.TestCase):
    def test_january(self):
        # Tests valid lower boundary case.
        self.assertEqual(calendar.monthrange(2004,1), (3,31))
    def test_february_leap(self):
        # Tests February during leap year.
        self.assertEqual(calendar.monthrange(2004,2), (6,29))
    def test_february_nonleap(self):
        # Tests February in non-leap year.
        self.assertEqual(calendar.monthrange(2010,2), (0,28))
    def test_december(self):
        # Tests valid upper boundary case.
        self.assertEqual(calendar.monthrange(2004,12), (2,31))
    def test_zeroth_month(self):
        # Tests low invalid boundary case.
        with self.assertRaises(calendar.IllegalMonthError):
            calendar.monthrange(2004, 0)
    def test_thirteenth_month(self):
        # Tests high invalid boundary case.
        with self.assertRaises(calendar.IllegalMonthError):
            calendar.monthrange(2004, 13)
class LeapdaysTestCase(unittest.TestCase):
    def test_no_range(self):
        # test when no range i.e. two identical years as args
        self.assertEqual(calendar.leapdays(2010,2010), 0)
    def test_no_leapdays(self):
        # test when no leap years in range
        self.assertEqual(calendar.leapdays(2010,2011), 0)
    def test_no_leapdays_upper_boundary(self):
        # test no leap years in range, when upper boundary is a leap year
        self.assertEqual(calendar.leapdays(2010,2012), 0)
    def test_one_leapday_lower_boundary(self):
        # test when one leap year in range, lower boundary is leap year
        self.assertEqual(calendar.leapdays(2012,2013), 1)
    def test_several_leapyears_in_range(self):
        self.assertEqual(calendar.leapdays(1997,2020), 5)
class ConsoleOutputTestCase(unittest.TestCase):
    def test_outputs_bytes(self):
        (return_code, stdout, stderr) = assert_python_ok('-m', 'calendar', '--type=html', '2010')
        self.assertEqual(stdout[:6], b'