diff --git a/Lib/datetime.py b/Lib/datetime.py --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -7,6 +7,9 @@ import time as _time import math as _math +# Sentinel value to disallow None +_SENTINEL = object() + def _cmp(x, y): return 0 if x == y else 1 if x > y else -1 @@ -14,6 +17,8 @@ MAXYEAR = 9999 _MAXORDINAL = 3652059 # date.max.toordinal() +_MAX_DELTA_DAYS = 999999999 + # Utility functions, adapted from Python's Demo/classes/Dates.py, which # also assumes the current Gregorian calendar indefinitely extended in # both directions. Difference: Dates.py calls January 1 of year 0 day @@ -79,6 +84,15 @@ # pasting together 25 4-year cycles. assert _DI100Y == 25 * _DI4Y - 1 +_US_PER_US = 1 +_US_PER_MS = 1000 +_US_PER_SECOND = 1000000 +_US_PER_MINUTE = 60000000 +_SECONDS_PER_DAY = 24 * 3600 +_US_PER_HOUR = 3600000000 +_US_PER_DAY = 86400000000 +_US_PER_WEEK = 604800000000 + def _ord2ymd(n): "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1." @@ -146,6 +160,24 @@ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] _DAYNAMES = [None, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] +def _accum(tag, sofar, num, factor, leftover): + if isinstance(num, int): + prod = num * factor + result = sofar + prod + return result, leftover + if isinstance(num, float): + fracpart, intpart = _math.modf(num) + prod = int(intpart) * factor + result = sofar + prod + if fracpart == 0.0: + return result, leftover + assert isinstance(factor, int) + fracpart, intpart = _math.modf(factor * fracpart) + result += int(intpart) + return result, leftover + fracpart + raise TypeError("unsupported type for timedelta %s component: %s" % + (tag, type(num))) + def _build_struct_time(y, m, d, hh, mm, ss, dstflag): wday = (_ymd2ord(y, m, d) + 6) % 7 @@ -543,7 +575,7 @@ __rmul__ = __mul__ def _to_microseconds(self): - return ((self._days * (24*3600) + self._seconds) * 1000000 + + return ((self._days * _SECONDS_PER_DAY + self._seconds) * _US_PER_SECOND + self._microseconds) def __floordiv__(self, other): @@ -634,9 +666,8 @@ def __reduce__(self): return (self.__class__, self._getstate()) -timedelta.min = timedelta(-999999999) -timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59, - microseconds=999999) +timedelta.min = timedelta(-_MAX_DELTA_DAYS) +timedelta.max = timedelta(_MAX_DELTA_DAYS, 24*3600-1, 1000000-1) timedelta.resolution = timedelta(microseconds=1) class date: @@ -1816,11 +1847,10 @@ __slots__ = '_offset', '_name' # Sentinel value to disallow None - _Omitted = object() - def __new__(cls, offset, name=_Omitted): + def __new__(cls, offset, name=_SENTINEL): if not isinstance(offset, timedelta): raise TypeError("offset must be a timedelta") - if name is cls._Omitted: + if name is _SENTINEL: if not offset: return cls.utc name = None diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -64,7 +64,7 @@ self.assertEqual(names - allowed, set([])) def test_divide_and_round(self): - if '_Fast' in str(self): + if '_Fast' in type(self).__name__: return dar = datetime_module._divide_and_round