import _testcapi
import fractions
# _PyTime_ROUND_FLOOR: Round towards minus infinity (-inf)
_PyTime_ROUND_FLOOR = 0
SEC_TO_NS = 10 ** 9
FULLINT = False
CHECK_OVERFLOW = False
def test(qpc, qpf):
text = "[qpc=%s, qpf=%s]" % (qpc, qpf)
bugs = []
if FULLINT:
frac = fractions.Fraction(SEC_TO_NS, qpf)
mul, div = frac.numerator, frac.denominator
t = qpc * mul
if CHECK_OVERFLOW:
if t > 2**63 - 1:
raise OverflowError("%s: t=%s, bits=%s" % (text, t, t.bit_length()))
t = t // div
d = _testcapi.PyTime_AsSecondsDouble(t)
t2 = _testcapi.PyTime_FromSecondsObject(d, _PyTime_ROUND_FLOOR)
text = ("%s t: %s -> %s -> %s (int diff=%s)"
% (text, t, d, t2, t2 - t))
if t2 != t:
# check if the conversion to double looses precision
bugs.append("t2 != t")
else:
d = qpc / qpf
t2 = _testcapi.PyTime_FromSecondsObject(d, _PyTime_ROUND_FLOOR)
d2 = _testcapi.PyTime_AsSecondsDouble(t2)
text = ("%s: %s -> %s -> %s (double diff=%s)"
% (text, d, t2, d2, d2 - d))
if d2 != d:
bugs.append("d2 != d")
if bugs:
print("BUGS %s! %s" % (bugs, text))
else:
print("Ok. %s" % text)
return bool(bugs)
day_in_sec = 3600 * 24
year_in_sec = day_in_sec * 366
loss = False
for qpf in (10 ** 7, 3579545):
for sec in (
1,
#day_in_sec,
#day_in_sec * 49,
#year_in_sec,
#year_in_sec * 25,
):
qpc = sec * qpf
loss |= test(qpc, qpf)
loss |= test(qpc - 1, qpf)
loss |= test(qpc + 1, qpf)
print()
if loss:
print("Lost precision :-(")
else:
print("Everything is fine!")