Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Updated the _pydatetime.py lib
  • Loading branch information
terryluan12 authored and youknowone committed Dec 30, 2025
commit c0ee057571ba2d2e2bf1a9643b8ef27c8003703c
62 changes: 29 additions & 33 deletions Lib/_pydatetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,8 @@ def _parse_hh_mm_ss_ff(tstr):
raise ValueError("Invalid microsecond component")
else:
pos += 1
if not all(map(_is_ascii_digit, tstr[pos:])):
raise ValueError("Non-digit values in fraction")

len_remainder = len_str - pos

Expand All @@ -413,9 +415,6 @@ def _parse_hh_mm_ss_ff(tstr):
time_comps[3] = int(tstr[pos:(pos+to_parse)])
if to_parse < 6:
time_comps[3] *= _FRACTION_CORRECTION[to_parse-1]
if (len_remainder > to_parse
and not all(map(_is_ascii_digit, tstr[(pos+to_parse):]))):
raise ValueError("Non-digit values in unparsed fraction")

return time_comps

Expand Down Expand Up @@ -556,10 +555,6 @@ def _check_tzinfo_arg(tz):
if tz is not None and not isinstance(tz, tzinfo):
raise TypeError("tzinfo argument must be None or of a tzinfo subclass")

def _cmperror(x, y):
raise TypeError("can't compare '%s' to '%s'" % (
type(x).__name__, type(y).__name__))

def _divide_and_round(a, b):
"""divide a by b and round result to the nearest integer

Expand Down Expand Up @@ -970,6 +965,8 @@ def __new__(cls, year, month=None, day=None):
@classmethod
def fromtimestamp(cls, t):
"Construct a date from a POSIX timestamp (like time.time())."
if t is None:
raise TypeError("'NoneType' object cannot be interpreted as an integer")
y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
return cls(y, m, d)

Expand Down Expand Up @@ -1059,8 +1056,8 @@ def isoformat(self):
This is 'YYYY-MM-DD'.

References:
- http://www.w3.org/TR/NOTE-datetime
- http://www.cl.cam.ac.uk/~mgk25/iso-time.html
- https://www.w3.org/TR/NOTE-datetime
- https://www.cl.cam.ac.uk/~mgk25/iso-time.html
"""
return "%04d-%02d-%02d" % (self._year, self._month, self._day)

Expand Down Expand Up @@ -1108,35 +1105,38 @@ def replace(self, year=None, month=None, day=None):
day = self._day
return type(self)(year, month, day)

__replace__ = replace

# Comparisons of date objects with other.

def __eq__(self, other):
if isinstance(other, date):
if isinstance(other, date) and not isinstance(other, datetime):
return self._cmp(other) == 0
return NotImplemented

def __le__(self, other):
if isinstance(other, date):
if isinstance(other, date) and not isinstance(other, datetime):
return self._cmp(other) <= 0
return NotImplemented

def __lt__(self, other):
if isinstance(other, date):
if isinstance(other, date) and not isinstance(other, datetime):
return self._cmp(other) < 0
return NotImplemented

def __ge__(self, other):
if isinstance(other, date):
if isinstance(other, date) and not isinstance(other, datetime):
return self._cmp(other) >= 0
return NotImplemented

def __gt__(self, other):
if isinstance(other, date):
if isinstance(other, date) and not isinstance(other, datetime):
return self._cmp(other) > 0
return NotImplemented

def _cmp(self, other):
assert isinstance(other, date)
assert not isinstance(other, datetime)
y, m, d = self._year, self._month, self._day
y2, m2, d2 = other._year, other._month, other._day
return _cmp((y, m, d), (y2, m2, d2))
Expand Down Expand Up @@ -1191,7 +1191,7 @@ def isocalendar(self):
The first week is 1; Monday is 1 ... Sunday is 7.

ISO calendar algorithm taken from
http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
https://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
(used with permission)
"""
year = self._year
Expand Down Expand Up @@ -1633,6 +1633,8 @@ def replace(self, hour=None, minute=None, second=None, microsecond=None,
fold = self._fold
return type(self)(hour, minute, second, microsecond, tzinfo, fold=fold)

__replace__ = replace

# Pickle support.

def _getstate(self, protocol=3):
Expand Down Expand Up @@ -1680,7 +1682,7 @@ class datetime(date):
The year, month and day arguments are required. tzinfo may be None, or an
instance of a tzinfo subclass. The remaining arguments may be ints.
"""
__slots__ = date.__slots__ + time.__slots__
__slots__ = time.__slots__

def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
microsecond=0, tzinfo=None, *, fold=0):
Expand Down Expand Up @@ -1979,6 +1981,8 @@ def replace(self, year=None, month=None, day=None, hour=None,
return type(self)(year, month, day, hour, minute, second,
microsecond, tzinfo, fold=fold)

__replace__ = replace

def _local_timezone(self):
if self.tzinfo is None:
ts = self._mktime()
Expand Down Expand Up @@ -2040,7 +2044,7 @@ def isoformat(self, sep='T', timespec='auto'):
By default, the fractional part is omitted if self.microsecond == 0.

If self.tzinfo is not None, the UTC offset is also attached, giving
giving a full format of 'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM'.
a full format of 'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM'.

Optional argument sep specifies the separator between date and
time, default 'T'.
Expand Down Expand Up @@ -2131,42 +2135,32 @@ def dst(self):
def __eq__(self, other):
if isinstance(other, datetime):
return self._cmp(other, allow_mixed=True) == 0
elif not isinstance(other, date):
return NotImplemented
else:
return False
return NotImplemented

def __le__(self, other):
if isinstance(other, datetime):
return self._cmp(other) <= 0
elif not isinstance(other, date):
return NotImplemented
else:
_cmperror(self, other)
return NotImplemented

def __lt__(self, other):
if isinstance(other, datetime):
return self._cmp(other) < 0
elif not isinstance(other, date):
return NotImplemented
else:
_cmperror(self, other)
return NotImplemented

def __ge__(self, other):
if isinstance(other, datetime):
return self._cmp(other) >= 0
elif not isinstance(other, date):
return NotImplemented
else:
_cmperror(self, other)
return NotImplemented

def __gt__(self, other):
if isinstance(other, datetime):
return self._cmp(other) > 0
elif not isinstance(other, date):
return NotImplemented
else:
_cmperror(self, other)
return NotImplemented

def _cmp(self, other, allow_mixed=False):
assert isinstance(other, datetime)
Expand Down Expand Up @@ -2311,7 +2305,6 @@ def __reduce__(self):

def _isoweek1monday(year):
# Helper to calculate the day number of the Monday starting week 1
# XXX This could be done more efficiently
THURSDAY = 3
firstday = _ymd2ord(year, 1, 1)
firstweekday = (firstday + 6) % 7 # See weekday() above
Expand Down Expand Up @@ -2341,6 +2334,9 @@ def __new__(cls, offset, name=_Omitted):
"timedelta(hours=24).")
return cls._create(offset, name)

def __init_subclass__(cls):
raise TypeError("type 'datetime.timezone' is not an acceptable base type")

@classmethod
def _create(cls, offset, name=None):
self = tzinfo.__new__(cls)
Expand Down