Commit e11b510a authored by Raymond Hettinger's avatar Raymond Hettinger

SF 658405: calendar.py to rely on the datetime module instead of the time

module.

The code is shorter, more readable, faster, and dramatically increases the
range of acceptable dates.

Also, used the floor division operator in leapdays().
parent 80475bb4
......@@ -15,10 +15,12 @@ convention). Use \function{setfirstweekday()} to set the first day of the
week to Sunday (6) or to any other weekday. Parameters that specify
dates are given as integers.
Most of these functions rely on the platform provided \function{mktime()}.
Therefore, valid argument values may vary from system to system.
On Unix, valid years are typically between \code{1970} and \code{2037},
but may be work between \code{1902} and \code{2037}.
Most of these functions rely on the \module{datetime} module which
uses an idealized calendar, the current Gregorian calendar indefinitely
extended 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.
\begin{funcdesc}{setfirstweekday}{weekday}
Sets the weekday (\code{0} is Monday, \code{6} is Sunday) to start
......
......@@ -5,10 +5,7 @@ default, these calendars have Monday as the first day of the week, and
Sunday as the last (the European convention). Use setfirstweekday() to
set the first day of the week (0=Monday, 6=Sunday)."""
# Revision 2: uses functions from built-in time module
# Import functions and variables from time module
from time import localtime, mktime, strftime
import datetime
__all__ = ["error","setfirstweekday","firstweekday","isleap",
"leapdays","weekday","monthrange","monthcalendar",
......@@ -35,7 +32,7 @@ class _localized_month:
self.format = format
def __getitem__(self, i):
data = [strftime(self.format, (2001, j, 1, 12, 0, 0, 1, 1, 0))
data = [datetime.date(2001, j, 1).strftime(self.format)
for j in range(1, 13)]
data.insert(0, "")
return data[i]
......@@ -49,7 +46,7 @@ class _localized_day:
def __getitem__(self, i):
# January 1, 2001, was a Monday.
data = [strftime(self.format, (2001, 1, j+1, 12, 0, 0, j, j+1, 0))
data = [datetime.date(2001, 1, j+1).strftime(self.format)
for j in range(7)]
return data[i]
......@@ -89,14 +86,12 @@ def leapdays(y1, y2):
Assume y1 <= y2."""
y1 -= 1
y2 -= 1
return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400)
return (y2//4 - y1//4) - (y2//100 - y1//100) + (y2//400 - y1//400)
def weekday(year, month, day):
"""Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12),
day (1-31)."""
secs = mktime((year, month, day, 0, 0, 0, 0, 0, 0))
tuple = localtime(secs)
return tuple[6]
return datetime.date(year, month, day).weekday()
def monthrange(year, month):
"""Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for
......@@ -213,17 +208,12 @@ def calendar(year, w=0, l=0, c=_spacing):
return s[:-l] + '\n'
EPOCH = 1970
_EPOCH_ORD = datetime.date(EPOCH, 1, 1).toordinal()
def timegm(tuple):
"""Unrelated but handy function to calculate Unix timestamp from GMT."""
year, month, day, hour, minute, second = tuple[:6]
assert year >= EPOCH
assert 1 <= month <= 12
days = 365*(year-EPOCH) + leapdays(EPOCH, year)
for i in range(1, month):
days = days + mdays[i]
if month > 2 and isleap(year):
days = days + 1
days = days + day - 1
days = datetime.date(year, month, day).toordinal() - _EPOCH_ORD
hours = days*24 + hour
minutes = hours*60 + minute
seconds = minutes*60 + second
......
......@@ -443,6 +443,10 @@ Extension modules
Library
-------
- calendar.py now depends on the new datetime module rather than
the time module. As a result, the range of allowable dates
has been increased.
- pdb has a new 'j(ump)' command to select the next line to be
executed.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment