From 66c88ce30ca2b23daa37038e1a3c0de98f241f50 Mon Sep 17 00:00:00 2001 From: Alexander Belopolsky Date: Thu, 26 Oct 2017 15:34:11 -0400 Subject: [PATCH] Closes bpo-28281: Remove year (1-9999) limits on the weekday() function. (#4109) Patch by Mark Gollahon. --- Doc/library/calendar.rst | 8 ++- Lib/calendar.py | 5 +- Lib/test/test_calendar.py | 62 +++++++++++++++++++ Misc/ACKS | 1 + .../2017-10-26-14-54-38.bpo-28281.7ZN5FG.rst | 3 + 5 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-10-26-14-54-38.bpo-28281.7ZN5FG.rst diff --git a/Doc/library/calendar.rst b/Doc/library/calendar.rst index 8fe93fd4de3..56b75ef0f85 100644 --- a/Doc/library/calendar.rst +++ b/Doc/library/calendar.rst @@ -19,11 +19,13 @@ the week to Sunday (6) or to any other weekday. Parameters that specify dates are given as integers. For related functionality, see also the :mod:`datetime` and :mod:`time` modules. -Most of these functions and classes rely on the :mod:`datetime` module which -uses an idealized calendar, the current Gregorian calendar extended +The functions and classes defined in this module +use an idealized calendar, the current Gregorian calendar extended indefinitely in both directions. This matches the definition of the "proleptic Gregorian" calendar in Dershowitz and Reingold's book "Calendrical Calculations", where -it's the base calendar for all computations. +it's the base calendar for all computations. Zero and negative years are +interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is +2 BC, and so on. .. class:: Calendar(firstweekday=0) diff --git a/Lib/calendar.py b/Lib/calendar.py index fb594e0f5b0..3828c43ed27 100644 --- a/Lib/calendar.py +++ b/Lib/calendar.py @@ -111,8 +111,9 @@ def leapdays(y1, y2): def weekday(year, month, day): - """Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), - day (1-31).""" + """Return weekday (0-6 ~ Mon-Sun) for year, month (1-12), day (1-31).""" + if not datetime.MINYEAR <= year <= datetime.MAXYEAR: + year = 2000 + year % 400 return datetime.date(year, month, day).weekday() diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py index ad8b6bb6b93..6241d114d33 100644 --- a/Lib/test/test_calendar.py +++ b/Lib/test/test_calendar.py @@ -9,6 +9,56 @@ import sys import datetime import os +# From https://en.wikipedia.org/wiki/Leap_year_starting_on_Saturday +result_0_02_text = """\ + February 0 +Mo Tu We Th Fr Sa Su + 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 +""" + +result_0_text = """\ + 0 + + 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 1 2 3 4 5 6 1 2 3 4 5 + 3 4 5 6 7 8 9 7 8 9 10 11 12 13 6 7 8 9 10 11 12 +10 11 12 13 14 15 16 14 15 16 17 18 19 20 13 14 15 16 17 18 19 +17 18 19 20 21 22 23 21 22 23 24 25 26 27 20 21 22 23 24 25 26 +24 25 26 27 28 29 30 28 29 27 28 29 30 31 +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 1 2 3 4 5 6 7 1 2 3 4 + 3 4 5 6 7 8 9 8 9 10 11 12 13 14 5 6 7 8 9 10 11 +10 11 12 13 14 15 16 15 16 17 18 19 20 21 12 13 14 15 16 17 18 +17 18 19 20 21 22 23 22 23 24 25 26 27 28 19 20 21 22 23 24 25 +24 25 26 27 28 29 30 29 30 31 26 27 28 29 30 + + 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 1 2 3 4 5 6 1 2 3 + 3 4 5 6 7 8 9 7 8 9 10 11 12 13 4 5 6 7 8 9 10 +10 11 12 13 14 15 16 14 15 16 17 18 19 20 11 12 13 14 15 16 17 +17 18 19 20 21 22 23 21 22 23 24 25 26 27 18 19 20 21 22 23 24 +24 25 26 27 28 29 30 28 29 30 31 25 26 27 28 29 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 1 2 3 4 5 1 2 3 + 2 3 4 5 6 7 8 6 7 8 9 10 11 12 4 5 6 7 8 9 10 + 9 10 11 12 13 14 15 13 14 15 16 17 18 19 11 12 13 14 15 16 17 +16 17 18 19 20 21 22 20 21 22 23 24 25 26 18 19 20 21 22 23 24 +23 24 25 26 27 28 29 27 28 29 30 25 26 27 28 29 30 31 +30 31 +""" + result_2004_01_text = """\ January 2004 Mo Tu We Th Fr Sa Su @@ -343,12 +393,20 @@ class OutputTestCase(unittest.TestCase): self.normalize_calendar(calendar.calendar(2004)), self.normalize_calendar(result_2004_text) ) + self.assertEqual( + self.normalize_calendar(calendar.calendar(0)), + self.normalize_calendar(result_0_text) + ) def test_output_textcalendar(self): self.assertEqual( calendar.TextCalendar().formatyear(2004), result_2004_text ) + self.assertEqual( + calendar.TextCalendar().formatyear(0), + result_0_text + ) def test_output_htmlcalendar_encoding_ascii(self): self.check_htmlcalendar_encoding('ascii', 'ascii') @@ -393,6 +451,10 @@ class OutputTestCase(unittest.TestCase): calendar.TextCalendar().formatmonth(2004, 1), result_2004_01_text ) + self.assertEqual( + calendar.TextCalendar().formatmonth(0, 2), + result_0_02_text + ) def test_formatmonthname_with_year(self): self.assertEqual( diff --git a/Misc/ACKS b/Misc/ACKS index 7b174c63535..ac7a258df18 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -545,6 +545,7 @@ Karan Goel Jeroen Van Goey Christoph Gohlke Tim Golden +Mark Gollahon Guilherme Gonçalves Tiago Gonçalves Chris Gonnerman diff --git a/Misc/NEWS.d/next/Library/2017-10-26-14-54-38.bpo-28281.7ZN5FG.rst b/Misc/NEWS.d/next/Library/2017-10-26-14-54-38.bpo-28281.7ZN5FG.rst new file mode 100644 index 00000000000..e7681dd4e8f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-10-26-14-54-38.bpo-28281.7ZN5FG.rst @@ -0,0 +1,3 @@ +Remove year (1-9999) limits on the Calendar.weekday() function. + +Patch by Mark Gollahon.