1 import calendar
2 import unittest
3
4 from test import support
5 from test.support.script_helper import assert_python_ok, assert_python_failure
6 import time
7 import locale
8 import sys
9 import datetime
10 import os
11 import warnings
12
13 # From https://en.wikipedia.org/wiki/Leap_year_starting_on_Saturday
14 result_0_02_text = """\
15 February 0
16 Mo Tu We Th Fr Sa Su
17 1 2 3 4 5 6
18 7 8 9 10 11 12 13
19 14 15 16 17 18 19 20
20 21 22 23 24 25 26 27
21 28 29
22 """
23
24 result_0_text = """\
25 0
26
27 January February March
28 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
29 1 2 1 2 3 4 5 6 1 2 3 4 5
30 3 4 5 6 7 8 9 7 8 9 10 11 12 13 6 7 8 9 10 11 12
31 10 11 12 13 14 15 16 14 15 16 17 18 19 20 13 14 15 16 17 18 19
32 17 18 19 20 21 22 23 21 22 23 24 25 26 27 20 21 22 23 24 25 26
33 24 25 26 27 28 29 30 28 29 27 28 29 30 31
34 31
35
36 April May June
37 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
38 1 2 1 2 3 4 5 6 7 1 2 3 4
39 3 4 5 6 7 8 9 8 9 10 11 12 13 14 5 6 7 8 9 10 11
40 10 11 12 13 14 15 16 15 16 17 18 19 20 21 12 13 14 15 16 17 18
41 17 18 19 20 21 22 23 22 23 24 25 26 27 28 19 20 21 22 23 24 25
42 24 25 26 27 28 29 30 29 30 31 26 27 28 29 30
43
44 July August September
45 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
46 1 2 1 2 3 4 5 6 1 2 3
47 3 4 5 6 7 8 9 7 8 9 10 11 12 13 4 5 6 7 8 9 10
48 10 11 12 13 14 15 16 14 15 16 17 18 19 20 11 12 13 14 15 16 17
49 17 18 19 20 21 22 23 21 22 23 24 25 26 27 18 19 20 21 22 23 24
50 24 25 26 27 28 29 30 28 29 30 31 25 26 27 28 29 30
51 31
52
53 October November December
54 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
55 1 1 2 3 4 5 1 2 3
56 2 3 4 5 6 7 8 6 7 8 9 10 11 12 4 5 6 7 8 9 10
57 9 10 11 12 13 14 15 13 14 15 16 17 18 19 11 12 13 14 15 16 17
58 16 17 18 19 20 21 22 20 21 22 23 24 25 26 18 19 20 21 22 23 24
59 23 24 25 26 27 28 29 27 28 29 30 25 26 27 28 29 30 31
60 30 31
61 """
62
63 result_2004_01_text = """\
64 January 2004
65 Mo Tu We Th Fr Sa Su
66 1 2 3 4
67 5 6 7 8 9 10 11
68 12 13 14 15 16 17 18
69 19 20 21 22 23 24 25
70 26 27 28 29 30 31
71 """
72
73 result_2004_text = """\
74 2004
75
76 January February March
77 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
78 1 2 3 4 1 1 2 3 4 5 6 7
79 5 6 7 8 9 10 11 2 3 4 5 6 7 8 8 9 10 11 12 13 14
80 12 13 14 15 16 17 18 9 10 11 12 13 14 15 15 16 17 18 19 20 21
81 19 20 21 22 23 24 25 16 17 18 19 20 21 22 22 23 24 25 26 27 28
82 26 27 28 29 30 31 23 24 25 26 27 28 29 29 30 31
83
84 April May June
85 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
86 1 2 3 4 1 2 1 2 3 4 5 6
87 5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13
88 12 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20
89 19 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27
90 26 27 28 29 30 24 25 26 27 28 29 30 28 29 30
91 31
92
93 July August September
94 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
95 1 2 3 4 1 1 2 3 4 5
96 5 6 7 8 9 10 11 2 3 4 5 6 7 8 6 7 8 9 10 11 12
97 12 13 14 15 16 17 18 9 10 11 12 13 14 15 13 14 15 16 17 18 19
98 19 20 21 22 23 24 25 16 17 18 19 20 21 22 20 21 22 23 24 25 26
99 26 27 28 29 30 31 23 24 25 26 27 28 29 27 28 29 30
100 30 31
101
102 October November December
103 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
104 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5
105 4 5 6 7 8 9 10 8 9 10 11 12 13 14 6 7 8 9 10 11 12
106 11 12 13 14 15 16 17 15 16 17 18 19 20 21 13 14 15 16 17 18 19
107 18 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26
108 25 26 27 28 29 30 31 29 30 27 28 29 30 31
109 """
110
111
112 default_format = dict(year="year", month="month", encoding="ascii")
113
114 result_2004_html = """\
115 <?xml version="1.0" encoding="{encoding}"?>
116 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
117 <html>
118 <head>
119 <meta http-equiv="Content-Type" content="text/html; charset={encoding}" />
120 <link rel="stylesheet" type="text/css" href="calendar.css" />
121 <title>Calendar for 2004</title>
122 </head>
123 <body>
124 <table border="0" cellpadding="0" cellspacing="0" class="{year}">
125 <tr><th colspan="3" class="{year}">2004</th></tr><tr><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
126 <tr><th colspan="7" class="{month}">January</th></tr>
127 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
128 <tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="thu">1</td><td class="fri">2</td><td class="sat">3</td><td class="sun">4</td></tr>
129 <tr><td class="mon">5</td><td class="tue">6</td><td class="wed">7</td><td class="thu">8</td><td class="fri">9</td><td class="sat">10</td><td class="sun">11</td></tr>
130 <tr><td class="mon">12</td><td class="tue">13</td><td class="wed">14</td><td class="thu">15</td><td class="fri">16</td><td class="sat">17</td><td class="sun">18</td></tr>
131 <tr><td class="mon">19</td><td class="tue">20</td><td class="wed">21</td><td class="thu">22</td><td class="fri">23</td><td class="sat">24</td><td class="sun">25</td></tr>
132 <tr><td class="mon">26</td><td class="tue">27</td><td class="wed">28</td><td class="thu">29</td><td class="fri">30</td><td class="sat">31</td><td class="noday"> </td></tr>
133 </table>
134 </td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
135 <tr><th colspan="7" class="{month}">February</th></tr>
136 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
137 <tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="sun">1</td></tr>
138 <tr><td class="mon">2</td><td class="tue">3</td><td class="wed">4</td><td class="thu">5</td><td class="fri">6</td><td class="sat">7</td><td class="sun">8</td></tr>
139 <tr><td class="mon">9</td><td class="tue">10</td><td class="wed">11</td><td class="thu">12</td><td class="fri">13</td><td class="sat">14</td><td class="sun">15</td></tr>
140 <tr><td class="mon">16</td><td class="tue">17</td><td class="wed">18</td><td class="thu">19</td><td class="fri">20</td><td class="sat">21</td><td class="sun">22</td></tr>
141 <tr><td class="mon">23</td><td class="tue">24</td><td class="wed">25</td><td class="thu">26</td><td class="fri">27</td><td class="sat">28</td><td class="sun">29</td></tr>
142 </table>
143 </td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
144 <tr><th colspan="7" class="{month}">March</th></tr>
145 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
146 <tr><td class="mon">1</td><td class="tue">2</td><td class="wed">3</td><td class="thu">4</td><td class="fri">5</td><td class="sat">6</td><td class="sun">7</td></tr>
147 <tr><td class="mon">8</td><td class="tue">9</td><td class="wed">10</td><td class="thu">11</td><td class="fri">12</td><td class="sat">13</td><td class="sun">14</td></tr>
148 <tr><td class="mon">15</td><td class="tue">16</td><td class="wed">17</td><td class="thu">18</td><td class="fri">19</td><td class="sat">20</td><td class="sun">21</td></tr>
149 <tr><td class="mon">22</td><td class="tue">23</td><td class="wed">24</td><td class="thu">25</td><td class="fri">26</td><td class="sat">27</td><td class="sun">28</td></tr>
150 <tr><td class="mon">29</td><td class="tue">30</td><td class="wed">31</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr>
151 </table>
152 </td></tr><tr><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
153 <tr><th colspan="7" class="{month}">April</th></tr>
154 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
155 <tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="thu">1</td><td class="fri">2</td><td class="sat">3</td><td class="sun">4</td></tr>
156 <tr><td class="mon">5</td><td class="tue">6</td><td class="wed">7</td><td class="thu">8</td><td class="fri">9</td><td class="sat">10</td><td class="sun">11</td></tr>
157 <tr><td class="mon">12</td><td class="tue">13</td><td class="wed">14</td><td class="thu">15</td><td class="fri">16</td><td class="sat">17</td><td class="sun">18</td></tr>
158 <tr><td class="mon">19</td><td class="tue">20</td><td class="wed">21</td><td class="thu">22</td><td class="fri">23</td><td class="sat">24</td><td class="sun">25</td></tr>
159 <tr><td class="mon">26</td><td class="tue">27</td><td class="wed">28</td><td class="thu">29</td><td class="fri">30</td><td class="noday"> </td><td class="noday"> </td></tr>
160 </table>
161 </td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
162 <tr><th colspan="7" class="{month}">May</th></tr>
163 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
164 <tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="sat">1</td><td class="sun">2</td></tr>
165 <tr><td class="mon">3</td><td class="tue">4</td><td class="wed">5</td><td class="thu">6</td><td class="fri">7</td><td class="sat">8</td><td class="sun">9</td></tr>
166 <tr><td class="mon">10</td><td class="tue">11</td><td class="wed">12</td><td class="thu">13</td><td class="fri">14</td><td class="sat">15</td><td class="sun">16</td></tr>
167 <tr><td class="mon">17</td><td class="tue">18</td><td class="wed">19</td><td class="thu">20</td><td class="fri">21</td><td class="sat">22</td><td class="sun">23</td></tr>
168 <tr><td class="mon">24</td><td class="tue">25</td><td class="wed">26</td><td class="thu">27</td><td class="fri">28</td><td class="sat">29</td><td class="sun">30</td></tr>
169 <tr><td class="mon">31</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr>
170 </table>
171 </td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
172 <tr><th colspan="7" class="{month}">June</th></tr>
173 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
174 <tr><td class="noday"> </td><td class="tue">1</td><td class="wed">2</td><td class="thu">3</td><td class="fri">4</td><td class="sat">5</td><td class="sun">6</td></tr>
175 <tr><td class="mon">7</td><td class="tue">8</td><td class="wed">9</td><td class="thu">10</td><td class="fri">11</td><td class="sat">12</td><td class="sun">13</td></tr>
176 <tr><td class="mon">14</td><td class="tue">15</td><td class="wed">16</td><td class="thu">17</td><td class="fri">18</td><td class="sat">19</td><td class="sun">20</td></tr>
177 <tr><td class="mon">21</td><td class="tue">22</td><td class="wed">23</td><td class="thu">24</td><td class="fri">25</td><td class="sat">26</td><td class="sun">27</td></tr>
178 <tr><td class="mon">28</td><td class="tue">29</td><td class="wed">30</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr>
179 </table>
180 </td></tr><tr><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
181 <tr><th colspan="7" class="{month}">July</th></tr>
182 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
183 <tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="thu">1</td><td class="fri">2</td><td class="sat">3</td><td class="sun">4</td></tr>
184 <tr><td class="mon">5</td><td class="tue">6</td><td class="wed">7</td><td class="thu">8</td><td class="fri">9</td><td class="sat">10</td><td class="sun">11</td></tr>
185 <tr><td class="mon">12</td><td class="tue">13</td><td class="wed">14</td><td class="thu">15</td><td class="fri">16</td><td class="sat">17</td><td class="sun">18</td></tr>
186 <tr><td class="mon">19</td><td class="tue">20</td><td class="wed">21</td><td class="thu">22</td><td class="fri">23</td><td class="sat">24</td><td class="sun">25</td></tr>
187 <tr><td class="mon">26</td><td class="tue">27</td><td class="wed">28</td><td class="thu">29</td><td class="fri">30</td><td class="sat">31</td><td class="noday"> </td></tr>
188 </table>
189 </td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
190 <tr><th colspan="7" class="{month}">August</th></tr>
191 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
192 <tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="sun">1</td></tr>
193 <tr><td class="mon">2</td><td class="tue">3</td><td class="wed">4</td><td class="thu">5</td><td class="fri">6</td><td class="sat">7</td><td class="sun">8</td></tr>
194 <tr><td class="mon">9</td><td class="tue">10</td><td class="wed">11</td><td class="thu">12</td><td class="fri">13</td><td class="sat">14</td><td class="sun">15</td></tr>
195 <tr><td class="mon">16</td><td class="tue">17</td><td class="wed">18</td><td class="thu">19</td><td class="fri">20</td><td class="sat">21</td><td class="sun">22</td></tr>
196 <tr><td class="mon">23</td><td class="tue">24</td><td class="wed">25</td><td class="thu">26</td><td class="fri">27</td><td class="sat">28</td><td class="sun">29</td></tr>
197 <tr><td class="mon">30</td><td class="tue">31</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr>
198 </table>
199 </td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
200 <tr><th colspan="7" class="{month}">September</th></tr>
201 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
202 <tr><td class="noday"> </td><td class="noday"> </td><td class="wed">1</td><td class="thu">2</td><td class="fri">3</td><td class="sat">4</td><td class="sun">5</td></tr>
203 <tr><td class="mon">6</td><td class="tue">7</td><td class="wed">8</td><td class="thu">9</td><td class="fri">10</td><td class="sat">11</td><td class="sun">12</td></tr>
204 <tr><td class="mon">13</td><td class="tue">14</td><td class="wed">15</td><td class="thu">16</td><td class="fri">17</td><td class="sat">18</td><td class="sun">19</td></tr>
205 <tr><td class="mon">20</td><td class="tue">21</td><td class="wed">22</td><td class="thu">23</td><td class="fri">24</td><td class="sat">25</td><td class="sun">26</td></tr>
206 <tr><td class="mon">27</td><td class="tue">28</td><td class="wed">29</td><td class="thu">30</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr>
207 </table>
208 </td></tr><tr><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
209 <tr><th colspan="7" class="{month}">October</th></tr>
210 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
211 <tr><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="fri">1</td><td class="sat">2</td><td class="sun">3</td></tr>
212 <tr><td class="mon">4</td><td class="tue">5</td><td class="wed">6</td><td class="thu">7</td><td class="fri">8</td><td class="sat">9</td><td class="sun">10</td></tr>
213 <tr><td class="mon">11</td><td class="tue">12</td><td class="wed">13</td><td class="thu">14</td><td class="fri">15</td><td class="sat">16</td><td class="sun">17</td></tr>
214 <tr><td class="mon">18</td><td class="tue">19</td><td class="wed">20</td><td class="thu">21</td><td class="fri">22</td><td class="sat">23</td><td class="sun">24</td></tr>
215 <tr><td class="mon">25</td><td class="tue">26</td><td class="wed">27</td><td class="thu">28</td><td class="fri">29</td><td class="sat">30</td><td class="sun">31</td></tr>
216 </table>
217 </td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
218 <tr><th colspan="7" class="{month}">November</th></tr>
219 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
220 <tr><td class="mon">1</td><td class="tue">2</td><td class="wed">3</td><td class="thu">4</td><td class="fri">5</td><td class="sat">6</td><td class="sun">7</td></tr>
221 <tr><td class="mon">8</td><td class="tue">9</td><td class="wed">10</td><td class="thu">11</td><td class="fri">12</td><td class="sat">13</td><td class="sun">14</td></tr>
222 <tr><td class="mon">15</td><td class="tue">16</td><td class="wed">17</td><td class="thu">18</td><td class="fri">19</td><td class="sat">20</td><td class="sun">21</td></tr>
223 <tr><td class="mon">22</td><td class="tue">23</td><td class="wed">24</td><td class="thu">25</td><td class="fri">26</td><td class="sat">27</td><td class="sun">28</td></tr>
224 <tr><td class="mon">29</td><td class="tue">30</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr>
225 </table>
226 </td><td><table border="0" cellpadding="0" cellspacing="0" class="{month}">
227 <tr><th colspan="7" class="{month}">December</th></tr>
228 <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
229 <tr><td class="noday"> </td><td class="noday"> </td><td class="wed">1</td><td class="thu">2</td><td class="fri">3</td><td class="sat">4</td><td class="sun">5</td></tr>
230 <tr><td class="mon">6</td><td class="tue">7</td><td class="wed">8</td><td class="thu">9</td><td class="fri">10</td><td class="sat">11</td><td class="sun">12</td></tr>
231 <tr><td class="mon">13</td><td class="tue">14</td><td class="wed">15</td><td class="thu">16</td><td class="fri">17</td><td class="sat">18</td><td class="sun">19</td></tr>
232 <tr><td class="mon">20</td><td class="tue">21</td><td class="wed">22</td><td class="thu">23</td><td class="fri">24</td><td class="sat">25</td><td class="sun">26</td></tr>
233 <tr><td class="mon">27</td><td class="tue">28</td><td class="wed">29</td><td class="thu">30</td><td class="fri">31</td><td class="noday"> </td><td class="noday"> </td></tr>
234 </table>
235 </td></tr></table></body>
236 </html>
237 """
238
239 result_2004_days = [
240 [[[0, 0, 0, 1, 2, 3, 4],
241 [5, 6, 7, 8, 9, 10, 11],
242 [12, 13, 14, 15, 16, 17, 18],
243 [19, 20, 21, 22, 23, 24, 25],
244 [26, 27, 28, 29, 30, 31, 0]],
245 [[0, 0, 0, 0, 0, 0, 1],
246 [2, 3, 4, 5, 6, 7, 8],
247 [9, 10, 11, 12, 13, 14, 15],
248 [16, 17, 18, 19, 20, 21, 22],
249 [23, 24, 25, 26, 27, 28, 29]],
250 [[1, 2, 3, 4, 5, 6, 7],
251 [8, 9, 10, 11, 12, 13, 14],
252 [15, 16, 17, 18, 19, 20, 21],
253 [22, 23, 24, 25, 26, 27, 28],
254 [29, 30, 31, 0, 0, 0, 0]]],
255 [[[0, 0, 0, 1, 2, 3, 4],
256 [5, 6, 7, 8, 9, 10, 11],
257 [12, 13, 14, 15, 16, 17, 18],
258 [19, 20, 21, 22, 23, 24, 25],
259 [26, 27, 28, 29, 30, 0, 0]],
260 [[0, 0, 0, 0, 0, 1, 2],
261 [3, 4, 5, 6, 7, 8, 9],
262 [10, 11, 12, 13, 14, 15, 16],
263 [17, 18, 19, 20, 21, 22, 23],
264 [24, 25, 26, 27, 28, 29, 30],
265 [31, 0, 0, 0, 0, 0, 0]],
266 [[0, 1, 2, 3, 4, 5, 6],
267 [7, 8, 9, 10, 11, 12, 13],
268 [14, 15, 16, 17, 18, 19, 20],
269 [21, 22, 23, 24, 25, 26, 27],
270 [28, 29, 30, 0, 0, 0, 0]]],
271 [[[0, 0, 0, 1, 2, 3, 4],
272 [5, 6, 7, 8, 9, 10, 11],
273 [12, 13, 14, 15, 16, 17, 18],
274 [19, 20, 21, 22, 23, 24, 25],
275 [26, 27, 28, 29, 30, 31, 0]],
276 [[0, 0, 0, 0, 0, 0, 1],
277 [2, 3, 4, 5, 6, 7, 8],
278 [9, 10, 11, 12, 13, 14, 15],
279 [16, 17, 18, 19, 20, 21, 22],
280 [23, 24, 25, 26, 27, 28, 29],
281 [30, 31, 0, 0, 0, 0, 0]],
282 [[0, 0, 1, 2, 3, 4, 5],
283 [6, 7, 8, 9, 10, 11, 12],
284 [13, 14, 15, 16, 17, 18, 19],
285 [20, 21, 22, 23, 24, 25, 26],
286 [27, 28, 29, 30, 0, 0, 0]]],
287 [[[0, 0, 0, 0, 1, 2, 3],
288 [4, 5, 6, 7, 8, 9, 10],
289 [11, 12, 13, 14, 15, 16, 17],
290 [18, 19, 20, 21, 22, 23, 24],
291 [25, 26, 27, 28, 29, 30, 31]],
292 [[1, 2, 3, 4, 5, 6, 7],
293 [8, 9, 10, 11, 12, 13, 14],
294 [15, 16, 17, 18, 19, 20, 21],
295 [22, 23, 24, 25, 26, 27, 28],
296 [29, 30, 0, 0, 0, 0, 0]],
297 [[0, 0, 1, 2, 3, 4, 5],
298 [6, 7, 8, 9, 10, 11, 12],
299 [13, 14, 15, 16, 17, 18, 19],
300 [20, 21, 22, 23, 24, 25, 26],
301 [27, 28, 29, 30, 31, 0, 0]]]
302 ]
303
304 result_2004_dates = \
305 [[['12/29/03 12/30/03 12/31/03 01/01/04 01/02/04 01/03/04 01/04/04',
306 '01/05/04 01/06/04 01/07/04 01/08/04 01/09/04 01/10/04 01/11/04',
307 '01/12/04 01/13/04 01/14/04 01/15/04 01/16/04 01/17/04 01/18/04',
308 '01/19/04 01/20/04 01/21/04 01/22/04 01/23/04 01/24/04 01/25/04',
309 '01/26/04 01/27/04 01/28/04 01/29/04 01/30/04 01/31/04 02/01/04'],
310 ['01/26/04 01/27/04 01/28/04 01/29/04 01/30/04 01/31/04 02/01/04',
311 '02/02/04 02/03/04 02/04/04 02/05/04 02/06/04 02/07/04 02/08/04',
312 '02/09/04 02/10/04 02/11/04 02/12/04 02/13/04 02/14/04 02/15/04',
313 '02/16/04 02/17/04 02/18/04 02/19/04 02/20/04 02/21/04 02/22/04',
314 '02/23/04 02/24/04 02/25/04 02/26/04 02/27/04 02/28/04 02/29/04'],
315 ['03/01/04 03/02/04 03/03/04 03/04/04 03/05/04 03/06/04 03/07/04',
316 '03/08/04 03/09/04 03/10/04 03/11/04 03/12/04 03/13/04 03/14/04',
317 '03/15/04 03/16/04 03/17/04 03/18/04 03/19/04 03/20/04 03/21/04',
318 '03/22/04 03/23/04 03/24/04 03/25/04 03/26/04 03/27/04 03/28/04',
319 '03/29/04 03/30/04 03/31/04 04/01/04 04/02/04 04/03/04 04/04/04']],
320 [['03/29/04 03/30/04 03/31/04 04/01/04 04/02/04 04/03/04 04/04/04',
321 '04/05/04 04/06/04 04/07/04 04/08/04 04/09/04 04/10/04 04/11/04',
322 '04/12/04 04/13/04 04/14/04 04/15/04 04/16/04 04/17/04 04/18/04',
323 '04/19/04 04/20/04 04/21/04 04/22/04 04/23/04 04/24/04 04/25/04',
324 '04/26/04 04/27/04 04/28/04 04/29/04 04/30/04 05/01/04 05/02/04'],
325 ['04/26/04 04/27/04 04/28/04 04/29/04 04/30/04 05/01/04 05/02/04',
326 '05/03/04 05/04/04 05/05/04 05/06/04 05/07/04 05/08/04 05/09/04',
327 '05/10/04 05/11/04 05/12/04 05/13/04 05/14/04 05/15/04 05/16/04',
328 '05/17/04 05/18/04 05/19/04 05/20/04 05/21/04 05/22/04 05/23/04',
329 '05/24/04 05/25/04 05/26/04 05/27/04 05/28/04 05/29/04 05/30/04',
330 '05/31/04 06/01/04 06/02/04 06/03/04 06/04/04 06/05/04 06/06/04'],
331 ['05/31/04 06/01/04 06/02/04 06/03/04 06/04/04 06/05/04 06/06/04',
332 '06/07/04 06/08/04 06/09/04 06/10/04 06/11/04 06/12/04 06/13/04',
333 '06/14/04 06/15/04 06/16/04 06/17/04 06/18/04 06/19/04 06/20/04',
334 '06/21/04 06/22/04 06/23/04 06/24/04 06/25/04 06/26/04 06/27/04',
335 '06/28/04 06/29/04 06/30/04 07/01/04 07/02/04 07/03/04 07/04/04']],
336 [['06/28/04 06/29/04 06/30/04 07/01/04 07/02/04 07/03/04 07/04/04',
337 '07/05/04 07/06/04 07/07/04 07/08/04 07/09/04 07/10/04 07/11/04',
338 '07/12/04 07/13/04 07/14/04 07/15/04 07/16/04 07/17/04 07/18/04',
339 '07/19/04 07/20/04 07/21/04 07/22/04 07/23/04 07/24/04 07/25/04',
340 '07/26/04 07/27/04 07/28/04 07/29/04 07/30/04 07/31/04 08/01/04'],
341 ['07/26/04 07/27/04 07/28/04 07/29/04 07/30/04 07/31/04 08/01/04',
342 '08/02/04 08/03/04 08/04/04 08/05/04 08/06/04 08/07/04 08/08/04',
343 '08/09/04 08/10/04 08/11/04 08/12/04 08/13/04 08/14/04 08/15/04',
344 '08/16/04 08/17/04 08/18/04 08/19/04 08/20/04 08/21/04 08/22/04',
345 '08/23/04 08/24/04 08/25/04 08/26/04 08/27/04 08/28/04 08/29/04',
346 '08/30/04 08/31/04 09/01/04 09/02/04 09/03/04 09/04/04 09/05/04'],
347 ['08/30/04 08/31/04 09/01/04 09/02/04 09/03/04 09/04/04 09/05/04',
348 '09/06/04 09/07/04 09/08/04 09/09/04 09/10/04 09/11/04 09/12/04',
349 '09/13/04 09/14/04 09/15/04 09/16/04 09/17/04 09/18/04 09/19/04',
350 '09/20/04 09/21/04 09/22/04 09/23/04 09/24/04 09/25/04 09/26/04',
351 '09/27/04 09/28/04 09/29/04 09/30/04 10/01/04 10/02/04 10/03/04']],
352 [['09/27/04 09/28/04 09/29/04 09/30/04 10/01/04 10/02/04 10/03/04',
353 '10/04/04 10/05/04 10/06/04 10/07/04 10/08/04 10/09/04 10/10/04',
354 '10/11/04 10/12/04 10/13/04 10/14/04 10/15/04 10/16/04 10/17/04',
355 '10/18/04 10/19/04 10/20/04 10/21/04 10/22/04 10/23/04 10/24/04',
356 '10/25/04 10/26/04 10/27/04 10/28/04 10/29/04 10/30/04 10/31/04'],
357 ['11/01/04 11/02/04 11/03/04 11/04/04 11/05/04 11/06/04 11/07/04',
358 '11/08/04 11/09/04 11/10/04 11/11/04 11/12/04 11/13/04 11/14/04',
359 '11/15/04 11/16/04 11/17/04 11/18/04 11/19/04 11/20/04 11/21/04',
360 '11/22/04 11/23/04 11/24/04 11/25/04 11/26/04 11/27/04 11/28/04',
361 '11/29/04 11/30/04 12/01/04 12/02/04 12/03/04 12/04/04 12/05/04'],
362 ['11/29/04 11/30/04 12/01/04 12/02/04 12/03/04 12/04/04 12/05/04',
363 '12/06/04 12/07/04 12/08/04 12/09/04 12/10/04 12/11/04 12/12/04',
364 '12/13/04 12/14/04 12/15/04 12/16/04 12/17/04 12/18/04 12/19/04',
365 '12/20/04 12/21/04 12/22/04 12/23/04 12/24/04 12/25/04 12/26/04',
366 '12/27/04 12/28/04 12/29/04 12/30/04 12/31/04 01/01/05 01/02/05']]]
367
368
369 class ESC[4;38;5;81mOutputTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
370 def normalize_calendar(self, s):
371 # Filters out locale dependent strings
372 def neitherspacenordigit(c):
373 return not c.isspace() and not c.isdigit()
374
375 lines = []
376 for line in s.splitlines(keepends=False):
377 # Drop texts, as they are locale dependent
378 if line and not filter(neitherspacenordigit, line):
379 lines.append(line)
380 return lines
381
382 def check_htmlcalendar_encoding(self, req, res):
383 cal = calendar.HTMLCalendar()
384 format_ = default_format.copy()
385 format_["encoding"] = req or 'utf-8'
386 output = cal.formatyearpage(2004, encoding=req)
387 self.assertEqual(
388 output,
389 result_2004_html.format(**format_).encode(res)
390 )
391
392 def test_output(self):
393 self.assertEqual(
394 self.normalize_calendar(calendar.calendar(2004)),
395 self.normalize_calendar(result_2004_text)
396 )
397 self.assertEqual(
398 self.normalize_calendar(calendar.calendar(0)),
399 self.normalize_calendar(result_0_text)
400 )
401
402 def test_output_textcalendar(self):
403 self.assertEqual(
404 calendar.TextCalendar().formatyear(2004),
405 result_2004_text
406 )
407 self.assertEqual(
408 calendar.TextCalendar().formatyear(0),
409 result_0_text
410 )
411
412 def test_output_htmlcalendar_encoding_ascii(self):
413 self.check_htmlcalendar_encoding('ascii', 'ascii')
414
415 def test_output_htmlcalendar_encoding_utf8(self):
416 self.check_htmlcalendar_encoding('utf-8', 'utf-8')
417
418 def test_output_htmlcalendar_encoding_default(self):
419 self.check_htmlcalendar_encoding(None, sys.getdefaultencoding())
420
421 def test_yeardatescalendar(self):
422 def shrink(cal):
423 return [[[' '.join('{:02d}/{:02d}/{}'.format(
424 d.month, d.day, str(d.year)[-2:]) for d in z)
425 for z in y] for y in x] for x in cal]
426 self.assertEqual(
427 shrink(calendar.Calendar().yeardatescalendar(2004)),
428 result_2004_dates
429 )
430
431 def test_yeardayscalendar(self):
432 self.assertEqual(
433 calendar.Calendar().yeardayscalendar(2004),
434 result_2004_days
435 )
436
437 def test_formatweekheader_short(self):
438 self.assertEqual(
439 calendar.TextCalendar().formatweekheader(2),
440 'Mo Tu We Th Fr Sa Su'
441 )
442
443 def test_formatweekheader_long(self):
444 self.assertEqual(
445 calendar.TextCalendar().formatweekheader(9),
446 ' Monday Tuesday Wednesday Thursday '
447 ' Friday Saturday Sunday '
448 )
449
450 def test_formatmonth(self):
451 self.assertEqual(
452 calendar.TextCalendar().formatmonth(2004, 1),
453 result_2004_01_text
454 )
455 self.assertEqual(
456 calendar.TextCalendar().formatmonth(0, 2),
457 result_0_02_text
458 )
459
460 def test_formatmonthname_with_year(self):
461 self.assertEqual(
462 calendar.HTMLCalendar().formatmonthname(2004, 1, withyear=True),
463 '<tr><th colspan="7" class="month">January 2004</th></tr>'
464 )
465
466 def test_formatmonthname_without_year(self):
467 self.assertEqual(
468 calendar.HTMLCalendar().formatmonthname(2004, 1, withyear=False),
469 '<tr><th colspan="7" class="month">January</th></tr>'
470 )
471
472 def test_prweek(self):
473 with support.captured_stdout() as out:
474 week = [(1,0), (2,1), (3,2), (4,3), (5,4), (6,5), (7,6)]
475 calendar.TextCalendar().prweek(week, 1)
476 self.assertEqual(out.getvalue(), " 1 2 3 4 5 6 7")
477
478 def test_prmonth(self):
479 with support.captured_stdout() as out:
480 calendar.TextCalendar().prmonth(2004, 1)
481 self.assertEqual(out.getvalue(), result_2004_01_text)
482
483 def test_pryear(self):
484 with support.captured_stdout() as out:
485 calendar.TextCalendar().pryear(2004)
486 self.assertEqual(out.getvalue(), result_2004_text)
487
488 def test_format(self):
489 with support.captured_stdout() as out:
490 calendar.format(["1", "2", "3"], colwidth=3, spacing=1)
491 self.assertEqual(out.getvalue().strip(), "1 2 3")
492
493 class ESC[4;38;5;81mCalendarTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
494
495 def test_deprecation_warning(self):
496 with self.assertWarnsRegex(
497 DeprecationWarning,
498 "The 'January' attribute is deprecated, use 'JANUARY' instead"
499 ):
500 calendar.January
501
502 def test_isleap(self):
503 # Make sure that the return is right for a few years, and
504 # ensure that the return values are 1 or 0, not just true or
505 # false (see SF bug #485794). Specific additional tests may
506 # be appropriate; this tests a single "cycle".
507 self.assertEqual(calendar.isleap(2000), 1)
508 self.assertEqual(calendar.isleap(2001), 0)
509 self.assertEqual(calendar.isleap(2002), 0)
510 self.assertEqual(calendar.isleap(2003), 0)
511
512 def test_setfirstweekday(self):
513 self.assertRaises(TypeError, calendar.setfirstweekday, 'flabber')
514 self.assertRaises(ValueError, calendar.setfirstweekday, -1)
515 self.assertRaises(ValueError, calendar.setfirstweekday, 200)
516 orig = calendar.firstweekday()
517 calendar.setfirstweekday(calendar.SUNDAY)
518 self.assertEqual(calendar.firstweekday(), calendar.SUNDAY)
519 calendar.setfirstweekday(calendar.MONDAY)
520 self.assertEqual(calendar.firstweekday(), calendar.MONDAY)
521 calendar.setfirstweekday(orig)
522
523 def test_illegal_weekday_reported(self):
524 with self.assertRaisesRegex(calendar.IllegalWeekdayError, '123'):
525 calendar.setfirstweekday(123)
526
527 def test_enumerate_weekdays(self):
528 self.assertRaises(IndexError, calendar.day_abbr.__getitem__, -10)
529 self.assertRaises(IndexError, calendar.day_name.__getitem__, 10)
530 self.assertEqual(len([d for d in calendar.day_abbr]), 7)
531
532 def test_days(self):
533 for attr in "day_name", "day_abbr":
534 value = getattr(calendar, attr)
535 self.assertEqual(len(value), 7)
536 self.assertEqual(len(value[:]), 7)
537 # ensure they're all unique
538 self.assertEqual(len(set(value)), 7)
539 # verify it "acts like a sequence" in two forms of iteration
540 self.assertEqual(value[::-1], list(reversed(value)))
541
542 def test_months(self):
543 for attr in "month_name", "month_abbr":
544 value = getattr(calendar, attr)
545 self.assertEqual(len(value), 13)
546 self.assertEqual(len(value[:]), 13)
547 self.assertEqual(value[0], "")
548 # ensure they're all unique
549 self.assertEqual(len(set(value)), 13)
550 # verify it "acts like a sequence" in two forms of iteration
551 self.assertEqual(value[::-1], list(reversed(value)))
552
553 def test_locale_calendars(self):
554 # ensure that Locale{Text,HTML}Calendar resets the locale properly
555 # (it is still not thread-safe though)
556 old_october = calendar.TextCalendar().formatmonthname(2010, 10, 10)
557 try:
558 cal = calendar.LocaleTextCalendar(locale='')
559 local_weekday = cal.formatweekday(1, 10)
560 local_month = cal.formatmonthname(2010, 10, 10)
561 except locale.Error:
562 # cannot set the system default locale -- skip rest of test
563 raise unittest.SkipTest('cannot set the system default locale')
564 self.assertIsInstance(local_weekday, str)
565 self.assertIsInstance(local_month, str)
566 self.assertEqual(len(local_weekday), 10)
567 self.assertGreaterEqual(len(local_month), 10)
568 cal = calendar.LocaleHTMLCalendar(locale='')
569 local_weekday = cal.formatweekday(1)
570 local_month = cal.formatmonthname(2010, 10)
571 self.assertIsInstance(local_weekday, str)
572 self.assertIsInstance(local_month, str)
573 new_october = calendar.TextCalendar().formatmonthname(2010, 10, 10)
574 self.assertEqual(old_october, new_october)
575
576 def test_locale_calendar_formatweekday(self):
577 try:
578 # formatweekday uses different day names based on the available width.
579 cal = calendar.LocaleTextCalendar(locale='en_US')
580 # For really short widths, the abbreviated name is truncated.
581 self.assertEqual(cal.formatweekday(0, 1), "M")
582 self.assertEqual(cal.formatweekday(0, 2), "Mo")
583 # For short widths, a centered, abbreviated name is used.
584 self.assertEqual(cal.formatweekday(0, 3), "Mon")
585 self.assertEqual(cal.formatweekday(0, 5), " Mon ")
586 self.assertEqual(cal.formatweekday(0, 8), " Mon ")
587 # For long widths, the full day name is used.
588 self.assertEqual(cal.formatweekday(0, 9), " Monday ")
589 self.assertEqual(cal.formatweekday(0, 10), " Monday ")
590 except locale.Error:
591 raise unittest.SkipTest('cannot set the en_US locale')
592
593 def test_locale_html_calendar_custom_css_class_month_name(self):
594 try:
595 cal = calendar.LocaleHTMLCalendar(locale='')
596 local_month = cal.formatmonthname(2010, 10, 10)
597 except locale.Error:
598 # cannot set the system default locale -- skip rest of test
599 raise unittest.SkipTest('cannot set the system default locale')
600 self.assertIn('class="month"', local_month)
601 cal.cssclass_month_head = "text-center month"
602 local_month = cal.formatmonthname(2010, 10, 10)
603 self.assertIn('class="text-center month"', local_month)
604
605 def test_locale_html_calendar_custom_css_class_weekday(self):
606 try:
607 cal = calendar.LocaleHTMLCalendar(locale='')
608 local_weekday = cal.formatweekday(6)
609 except locale.Error:
610 # cannot set the system default locale -- skip rest of test
611 raise unittest.SkipTest('cannot set the system default locale')
612 self.assertIn('class="sun"', local_weekday)
613 cal.cssclasses_weekday_head = ["mon2", "tue2", "wed2", "thu2", "fri2", "sat2", "sun2"]
614 local_weekday = cal.formatweekday(6)
615 self.assertIn('class="sun2"', local_weekday)
616
617 def test_itermonthdays3(self):
618 # ensure itermonthdays3 doesn't overflow after datetime.MAXYEAR
619 list(calendar.Calendar().itermonthdays3(datetime.MAXYEAR, 12))
620
621 def test_itermonthdays4(self):
622 cal = calendar.Calendar(firstweekday=3)
623 days = list(cal.itermonthdays4(2001, 2))
624 self.assertEqual(days[0], (2001, 2, 1, 3))
625 self.assertEqual(days[-1], (2001, 2, 28, 2))
626
627 def test_itermonthdays(self):
628 for firstweekday in range(7):
629 cal = calendar.Calendar(firstweekday)
630 # Test the extremes, see #28253 and #26650
631 for y, m in [(1, 1), (9999, 12)]:
632 days = list(cal.itermonthdays(y, m))
633 self.assertIn(len(days), (35, 42))
634 # Test a short month
635 cal = calendar.Calendar(firstweekday=3)
636 days = list(cal.itermonthdays(2001, 2))
637 self.assertEqual(days, list(range(1, 29)))
638
639 def test_itermonthdays2(self):
640 for firstweekday in range(7):
641 cal = calendar.Calendar(firstweekday)
642 # Test the extremes, see #28253 and #26650
643 for y, m in [(1, 1), (9999, 12)]:
644 days = list(cal.itermonthdays2(y, m))
645 self.assertEqual(days[0][1], firstweekday)
646 self.assertEqual(days[-1][1], (firstweekday - 1) % 7)
647
648 def test_iterweekdays(self):
649 week0 = list(range(7))
650 for firstweekday in range(7):
651 cal = calendar.Calendar(firstweekday)
652 week = list(cal.iterweekdays())
653 expected = week0[firstweekday:] + week0[:firstweekday]
654 self.assertEqual(week, expected)
655
656
657 class ESC[4;38;5;81mMonthCalendarTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
658 def setUp(self):
659 self.oldfirstweekday = calendar.firstweekday()
660 calendar.setfirstweekday(self.firstweekday)
661
662 def tearDown(self):
663 calendar.setfirstweekday(self.oldfirstweekday)
664
665 def check_weeks(self, year, month, weeks):
666 cal = calendar.monthcalendar(year, month)
667 self.assertEqual(len(cal), len(weeks))
668 for i in range(len(weeks)):
669 self.assertEqual(weeks[i], sum(day != 0 for day in cal[i]))
670
671
672 class ESC[4;38;5;81mMondayTestCase(ESC[4;38;5;149mMonthCalendarTestCase):
673 firstweekday = calendar.MONDAY
674
675 def test_february(self):
676 # A 28-day february starting on monday (7+7+7+7 days)
677 self.check_weeks(1999, 2, (7, 7, 7, 7))
678
679 # A 28-day february starting on tuesday (6+7+7+7+1 days)
680 self.check_weeks(2005, 2, (6, 7, 7, 7, 1))
681
682 # A 28-day february starting on sunday (1+7+7+7+6 days)
683 self.check_weeks(1987, 2, (1, 7, 7, 7, 6))
684
685 # A 29-day february starting on monday (7+7+7+7+1 days)
686 self.check_weeks(1988, 2, (7, 7, 7, 7, 1))
687
688 # A 29-day february starting on tuesday (6+7+7+7+2 days)
689 self.check_weeks(1972, 2, (6, 7, 7, 7, 2))
690
691 # A 29-day february starting on sunday (1+7+7+7+7 days)
692 self.check_weeks(2004, 2, (1, 7, 7, 7, 7))
693
694 def test_april(self):
695 # A 30-day april starting on monday (7+7+7+7+2 days)
696 self.check_weeks(1935, 4, (7, 7, 7, 7, 2))
697
698 # A 30-day april starting on tuesday (6+7+7+7+3 days)
699 self.check_weeks(1975, 4, (6, 7, 7, 7, 3))
700
701 # A 30-day april starting on sunday (1+7+7+7+7+1 days)
702 self.check_weeks(1945, 4, (1, 7, 7, 7, 7, 1))
703
704 # A 30-day april starting on saturday (2+7+7+7+7 days)
705 self.check_weeks(1995, 4, (2, 7, 7, 7, 7))
706
707 # A 30-day april starting on friday (3+7+7+7+6 days)
708 self.check_weeks(1994, 4, (3, 7, 7, 7, 6))
709
710 def test_december(self):
711 # A 31-day december starting on monday (7+7+7+7+3 days)
712 self.check_weeks(1980, 12, (7, 7, 7, 7, 3))
713
714 # A 31-day december starting on tuesday (6+7+7+7+4 days)
715 self.check_weeks(1987, 12, (6, 7, 7, 7, 4))
716
717 # A 31-day december starting on sunday (1+7+7+7+7+2 days)
718 self.check_weeks(1968, 12, (1, 7, 7, 7, 7, 2))
719
720 # A 31-day december starting on thursday (4+7+7+7+6 days)
721 self.check_weeks(1988, 12, (4, 7, 7, 7, 6))
722
723 # A 31-day december starting on friday (3+7+7+7+7 days)
724 self.check_weeks(2017, 12, (3, 7, 7, 7, 7))
725
726 # A 31-day december starting on saturday (2+7+7+7+7+1 days)
727 self.check_weeks(2068, 12, (2, 7, 7, 7, 7, 1))
728
729
730 class ESC[4;38;5;81mSundayTestCase(ESC[4;38;5;149mMonthCalendarTestCase):
731 firstweekday = calendar.SUNDAY
732
733 def test_february(self):
734 # A 28-day february starting on sunday (7+7+7+7 days)
735 self.check_weeks(2009, 2, (7, 7, 7, 7))
736
737 # A 28-day february starting on monday (6+7+7+7+1 days)
738 self.check_weeks(1999, 2, (6, 7, 7, 7, 1))
739
740 # A 28-day february starting on saturday (1+7+7+7+6 days)
741 self.check_weeks(1997, 2, (1, 7, 7, 7, 6))
742
743 # A 29-day february starting on sunday (7+7+7+7+1 days)
744 self.check_weeks(2004, 2, (7, 7, 7, 7, 1))
745
746 # A 29-day february starting on monday (6+7+7+7+2 days)
747 self.check_weeks(1960, 2, (6, 7, 7, 7, 2))
748
749 # A 29-day february starting on saturday (1+7+7+7+7 days)
750 self.check_weeks(1964, 2, (1, 7, 7, 7, 7))
751
752 def test_april(self):
753 # A 30-day april starting on sunday (7+7+7+7+2 days)
754 self.check_weeks(1923, 4, (7, 7, 7, 7, 2))
755
756 # A 30-day april starting on monday (6+7+7+7+3 days)
757 self.check_weeks(1918, 4, (6, 7, 7, 7, 3))
758
759 # A 30-day april starting on saturday (1+7+7+7+7+1 days)
760 self.check_weeks(1950, 4, (1, 7, 7, 7, 7, 1))
761
762 # A 30-day april starting on friday (2+7+7+7+7 days)
763 self.check_weeks(1960, 4, (2, 7, 7, 7, 7))
764
765 # A 30-day april starting on thursday (3+7+7+7+6 days)
766 self.check_weeks(1909, 4, (3, 7, 7, 7, 6))
767
768 def test_december(self):
769 # A 31-day december starting on sunday (7+7+7+7+3 days)
770 self.check_weeks(2080, 12, (7, 7, 7, 7, 3))
771
772 # A 31-day december starting on monday (6+7+7+7+4 days)
773 self.check_weeks(1941, 12, (6, 7, 7, 7, 4))
774
775 # A 31-day december starting on saturday (1+7+7+7+7+2 days)
776 self.check_weeks(1923, 12, (1, 7, 7, 7, 7, 2))
777
778 # A 31-day december starting on wednesday (4+7+7+7+6 days)
779 self.check_weeks(1948, 12, (4, 7, 7, 7, 6))
780
781 # A 31-day december starting on thursday (3+7+7+7+7 days)
782 self.check_weeks(1927, 12, (3, 7, 7, 7, 7))
783
784 # A 31-day december starting on friday (2+7+7+7+7+1 days)
785 self.check_weeks(1995, 12, (2, 7, 7, 7, 7, 1))
786
787 class ESC[4;38;5;81mTimegmTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
788 TIMESTAMPS = [0, 10, 100, 1000, 10000, 100000, 1000000,
789 1234567890, 1262304000, 1275785153,]
790 def test_timegm(self):
791 for secs in self.TIMESTAMPS:
792 tuple = time.gmtime(secs)
793 self.assertEqual(secs, calendar.timegm(tuple))
794
795 class ESC[4;38;5;81mMonthRangeTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
796 def test_january(self):
797 # Tests valid lower boundary case.
798 self.assertEqual(calendar.monthrange(2004,1), (3,31))
799
800 def test_february_leap(self):
801 # Tests February during leap year.
802 self.assertEqual(calendar.monthrange(2004,2), (6,29))
803
804 def test_february_nonleap(self):
805 # Tests February in non-leap year.
806 self.assertEqual(calendar.monthrange(2010,2), (0,28))
807
808 def test_december(self):
809 # Tests valid upper boundary case.
810 self.assertEqual(calendar.monthrange(2004,12), (2,31))
811
812 def test_zeroth_month(self):
813 # Tests low invalid boundary case.
814 with self.assertRaises(calendar.IllegalMonthError):
815 calendar.monthrange(2004, 0)
816
817 def test_thirteenth_month(self):
818 # Tests high invalid boundary case.
819 with self.assertRaises(calendar.IllegalMonthError):
820 calendar.monthrange(2004, 13)
821
822 def test_illegal_month_reported(self):
823 with self.assertRaisesRegex(calendar.IllegalMonthError, '65'):
824 calendar.monthrange(2004, 65)
825
826 class ESC[4;38;5;81mLeapdaysTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
827 def test_no_range(self):
828 # test when no range i.e. two identical years as args
829 self.assertEqual(calendar.leapdays(2010,2010), 0)
830
831 def test_no_leapdays(self):
832 # test when no leap years in range
833 self.assertEqual(calendar.leapdays(2010,2011), 0)
834
835 def test_no_leapdays_upper_boundary(self):
836 # test no leap years in range, when upper boundary is a leap year
837 self.assertEqual(calendar.leapdays(2010,2012), 0)
838
839 def test_one_leapday_lower_boundary(self):
840 # test when one leap year in range, lower boundary is leap year
841 self.assertEqual(calendar.leapdays(2012,2013), 1)
842
843 def test_several_leapyears_in_range(self):
844 self.assertEqual(calendar.leapdays(1997,2020), 5)
845
846
847 def conv(s):
848 return s.replace('\n', os.linesep).encode()
849
850 class ESC[4;38;5;81mCommandLineTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
851 def run_ok(self, *args):
852 return assert_python_ok('-m', 'calendar', *args)[1]
853
854 def assertFailure(self, *args):
855 rc, stdout, stderr = assert_python_failure('-m', 'calendar', *args)
856 self.assertIn(b'usage:', stderr)
857 self.assertEqual(rc, 2)
858
859 def test_help(self):
860 stdout = self.run_ok('-h')
861 self.assertIn(b'usage:', stdout)
862 self.assertIn(b'calendar.py', stdout)
863 self.assertIn(b'--help', stdout)
864
865 def test_illegal_arguments(self):
866 self.assertFailure('-z')
867 self.assertFailure('spam')
868 self.assertFailure('2004', 'spam')
869 self.assertFailure('-t', 'html', '2004', '1')
870
871 def test_output_current_year(self):
872 stdout = self.run_ok()
873 year = datetime.datetime.now().year
874 self.assertIn((' %s' % year).encode(), stdout)
875 self.assertIn(b'January', stdout)
876 self.assertIn(b'Mo Tu We Th Fr Sa Su', stdout)
877
878 def test_output_year(self):
879 stdout = self.run_ok('2004')
880 self.assertEqual(stdout, conv(result_2004_text))
881
882 def test_output_month(self):
883 stdout = self.run_ok('2004', '1')
884 self.assertEqual(stdout, conv(result_2004_01_text))
885
886 def test_option_encoding(self):
887 self.assertFailure('-e')
888 self.assertFailure('--encoding')
889 stdout = self.run_ok('--encoding', 'utf-16-le', '2004')
890 self.assertEqual(stdout, result_2004_text.encode('utf-16-le'))
891
892 def test_option_locale(self):
893 self.assertFailure('-L')
894 self.assertFailure('--locale')
895 self.assertFailure('-L', 'en')
896
897 lang, enc = locale.getlocale()
898 lang = lang or 'C'
899 enc = enc or 'UTF-8'
900 try:
901 oldlocale = locale.getlocale(locale.LC_TIME)
902 try:
903 locale.setlocale(locale.LC_TIME, (lang, enc))
904 finally:
905 locale.setlocale(locale.LC_TIME, oldlocale)
906 except (locale.Error, ValueError):
907 self.skipTest('cannot set the system default locale')
908 stdout = self.run_ok('--locale', lang, '--encoding', enc, '2004')
909 self.assertIn('2004'.encode(enc), stdout)
910
911 def test_option_width(self):
912 self.assertFailure('-w')
913 self.assertFailure('--width')
914 self.assertFailure('-w', 'spam')
915 stdout = self.run_ok('--width', '3', '2004')
916 self.assertIn(b'Mon Tue Wed Thu Fri Sat Sun', stdout)
917
918 def test_option_lines(self):
919 self.assertFailure('-l')
920 self.assertFailure('--lines')
921 self.assertFailure('-l', 'spam')
922 stdout = self.run_ok('--lines', '2', '2004')
923 self.assertIn(conv('December\n\nMo Tu We'), stdout)
924
925 def test_option_spacing(self):
926 self.assertFailure('-s')
927 self.assertFailure('--spacing')
928 self.assertFailure('-s', 'spam')
929 stdout = self.run_ok('--spacing', '8', '2004')
930 self.assertIn(b'Su Mo', stdout)
931
932 def test_option_months(self):
933 self.assertFailure('-m')
934 self.assertFailure('--month')
935 self.assertFailure('-m', 'spam')
936 stdout = self.run_ok('--months', '1', '2004')
937 self.assertIn(conv('\nMo Tu We Th Fr Sa Su\n'), stdout)
938
939 def test_option_type(self):
940 self.assertFailure('-t')
941 self.assertFailure('--type')
942 self.assertFailure('-t', 'spam')
943 stdout = self.run_ok('--type', 'text', '2004')
944 self.assertEqual(stdout, conv(result_2004_text))
945 stdout = self.run_ok('--type', 'html', '2004')
946 self.assertEqual(stdout[:6], b'<?xml ')
947 self.assertIn(b'<title>Calendar for 2004</title>', stdout)
948
949 def test_html_output_current_year(self):
950 stdout = self.run_ok('--type', 'html')
951 year = datetime.datetime.now().year
952 self.assertIn(('<title>Calendar for %s</title>' % year).encode(),
953 stdout)
954 self.assertIn(b'<tr><th colspan="7" class="month">January</th></tr>',
955 stdout)
956
957 def test_html_output_year_encoding(self):
958 stdout = self.run_ok('-t', 'html', '--encoding', 'ascii', '2004')
959 self.assertEqual(stdout,
960 result_2004_html.format(**default_format).encode('ascii'))
961
962 def test_html_output_year_css(self):
963 self.assertFailure('-t', 'html', '-c')
964 self.assertFailure('-t', 'html', '--css')
965 stdout = self.run_ok('-t', 'html', '--css', 'custom.css', '2004')
966 self.assertIn(b'<link rel="stylesheet" type="text/css" '
967 b'href="custom.css" />', stdout)
968
969
970 class ESC[4;38;5;81mMiscTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
971 def test__all__(self):
972 not_exported = {
973 'mdays', 'January', 'February', 'EPOCH',
974 'different_locale', 'c', 'prweek', 'week', 'format',
975 'formatstring', 'main', 'monthlen', 'prevmonth', 'nextmonth'}
976 support.check__all__(self, calendar, not_exported=not_exported)
977
978
979 class ESC[4;38;5;81mTestSubClassingCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
980
981 def setUp(self):
982
983 class ESC[4;38;5;81mCustomHTMLCal(ESC[4;38;5;149mcalendarESC[4;38;5;149m.ESC[4;38;5;149mHTMLCalendar):
984 cssclasses = [style + " text-nowrap" for style in
985 calendar.HTMLCalendar.cssclasses]
986 cssclasses_weekday_head = ["red", "blue", "green", "lilac",
987 "yellow", "orange", "pink"]
988 cssclass_month_head = "text-center month-head"
989 cssclass_month = "text-center month"
990 cssclass_year = "text-italic "
991 cssclass_year_head = "lead "
992
993 self.cal = CustomHTMLCal()
994
995 def test_formatmonthname(self):
996 self.assertIn('class="text-center month-head"',
997 self.cal.formatmonthname(2017, 5))
998
999 def test_formatmonth(self):
1000 self.assertIn('class="text-center month"',
1001 self.cal.formatmonth(2017, 5))
1002
1003 def test_formatweek(self):
1004 weeks = self.cal.monthdays2calendar(2017, 5)
1005 self.assertIn('class="wed text-nowrap"', self.cal.formatweek(weeks[0]))
1006
1007 def test_formatweek_head(self):
1008 header = self.cal.formatweekheader()
1009 for color in self.cal.cssclasses_weekday_head:
1010 self.assertIn('<th class="%s">' % color, header)
1011
1012 def test_format_year(self):
1013 self.assertIn(
1014 ('<table border="0" cellpadding="0" cellspacing="0" class="%s">' %
1015 self.cal.cssclass_year), self.cal.formatyear(2017))
1016
1017 def test_format_year_head(self):
1018 self.assertIn('<tr><th colspan="%d" class="%s">%s</th></tr>' % (
1019 3, self.cal.cssclass_year_head, 2017), self.cal.formatyear(2017))
1020
1021 if __name__ == "__main__":
1022 unittest.main()