Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ExeBy/smexe_ro.../usr/lib64/python3....
File: datetime.py
"""Concrete date/time and related types.
[0] Fix | Delete
[1] Fix | Delete
See http://www.iana.org/time-zones/repository/tz-link.html for
[2] Fix | Delete
time zone and DST data sources.
[3] Fix | Delete
"""
[4] Fix | Delete
[5] Fix | Delete
import time as _time
[6] Fix | Delete
import math as _math
[7] Fix | Delete
import sys
[8] Fix | Delete
[9] Fix | Delete
def _cmp(x, y):
[10] Fix | Delete
return 0 if x == y else 1 if x > y else -1
[11] Fix | Delete
[12] Fix | Delete
MINYEAR = 1
[13] Fix | Delete
MAXYEAR = 9999
[14] Fix | Delete
_MAXORDINAL = 3652059 # date.max.toordinal()
[15] Fix | Delete
[16] Fix | Delete
# Utility functions, adapted from Python's Demo/classes/Dates.py, which
[17] Fix | Delete
# also assumes the current Gregorian calendar indefinitely extended in
[18] Fix | Delete
# both directions. Difference: Dates.py calls January 1 of year 0 day
[19] Fix | Delete
# number 1. The code here calls January 1 of year 1 day number 1. This is
[20] Fix | Delete
# to match the definition of the "proleptic Gregorian" calendar in Dershowitz
[21] Fix | Delete
# and Reingold's "Calendrical Calculations", where it's the base calendar
[22] Fix | Delete
# for all computations. See the book for algorithms for converting between
[23] Fix | Delete
# proleptic Gregorian ordinals and many other calendar systems.
[24] Fix | Delete
[25] Fix | Delete
# -1 is a placeholder for indexing purposes.
[26] Fix | Delete
_DAYS_IN_MONTH = [-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
[27] Fix | Delete
[28] Fix | Delete
_DAYS_BEFORE_MONTH = [-1] # -1 is a placeholder for indexing purposes.
[29] Fix | Delete
dbm = 0
[30] Fix | Delete
for dim in _DAYS_IN_MONTH[1:]:
[31] Fix | Delete
_DAYS_BEFORE_MONTH.append(dbm)
[32] Fix | Delete
dbm += dim
[33] Fix | Delete
del dbm, dim
[34] Fix | Delete
[35] Fix | Delete
def _is_leap(year):
[36] Fix | Delete
"year -> 1 if leap year, else 0."
[37] Fix | Delete
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
[38] Fix | Delete
[39] Fix | Delete
def _days_before_year(year):
[40] Fix | Delete
"year -> number of days before January 1st of year."
[41] Fix | Delete
y = year - 1
[42] Fix | Delete
return y*365 + y//4 - y//100 + y//400
[43] Fix | Delete
[44] Fix | Delete
def _days_in_month(year, month):
[45] Fix | Delete
"year, month -> number of days in that month in that year."
[46] Fix | Delete
assert 1 <= month <= 12, month
[47] Fix | Delete
if month == 2 and _is_leap(year):
[48] Fix | Delete
return 29
[49] Fix | Delete
return _DAYS_IN_MONTH[month]
[50] Fix | Delete
[51] Fix | Delete
def _days_before_month(year, month):
[52] Fix | Delete
"year, month -> number of days in year preceding first day of month."
[53] Fix | Delete
assert 1 <= month <= 12, 'month must be in 1..12'
[54] Fix | Delete
return _DAYS_BEFORE_MONTH[month] + (month > 2 and _is_leap(year))
[55] Fix | Delete
[56] Fix | Delete
def _ymd2ord(year, month, day):
[57] Fix | Delete
"year, month, day -> ordinal, considering 01-Jan-0001 as day 1."
[58] Fix | Delete
assert 1 <= month <= 12, 'month must be in 1..12'
[59] Fix | Delete
dim = _days_in_month(year, month)
[60] Fix | Delete
assert 1 <= day <= dim, ('day must be in 1..%d' % dim)
[61] Fix | Delete
return (_days_before_year(year) +
[62] Fix | Delete
_days_before_month(year, month) +
[63] Fix | Delete
day)
[64] Fix | Delete
[65] Fix | Delete
_DI400Y = _days_before_year(401) # number of days in 400 years
[66] Fix | Delete
_DI100Y = _days_before_year(101) # " " " " 100 "
[67] Fix | Delete
_DI4Y = _days_before_year(5) # " " " " 4 "
[68] Fix | Delete
[69] Fix | Delete
# A 4-year cycle has an extra leap day over what we'd get from pasting
[70] Fix | Delete
# together 4 single years.
[71] Fix | Delete
assert _DI4Y == 4 * 365 + 1
[72] Fix | Delete
[73] Fix | Delete
# Similarly, a 400-year cycle has an extra leap day over what we'd get from
[74] Fix | Delete
# pasting together 4 100-year cycles.
[75] Fix | Delete
assert _DI400Y == 4 * _DI100Y + 1
[76] Fix | Delete
[77] Fix | Delete
# OTOH, a 100-year cycle has one fewer leap day than we'd get from
[78] Fix | Delete
# pasting together 25 4-year cycles.
[79] Fix | Delete
assert _DI100Y == 25 * _DI4Y - 1
[80] Fix | Delete
[81] Fix | Delete
def _ord2ymd(n):
[82] Fix | Delete
"ordinal -> (year, month, day), considering 01-Jan-0001 as day 1."
[83] Fix | Delete
[84] Fix | Delete
# n is a 1-based index, starting at 1-Jan-1. The pattern of leap years
[85] Fix | Delete
# repeats exactly every 400 years. The basic strategy is to find the
[86] Fix | Delete
# closest 400-year boundary at or before n, then work with the offset
[87] Fix | Delete
# from that boundary to n. Life is much clearer if we subtract 1 from
[88] Fix | Delete
# n first -- then the values of n at 400-year boundaries are exactly
[89] Fix | Delete
# those divisible by _DI400Y:
[90] Fix | Delete
#
[91] Fix | Delete
# D M Y n n-1
[92] Fix | Delete
# -- --- ---- ---------- ----------------
[93] Fix | Delete
# 31 Dec -400 -_DI400Y -_DI400Y -1
[94] Fix | Delete
# 1 Jan -399 -_DI400Y +1 -_DI400Y 400-year boundary
[95] Fix | Delete
# ...
[96] Fix | Delete
# 30 Dec 000 -1 -2
[97] Fix | Delete
# 31 Dec 000 0 -1
[98] Fix | Delete
# 1 Jan 001 1 0 400-year boundary
[99] Fix | Delete
# 2 Jan 001 2 1
[100] Fix | Delete
# 3 Jan 001 3 2
[101] Fix | Delete
# ...
[102] Fix | Delete
# 31 Dec 400 _DI400Y _DI400Y -1
[103] Fix | Delete
# 1 Jan 401 _DI400Y +1 _DI400Y 400-year boundary
[104] Fix | Delete
n -= 1
[105] Fix | Delete
n400, n = divmod(n, _DI400Y)
[106] Fix | Delete
year = n400 * 400 + 1 # ..., -399, 1, 401, ...
[107] Fix | Delete
[108] Fix | Delete
# Now n is the (non-negative) offset, in days, from January 1 of year, to
[109] Fix | Delete
# the desired date. Now compute how many 100-year cycles precede n.
[110] Fix | Delete
# Note that it's possible for n100 to equal 4! In that case 4 full
[111] Fix | Delete
# 100-year cycles precede the desired day, which implies the desired
[112] Fix | Delete
# day is December 31 at the end of a 400-year cycle.
[113] Fix | Delete
n100, n = divmod(n, _DI100Y)
[114] Fix | Delete
[115] Fix | Delete
# Now compute how many 4-year cycles precede it.
[116] Fix | Delete
n4, n = divmod(n, _DI4Y)
[117] Fix | Delete
[118] Fix | Delete
# And now how many single years. Again n1 can be 4, and again meaning
[119] Fix | Delete
# that the desired day is December 31 at the end of the 4-year cycle.
[120] Fix | Delete
n1, n = divmod(n, 365)
[121] Fix | Delete
[122] Fix | Delete
year += n100 * 100 + n4 * 4 + n1
[123] Fix | Delete
if n1 == 4 or n100 == 4:
[124] Fix | Delete
assert n == 0
[125] Fix | Delete
return year-1, 12, 31
[126] Fix | Delete
[127] Fix | Delete
# Now the year is correct, and n is the offset from January 1. We find
[128] Fix | Delete
# the month via an estimate that's either exact or one too large.
[129] Fix | Delete
leapyear = n1 == 3 and (n4 != 24 or n100 == 3)
[130] Fix | Delete
assert leapyear == _is_leap(year)
[131] Fix | Delete
month = (n + 50) >> 5
[132] Fix | Delete
preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear)
[133] Fix | Delete
if preceding > n: # estimate is too large
[134] Fix | Delete
month -= 1
[135] Fix | Delete
preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear)
[136] Fix | Delete
n -= preceding
[137] Fix | Delete
assert 0 <= n < _days_in_month(year, month)
[138] Fix | Delete
[139] Fix | Delete
# Now the year and month are correct, and n is the offset from the
[140] Fix | Delete
# start of that month: we're done!
[141] Fix | Delete
return year, month, n+1
[142] Fix | Delete
[143] Fix | Delete
# Month and day names. For localized versions, see the calendar module.
[144] Fix | Delete
_MONTHNAMES = [None, "Jan", "Feb", "Mar", "Apr", "May", "Jun",
[145] Fix | Delete
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
[146] Fix | Delete
_DAYNAMES = [None, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
[147] Fix | Delete
[148] Fix | Delete
[149] Fix | Delete
def _build_struct_time(y, m, d, hh, mm, ss, dstflag):
[150] Fix | Delete
wday = (_ymd2ord(y, m, d) + 6) % 7
[151] Fix | Delete
dnum = _days_before_month(y, m) + d
[152] Fix | Delete
return _time.struct_time((y, m, d, hh, mm, ss, wday, dnum, dstflag))
[153] Fix | Delete
[154] Fix | Delete
def _format_time(hh, mm, ss, us, timespec='auto'):
[155] Fix | Delete
specs = {
[156] Fix | Delete
'hours': '{:02d}',
[157] Fix | Delete
'minutes': '{:02d}:{:02d}',
[158] Fix | Delete
'seconds': '{:02d}:{:02d}:{:02d}',
[159] Fix | Delete
'milliseconds': '{:02d}:{:02d}:{:02d}.{:03d}',
[160] Fix | Delete
'microseconds': '{:02d}:{:02d}:{:02d}.{:06d}'
[161] Fix | Delete
}
[162] Fix | Delete
[163] Fix | Delete
if timespec == 'auto':
[164] Fix | Delete
# Skip trailing microseconds when us==0.
[165] Fix | Delete
timespec = 'microseconds' if us else 'seconds'
[166] Fix | Delete
elif timespec == 'milliseconds':
[167] Fix | Delete
us //= 1000
[168] Fix | Delete
try:
[169] Fix | Delete
fmt = specs[timespec]
[170] Fix | Delete
except KeyError:
[171] Fix | Delete
raise ValueError('Unknown timespec value')
[172] Fix | Delete
else:
[173] Fix | Delete
return fmt.format(hh, mm, ss, us)
[174] Fix | Delete
[175] Fix | Delete
def _format_offset(off):
[176] Fix | Delete
s = ''
[177] Fix | Delete
if off is not None:
[178] Fix | Delete
if off.days < 0:
[179] Fix | Delete
sign = "-"
[180] Fix | Delete
off = -off
[181] Fix | Delete
else:
[182] Fix | Delete
sign = "+"
[183] Fix | Delete
hh, mm = divmod(off, timedelta(hours=1))
[184] Fix | Delete
mm, ss = divmod(mm, timedelta(minutes=1))
[185] Fix | Delete
s += "%s%02d:%02d" % (sign, hh, mm)
[186] Fix | Delete
if ss or ss.microseconds:
[187] Fix | Delete
s += ":%02d" % ss.seconds
[188] Fix | Delete
[189] Fix | Delete
if ss.microseconds:
[190] Fix | Delete
s += '.%06d' % ss.microseconds
[191] Fix | Delete
return s
[192] Fix | Delete
[193] Fix | Delete
# Correctly substitute for %z and %Z escapes in strftime formats.
[194] Fix | Delete
def _wrap_strftime(object, format, timetuple):
[195] Fix | Delete
# Don't call utcoffset() or tzname() unless actually needed.
[196] Fix | Delete
freplace = None # the string to use for %f
[197] Fix | Delete
zreplace = None # the string to use for %z
[198] Fix | Delete
Zreplace = None # the string to use for %Z
[199] Fix | Delete
[200] Fix | Delete
# Scan format for %z and %Z escapes, replacing as needed.
[201] Fix | Delete
newformat = []
[202] Fix | Delete
push = newformat.append
[203] Fix | Delete
i, n = 0, len(format)
[204] Fix | Delete
while i < n:
[205] Fix | Delete
ch = format[i]
[206] Fix | Delete
i += 1
[207] Fix | Delete
if ch == '%':
[208] Fix | Delete
if i < n:
[209] Fix | Delete
ch = format[i]
[210] Fix | Delete
i += 1
[211] Fix | Delete
if ch == 'f':
[212] Fix | Delete
if freplace is None:
[213] Fix | Delete
freplace = '%06d' % getattr(object,
[214] Fix | Delete
'microsecond', 0)
[215] Fix | Delete
newformat.append(freplace)
[216] Fix | Delete
elif ch == 'z':
[217] Fix | Delete
if zreplace is None:
[218] Fix | Delete
zreplace = ""
[219] Fix | Delete
if hasattr(object, "utcoffset"):
[220] Fix | Delete
offset = object.utcoffset()
[221] Fix | Delete
if offset is not None:
[222] Fix | Delete
sign = '+'
[223] Fix | Delete
if offset.days < 0:
[224] Fix | Delete
offset = -offset
[225] Fix | Delete
sign = '-'
[226] Fix | Delete
h, rest = divmod(offset, timedelta(hours=1))
[227] Fix | Delete
m, rest = divmod(rest, timedelta(minutes=1))
[228] Fix | Delete
s = rest.seconds
[229] Fix | Delete
u = offset.microseconds
[230] Fix | Delete
if u:
[231] Fix | Delete
zreplace = '%c%02d%02d%02d.%06d' % (sign, h, m, s, u)
[232] Fix | Delete
elif s:
[233] Fix | Delete
zreplace = '%c%02d%02d%02d' % (sign, h, m, s)
[234] Fix | Delete
else:
[235] Fix | Delete
zreplace = '%c%02d%02d' % (sign, h, m)
[236] Fix | Delete
assert '%' not in zreplace
[237] Fix | Delete
newformat.append(zreplace)
[238] Fix | Delete
elif ch == 'Z':
[239] Fix | Delete
if Zreplace is None:
[240] Fix | Delete
Zreplace = ""
[241] Fix | Delete
if hasattr(object, "tzname"):
[242] Fix | Delete
s = object.tzname()
[243] Fix | Delete
if s is not None:
[244] Fix | Delete
# strftime is going to have at this: escape %
[245] Fix | Delete
Zreplace = s.replace('%', '%%')
[246] Fix | Delete
newformat.append(Zreplace)
[247] Fix | Delete
else:
[248] Fix | Delete
push('%')
[249] Fix | Delete
push(ch)
[250] Fix | Delete
else:
[251] Fix | Delete
push('%')
[252] Fix | Delete
else:
[253] Fix | Delete
push(ch)
[254] Fix | Delete
newformat = "".join(newformat)
[255] Fix | Delete
return _time.strftime(newformat, timetuple)
[256] Fix | Delete
[257] Fix | Delete
# Helpers for parsing the result of isoformat()
[258] Fix | Delete
def _parse_isoformat_date(dtstr):
[259] Fix | Delete
# It is assumed that this function will only be called with a
[260] Fix | Delete
# string of length exactly 10, and (though this is not used) ASCII-only
[261] Fix | Delete
year = int(dtstr[0:4])
[262] Fix | Delete
if dtstr[4] != '-':
[263] Fix | Delete
raise ValueError('Invalid date separator: %s' % dtstr[4])
[264] Fix | Delete
[265] Fix | Delete
month = int(dtstr[5:7])
[266] Fix | Delete
[267] Fix | Delete
if dtstr[7] != '-':
[268] Fix | Delete
raise ValueError('Invalid date separator')
[269] Fix | Delete
[270] Fix | Delete
day = int(dtstr[8:10])
[271] Fix | Delete
[272] Fix | Delete
return [year, month, day]
[273] Fix | Delete
[274] Fix | Delete
def _parse_hh_mm_ss_ff(tstr):
[275] Fix | Delete
# Parses things of the form HH[:MM[:SS[.fff[fff]]]]
[276] Fix | Delete
len_str = len(tstr)
[277] Fix | Delete
[278] Fix | Delete
time_comps = [0, 0, 0, 0]
[279] Fix | Delete
pos = 0
[280] Fix | Delete
for comp in range(0, 3):
[281] Fix | Delete
if (len_str - pos) < 2:
[282] Fix | Delete
raise ValueError('Incomplete time component')
[283] Fix | Delete
[284] Fix | Delete
time_comps[comp] = int(tstr[pos:pos+2])
[285] Fix | Delete
[286] Fix | Delete
pos += 2
[287] Fix | Delete
next_char = tstr[pos:pos+1]
[288] Fix | Delete
[289] Fix | Delete
if not next_char or comp >= 2:
[290] Fix | Delete
break
[291] Fix | Delete
[292] Fix | Delete
if next_char != ':':
[293] Fix | Delete
raise ValueError('Invalid time separator: %c' % next_char)
[294] Fix | Delete
[295] Fix | Delete
pos += 1
[296] Fix | Delete
[297] Fix | Delete
if pos < len_str:
[298] Fix | Delete
if tstr[pos] != '.':
[299] Fix | Delete
raise ValueError('Invalid microsecond component')
[300] Fix | Delete
else:
[301] Fix | Delete
pos += 1
[302] Fix | Delete
[303] Fix | Delete
len_remainder = len_str - pos
[304] Fix | Delete
if len_remainder not in (3, 6):
[305] Fix | Delete
raise ValueError('Invalid microsecond component')
[306] Fix | Delete
[307] Fix | Delete
time_comps[3] = int(tstr[pos:])
[308] Fix | Delete
if len_remainder == 3:
[309] Fix | Delete
time_comps[3] *= 1000
[310] Fix | Delete
[311] Fix | Delete
return time_comps
[312] Fix | Delete
[313] Fix | Delete
def _parse_isoformat_time(tstr):
[314] Fix | Delete
# Format supported is HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]
[315] Fix | Delete
len_str = len(tstr)
[316] Fix | Delete
if len_str < 2:
[317] Fix | Delete
raise ValueError('Isoformat time too short')
[318] Fix | Delete
[319] Fix | Delete
# This is equivalent to re.search('[+-]', tstr), but faster
[320] Fix | Delete
tz_pos = (tstr.find('-') + 1 or tstr.find('+') + 1)
[321] Fix | Delete
timestr = tstr[:tz_pos-1] if tz_pos > 0 else tstr
[322] Fix | Delete
[323] Fix | Delete
time_comps = _parse_hh_mm_ss_ff(timestr)
[324] Fix | Delete
[325] Fix | Delete
tzi = None
[326] Fix | Delete
if tz_pos > 0:
[327] Fix | Delete
tzstr = tstr[tz_pos:]
[328] Fix | Delete
[329] Fix | Delete
# Valid time zone strings are:
[330] Fix | Delete
# HH:MM len: 5
[331] Fix | Delete
# HH:MM:SS len: 8
[332] Fix | Delete
# HH:MM:SS.ffffff len: 15
[333] Fix | Delete
[334] Fix | Delete
if len(tzstr) not in (5, 8, 15):
[335] Fix | Delete
raise ValueError('Malformed time zone string')
[336] Fix | Delete
[337] Fix | Delete
tz_comps = _parse_hh_mm_ss_ff(tzstr)
[338] Fix | Delete
if all(x == 0 for x in tz_comps):
[339] Fix | Delete
tzi = timezone.utc
[340] Fix | Delete
else:
[341] Fix | Delete
tzsign = -1 if tstr[tz_pos - 1] == '-' else 1
[342] Fix | Delete
[343] Fix | Delete
td = timedelta(hours=tz_comps[0], minutes=tz_comps[1],
[344] Fix | Delete
seconds=tz_comps[2], microseconds=tz_comps[3])
[345] Fix | Delete
[346] Fix | Delete
tzi = timezone(tzsign * td)
[347] Fix | Delete
[348] Fix | Delete
time_comps.append(tzi)
[349] Fix | Delete
[350] Fix | Delete
return time_comps
[351] Fix | Delete
[352] Fix | Delete
[353] Fix | Delete
# Just raise TypeError if the arg isn't None or a string.
[354] Fix | Delete
def _check_tzname(name):
[355] Fix | Delete
if name is not None and not isinstance(name, str):
[356] Fix | Delete
raise TypeError("tzinfo.tzname() must return None or string, "
[357] Fix | Delete
"not '%s'" % type(name))
[358] Fix | Delete
[359] Fix | Delete
# name is the offset-producing method, "utcoffset" or "dst".
[360] Fix | Delete
# offset is what it returned.
[361] Fix | Delete
# If offset isn't None or timedelta, raises TypeError.
[362] Fix | Delete
# If offset is None, returns None.
[363] Fix | Delete
# Else offset is checked for being in range.
[364] Fix | Delete
# If it is, its integer value is returned. Else ValueError is raised.
[365] Fix | Delete
def _check_utc_offset(name, offset):
[366] Fix | Delete
assert name in ("utcoffset", "dst")
[367] Fix | Delete
if offset is None:
[368] Fix | Delete
return
[369] Fix | Delete
if not isinstance(offset, timedelta):
[370] Fix | Delete
raise TypeError("tzinfo.%s() must return None "
[371] Fix | Delete
"or timedelta, not '%s'" % (name, type(offset)))
[372] Fix | Delete
if not -timedelta(1) < offset < timedelta(1):
[373] Fix | Delete
raise ValueError("%s()=%s, must be strictly between "
[374] Fix | Delete
"-timedelta(hours=24) and timedelta(hours=24)" %
[375] Fix | Delete
(name, offset))
[376] Fix | Delete
[377] Fix | Delete
def _check_int_field(value):
[378] Fix | Delete
if isinstance(value, int):
[379] Fix | Delete
return value
[380] Fix | Delete
if isinstance(value, float):
[381] Fix | Delete
raise TypeError('integer argument expected, got float')
[382] Fix | Delete
try:
[383] Fix | Delete
value = value.__index__()
[384] Fix | Delete
except AttributeError:
[385] Fix | Delete
pass
[386] Fix | Delete
else:
[387] Fix | Delete
if not isinstance(value, int):
[388] Fix | Delete
raise TypeError('__index__ returned non-int (type %s)' %
[389] Fix | Delete
type(value).__name__)
[390] Fix | Delete
return value
[391] Fix | Delete
orig = value
[392] Fix | Delete
try:
[393] Fix | Delete
value = value.__int__()
[394] Fix | Delete
except AttributeError:
[395] Fix | Delete
pass
[396] Fix | Delete
else:
[397] Fix | Delete
if not isinstance(value, int):
[398] Fix | Delete
raise TypeError('__int__ returned non-int (type %s)' %
[399] Fix | Delete
type(value).__name__)
[400] Fix | Delete
import warnings
[401] Fix | Delete
warnings.warn("an integer is required (got type %s)" %
[402] Fix | Delete
type(orig).__name__,
[403] Fix | Delete
DeprecationWarning,
[404] Fix | Delete
stacklevel=2)
[405] Fix | Delete
return value
[406] Fix | Delete
raise TypeError('an integer is required (got type %s)' %
[407] Fix | Delete
type(value).__name__)
[408] Fix | Delete
[409] Fix | Delete
def _check_date_fields(year, month, day):
[410] Fix | Delete
year = _check_int_field(year)
[411] Fix | Delete
month = _check_int_field(month)
[412] Fix | Delete
day = _check_int_field(day)
[413] Fix | Delete
if not MINYEAR <= year <= MAXYEAR:
[414] Fix | Delete
raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
[415] Fix | Delete
if not 1 <= month <= 12:
[416] Fix | Delete
raise ValueError('month must be in 1..12', month)
[417] Fix | Delete
dim = _days_in_month(year, month)
[418] Fix | Delete
if not 1 <= day <= dim:
[419] Fix | Delete
raise ValueError('day must be in 1..%d' % dim, day)
[420] Fix | Delete
return year, month, day
[421] Fix | Delete
[422] Fix | Delete
def _check_time_fields(hour, minute, second, microsecond, fold):
[423] Fix | Delete
hour = _check_int_field(hour)
[424] Fix | Delete
minute = _check_int_field(minute)
[425] Fix | Delete
second = _check_int_field(second)
[426] Fix | Delete
microsecond = _check_int_field(microsecond)
[427] Fix | Delete
if not 0 <= hour <= 23:
[428] Fix | Delete
raise ValueError('hour must be in 0..23', hour)
[429] Fix | Delete
if not 0 <= minute <= 59:
[430] Fix | Delete
raise ValueError('minute must be in 0..59', minute)
[431] Fix | Delete
if not 0 <= second <= 59:
[432] Fix | Delete
raise ValueError('second must be in 0..59', second)
[433] Fix | Delete
if not 0 <= microsecond <= 999999:
[434] Fix | Delete
raise ValueError('microsecond must be in 0..999999', microsecond)
[435] Fix | Delete
if fold not in (0, 1):
[436] Fix | Delete
raise ValueError('fold must be either 0 or 1', fold)
[437] Fix | Delete
return hour, minute, second, microsecond, fold
[438] Fix | Delete
[439] Fix | Delete
def _check_tzinfo_arg(tz):
[440] Fix | Delete
if tz is not None and not isinstance(tz, tzinfo):
[441] Fix | Delete
raise TypeError("tzinfo argument must be None or of a tzinfo subclass")
[442] Fix | Delete
[443] Fix | Delete
def _cmperror(x, y):
[444] Fix | Delete
raise TypeError("can't compare '%s' to '%s'" % (
[445] Fix | Delete
type(x).__name__, type(y).__name__))
[446] Fix | Delete
[447] Fix | Delete
def _divide_and_round(a, b):
[448] Fix | Delete
"""divide a by b and round result to the nearest integer
[449] Fix | Delete
[450] Fix | Delete
When the ratio is exactly half-way between two integers,
[451] Fix | Delete
the even integer is returned.
[452] Fix | Delete
"""
[453] Fix | Delete
# Based on the reference implementation for divmod_near
[454] Fix | Delete
# in Objects/longobject.c.
[455] Fix | Delete
q, r = divmod(a, b)
[456] Fix | Delete
# round up if either r / b > 0.5, or r / b == 0.5 and q is odd.
[457] Fix | Delete
# The expression r / b > 0.5 is equivalent to 2 * r > b if b is
[458] Fix | Delete
# positive, 2 * r < b if b negative.
[459] Fix | Delete
r *= 2
[460] Fix | Delete
greater_than_half = r > b if b > 0 else r < b
[461] Fix | Delete
if greater_than_half or r == b and q % 2 == 1:
[462] Fix | Delete
q += 1
[463] Fix | Delete
[464] Fix | Delete
return q
[465] Fix | Delete
[466] Fix | Delete
[467] Fix | Delete
class timedelta:
[468] Fix | Delete
"""Represent the difference between two datetime objects.
[469] Fix | Delete
[470] Fix | Delete
Supported operators:
[471] Fix | Delete
[472] Fix | Delete
- add, subtract timedelta
[473] Fix | Delete
- unary plus, minus, abs
[474] Fix | Delete
- compare to timedelta
[475] Fix | Delete
- multiply, divide by int
[476] Fix | Delete
[477] Fix | Delete
In addition, datetime supports subtraction of two datetime objects
[478] Fix | Delete
returning a timedelta, and addition or subtraction of a datetime
[479] Fix | Delete
and a timedelta giving a datetime.
[480] Fix | Delete
[481] Fix | Delete
Representation: (days, seconds, microseconds). Why? Because I
[482] Fix | Delete
felt like it.
[483] Fix | Delete
"""
[484] Fix | Delete
__slots__ = '_days', '_seconds', '_microseconds', '_hashcode'
[485] Fix | Delete
[486] Fix | Delete
def __new__(cls, days=0, seconds=0, microseconds=0,
[487] Fix | Delete
milliseconds=0, minutes=0, hours=0, weeks=0):
[488] Fix | Delete
# Doing this efficiently and accurately in C is going to be difficult
[489] Fix | Delete
# and error-prone, due to ubiquitous overflow possibilities, and that
[490] Fix | Delete
# C double doesn't have enough bits of precision to represent
[491] Fix | Delete
# microseconds over 10K years faithfully. The code here tries to make
[492] Fix | Delete
# explicit where go-fast assumptions can be relied on, in order to
[493] Fix | Delete
# guide the C implementation; it's way more convoluted than speed-
[494] Fix | Delete
# ignoring auto-overflow-to-long idiomatic Python could be.
[495] Fix | Delete
[496] Fix | Delete
# XXX Check that all inputs are ints or floats.
[497] Fix | Delete
[498] Fix | Delete
# Final values, all integer.
[499] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function