codon/test/stdlib/datetime_test.codon

1995 lines
74 KiB
Python
Raw Normal View History

from datetime import *
from unittest import TestCase
from operator import lt, le, gt, ge, eq, ne, truediv, floordiv, mod
2022-01-24 18:32:33 +08:00
Dynamic Polymorphism (#58) * Use Static[] for static inheritance * Support .seq extension * Fix #36 * Polymorphic typechecking; vtables [wip] * v-table dispatch [wip] * vtable routing [wip; bug] * vtable routing [MVP] * Fix texts * Add union type support * Update FAQs * Clarify * Add BSL license * Add makeUnion * Add IR UnionType * Update union representation in LLVM * Update README * Update README.md * Update README * Update README.md * Add benchmarks * Add more benchmarks and README * Add primes benchmark * Update benchmarks * Fix cpp * Clean up list * Update faq.md * Add binary trees benchmark * Add fannkuch benchmark * Fix paths * Add PyPy * Abort on fail * More benchmarks * Add cpp word_count * Update set_partition cpp * Add nbody cpp * Add TAQ cpp; fix word_count timing * Update CODEOWNERS * Update README * Update README.md * Update CODEOWNERS * Fix bench script * Update binary_trees.cpp * Update taq.cpp * Fix primes benchmark * Add mandelbrot benchmark * Fix OpenMP init * Add Module::unsafeGetUnionType * UnionType [wip] [skip ci] * Integrate IR unions and Union * UnionType refactor [skip ci] * Update README.md * Update docs * UnionType [wip] [skip ci] * UnionType and automatic unions * Add Slack * Update faq.md * Refactor types * New error reporting [wip] * New error reporting [wip] * peglib updates [wip] [skip_ci] * Fix parsing issues * Fix parsing issues * Fix error reporting issues * Make sure random module matches Python * Update releases.md * Fix tests * Fix #59 * Fix #57 * Fix #50 * Fix #49 * Fix #26; Fix #51; Fix #47; Fix #49 * Fix collection extension methods * Fix #62 * Handle *args/**kwargs with Callable[]; Fix #43 * Fix #43 * Fix Ptr.__sub__; Fix polymorphism issues * Add typeinfo * clang-format * Upgrade fmtlib to v9; Use CPM for fmtlib; format spec support; __format__ support * Use CPM for semver and toml++ * Remove extension check * Revamp str methods * Update str.zfill * Fix thunk crashes [wip] [skip_ci] * Fix str.__reversed__ * Fix count_with_max * Fix vtable memory allocation issues * Add poly AST tests * Use PDQsort when stability does not matter * Fix dotted imports; Fix issues * Fix kwargs passing to Python * Fix #61 * Fix #37 * Add isinstance support for unions; Union methods return Union type if different * clang-format * Nicely format error tracebacks * Fix build issues; clang-format * Fix OpenMP init * Fix OpenMP init * Update README.md * Fix tests * Update license [skip ci] * Update license [ci skip] * Add copyright header to all source files * Fix super(); Fix error recovery in ClassStmt * Clean up whitespace [ci skip] * Use Python 3.9 on CI * Print info in random test * Fix single unions * Update random_test.codon * Fix polymorhic thunk instantiation * Fix random test * Add operator.attrgetter and operator.methodcaller * Add code documentation * Update documentation * Update README.md * Fix tests * Fix random init Co-authored-by: A. R. Shajii <ars@ars.me>
2022-12-05 08:45:21 +08:00
class TestTimeDelta(Static[TestCase]):
def test_constructor(self):
eq = self.assertEqual
td = timedelta
# Check keyword args to constructor
2022-01-24 18:32:33 +08:00
eq(
td(),
td(
weeks=0,
days=0,
hours=0,
minutes=0,
seconds=0,
milliseconds=0,
microseconds=0,
),
)
eq(td(1), td(days=1))
eq(td(0, 1), td(seconds=1))
eq(td(0, 0, 1), td(microseconds=1))
eq(td(weeks=1), td(days=7))
eq(td(days=1), td(hours=24))
eq(td(hours=1), td(minutes=60))
eq(td(minutes=1), td(seconds=60))
eq(td(seconds=1), td(milliseconds=1000))
eq(td(milliseconds=1), td(microseconds=1000))
# Check float args to constructor
2022-01-24 18:32:33 +08:00
eq(td(weeks=1.0 / 7), td(days=1))
eq(td(days=1.0 / 24), td(hours=1))
eq(td(hours=1.0 / 60), td(minutes=1))
eq(td(minutes=1.0 / 60), td(seconds=1))
eq(td(seconds=0.001), td(milliseconds=1))
eq(td(milliseconds=0.001), td(microseconds=1))
def test_computations(self):
eq = self.assertEqual
td = timedelta
2022-01-24 18:32:33 +08:00
a = td(7) # One week
b = td(0, 60) # One minute
c = td(0, 0, 1000) # One millisecond
eq(a + b + c, td(7, 60, 1000))
eq(a - b, td(6, 24 * 3600 - 60))
# eq(b.__rsub__(a), td(6, 24*3600 - 60))
eq(-a, td(-7))
eq(+a, td(7))
2022-01-24 18:32:33 +08:00
eq(-b, td(-1, 24 * 3600 - 60))
eq(-c, td(-1, 24 * 3600 - 1, 999000))
eq(abs(a), a)
eq(abs(-a), a)
2022-01-24 18:32:33 +08:00
eq(td(6, 24 * 3600), a)
eq(td(0, 0, 60 * 1000000), b)
eq(a * 10, td(70))
eq(a * 10, 10 * a)
eq(a * 10, 10 * a)
eq(b * 10, td(0, 600))
eq(10 * b, td(0, 600))
eq(b * 10, td(0, 600))
eq(c * 10, td(0, 0, 10000))
eq(10 * c, td(0, 0, 10000))
eq(c * 10, td(0, 0, 10000))
eq(a * -1, -a)
eq(b * -2, -b - b)
eq(c * -2, -c + -c)
eq(b * (60 * 24), (b * 60) * 24)
eq(b * (60 * 24), (60 * b) * 24)
eq(c * 1000, td(0, 1))
eq(1000 * c, td(0, 1))
eq(a // 7, td(1))
eq(b // 10, td(0, 6))
eq(c // 1000, td(0, 0, 1))
eq(a // 10, td(0, 7 * 24 * 360))
eq(a // 3600000, td(0, 0, 7 * 24 * 1000))
eq(a / 0.5, td(14))
eq(b / 0.5, td(0, 120))
eq(a / 7, td(1))
eq(b / 10, td(0, 6))
eq(c / 1000, td(0, 0, 1))
eq(a / 10, td(0, 7 * 24 * 360))
eq(a / 3600000, td(0, 0, 7 * 24 * 1000))
# Multiplication by float
us = td(microseconds=1)
2022-01-24 18:32:33 +08:00
eq((3 * us) * 0.5, 2 * us)
eq((5 * us) * 0.5, 2 * us)
eq(0.5 * (3 * us), 2 * us)
eq(0.5 * (5 * us), 2 * us)
eq((-3 * us) * 0.5, -2 * us)
eq((-5 * us) * 0.5, -2 * us)
# TODO: check Python's Issue #23521 and possibly
# incorporate the same fix here. For now a couple
# tests are disabled.
# Issue #23521
eq(td(seconds=1) * 0.123456, td(microseconds=123456))
# eq(td(seconds=1) * 0.6112295, td(microseconds=611229))
# Division by int and float
2022-01-24 18:32:33 +08:00
eq((3 * us) / 2, 2 * us)
eq((5 * us) / 2, 2 * us)
eq((-3 * us) / 2.0, -2 * us)
eq((-5 * us) / 2.0, -2 * us)
eq((3 * us) / -2, -2 * us)
eq((5 * us) / -2, -2 * us)
eq((3 * us) / -2.0, -2 * us)
eq((5 * us) / -2.0, -2 * us)
for i in range(-10, 10):
2022-01-24 18:32:33 +08:00
eq((i * us / 3) // us, round(i / 3))
for i in range(-10, 10):
2022-01-24 18:32:33 +08:00
eq((i * us / -3) // us, round(i / -3))
# Issue #23521
# eq(td(seconds=1) / (1 / 0.6112295), td(microseconds=611229))
# Issue #11576
2022-01-24 18:32:33 +08:00
eq(td(999999999, 86399, 999999) - td(999999999, 86399, 999998), td(0, 0, 1))
eq(td(999999999, 1, 1) - td(999999999, 1, 0), td(0, 0, 1))
2022-01-24 18:32:33 +08:00
"""
def test_disallowed_special(self):
a = timedelta(42)
NAN = 0. / 0.
self.assertRaises(ValueError, a.__mul__, NAN)
self.assertRaises(ValueError, a.__truediv__, NAN)
2022-01-24 18:32:33 +08:00
"""
def test_basic_attributes(self):
days, seconds, us = 1, 7, 31
td = timedelta(days, seconds, us)
self.assertEqual(td.days, days)
self.assertEqual(td.seconds, seconds)
self.assertEqual(td.microseconds, us)
def test_total_seconds(self):
td = timedelta(days=365)
self.assertEqual(td.total_seconds(), 31536000.0)
for total_seconds in [123456.789012, -123456.789012, 0.123456, 0, 1e6]:
td = timedelta(seconds=total_seconds)
self.assertEqual(td.total_seconds(), total_seconds)
# Issue8644: Test that td.total_seconds() has the same
# accuracy as td / timedelta(seconds=1).
for ms in [-1, -2, -123]:
td = timedelta(microseconds=ms)
self.assertEqual(td.total_seconds(), td / timedelta(seconds=1))
def test_carries(self):
2022-01-24 18:32:33 +08:00
t1 = timedelta(
days=100,
weeks=-7,
hours=-24 * (100 - 49),
minutes=-3,
seconds=12,
microseconds=(3 * 60 - 12) * 1e6 + 1,
)
t2 = timedelta(microseconds=1)
self.assertEqual(t1, t2)
def test_hash_equality(self):
2022-01-24 18:32:33 +08:00
t1 = timedelta(
days=100,
weeks=-7,
hours=-24 * (100 - 49),
minutes=-3,
seconds=12,
microseconds=(3 * 60 - 12) * 1000000,
)
t2 = timedelta()
self.assertEqual(hash(t1), hash(t2))
t1 += timedelta(weeks=7)
2022-01-24 18:32:33 +08:00
t2 += timedelta(days=7 * 7)
self.assertEqual(t1, t2)
self.assertEqual(hash(t1), hash(t2))
d = {t1: 1}
d[t2] = 2
self.assertEqual(len(d), 1)
self.assertEqual(d[t1], 2)
def test_compare(self):
t1 = timedelta(2, 3, 4)
t2 = timedelta(2, 3, 4)
self.assertEqual(t1, t2)
self.assertTrue(t1 <= t2)
self.assertTrue(t1 >= t2)
self.assertFalse(t1 != t2)
self.assertFalse(t1 < t2)
self.assertFalse(t1 > t2)
for args in (3, 3, 3), (2, 4, 4), (2, 3, 5):
2022-01-24 18:32:33 +08:00
t2 = timedelta(*args) # this is larger than t1
self.assertTrue(t1 < t2)
self.assertTrue(t2 > t1)
self.assertTrue(t1 <= t2)
self.assertTrue(t2 >= t1)
self.assertTrue(t1 != t2)
self.assertTrue(t2 != t1)
self.assertFalse(t1 == t2)
self.assertFalse(t2 == t1)
self.assertFalse(t1 > t2)
self.assertFalse(t2 < t1)
self.assertFalse(t1 >= t2)
self.assertFalse(t2 <= t1)
def test_str(self):
td = timedelta
eq = self.assertEqual
eq(str(td(1)), "1 day, 0:00:00")
eq(str(td(-1)), "-1 day, 0:00:00")
eq(str(td(2)), "2 days, 0:00:00")
eq(str(td(-2)), "-2 days, 0:00:00")
eq(str(td(hours=12, minutes=58, seconds=59)), "12:58:59")
eq(str(td(hours=2, minutes=3, seconds=4)), "2:03:04")
2022-01-24 18:32:33 +08:00
eq(str(td(weeks=-30, hours=23, minutes=12, seconds=34)), "-210 days, 23:12:34")
eq(str(td(milliseconds=1)), "0:00:00.001000")
eq(str(td(microseconds=3)), "0:00:00.000003")
# Codon's timedelta has a smaller range than Python's
# since it uses a pure microseconds representation, so
# below case is not supported.
2022-01-24 18:32:33 +08:00
"""
eq(str(td(days=999999999, hours=23, minutes=59, seconds=59,
microseconds=999999)),
"999999999 days, 23:59:59.999999")
2022-01-24 18:32:33 +08:00
"""
def test_repr(self):
td = timedelta
2022-01-24 18:32:33 +08:00
self.assertEqual(repr(td(1)), "timedelta(days=1)")
self.assertEqual(repr(td(10, 2)), "timedelta(days=10, seconds=2)")
self.assertEqual(
repr(td(-10, 2, 400000)),
"timedelta(days=-10, seconds=2, microseconds=400000)",
)
self.assertEqual(repr(td(seconds=60)), "timedelta(seconds=60)")
self.assertEqual(repr(td()), "timedelta(0)")
self.assertEqual(repr(td(microseconds=100)), "timedelta(microseconds=100)")
self.assertEqual(
repr(td(days=1, microseconds=100)), "timedelta(days=1, microseconds=100)"
)
self.assertEqual(
repr(td(seconds=1, microseconds=100)),
"timedelta(seconds=1, microseconds=100)",
)
def test_resolution_info(self):
self.assertTrue(timedelta.max > timedelta.min)
Typechecker refactoring (#20) * Initial refactor commit * Support external vars * Simplify refactor; Python scoping [wip] * Python scoping [wip] * Python scoping [fix loops; wip] * Fix lambdas * Python scoping [test fixes; wip] * Fix scoping [wip] * Fix basic tests [no-ci] * Fix tests * CallExpr refactoring [wip] * CallExpr refactoring [wip] * Remove activeUnbounds tracking * Add core.codon * Move Function and other core types to core.codon; Revamp Function and Callable types * Refactor IntExpr, FloatExpr and CallExpr * Refactor ClassStmt * Refactor context, IdExpr and DotExpr * Refactor DotExpr and AssignStmt * Refactor ImportStmt * Refactor FunctionStmt * Refactor * Remove UpdateStmt * Refactor AssignReplacementVisitor * Make SimplifyVisitor in-place * Fix new scoping * Fix import type alias handling * Add docstrings; Complete Simplify refactoring * Fixes for seqtest * Refactor typecheck [wip] * Refactor typecheck [wip] * Refactor typecheck/access; Remove void anduse NoneType; Fix #18 * Refactor typecheck/assign * clang-format and cmake-format * Fix none types in IR * Multi-error support in simplify * Fix IR tests for new void * Simplify ClassStmt * Refactor cond.cpp * Refactor error.cpp * Refactor function.cpp and simplify unbounds * Refactor op.cpp * Refactor call.cpp [wip] [no-ci] * seqassertn updates [noci] * Refactor call.cpp * Refactor call.cpp * Refactor call.cpp * Refactor typecheck * clang-tidy updates [noci] * Refactor infer.cpp [wip] * Refactor infer.cpp * Refactor wrapExpr * Remove visitedAsts * Remove old base logic * Refactor typecheck ctx * Fix JIT bug * Fix JIT tests * Scoping fixes [wip] [noci] * Fix ImperativeForFlow var store * Add newlines [noci] * Dump IR module with log flag * Fix scoping bugs; Add &, ^ and | static operations; Address stylistic review issues * Fix side effect analysis for for-loops * Add support for class variables and ClassVar * Refactor special dot-member cases * Add codon app tests * Fix class variables; clang-tidy * Fix __argv__ * Add datetime constants and update tests * Fix #25; Add Py_None, Py_True and Py_False; External var support [wip] * External var support [wip] * Dump LLVM IR when debug flags are active * clang-format * Fix arg var construction * Extern var fixes * Undo extern var changes related to stdout etc. * Fix tuple magics * Fix extern vars and tuple magics * Fix duplicate var name error * Fix extern vars * Fix #16 * Fix side-effect analysis for try-catch * Move test C var to test executable * Add staticmethod * Fix var status for try-catch * Fix tests * Fix shell var name * Fix test * Fix app test * Fix scoping issue (remove dominated identifier from stack) * Fix no-pie issue * Use PIC when building library object * Don't use -no-pie when building library [noci] * Use -relocation-model=pic in test * Fix lib build on Linux * Fix lib build * Update exceptions to use subclasses vs. header * Fix __repr__ * Fix tests * Fix exceptions test * Don't build docs Co-authored-by: A. R. Shajii <ars@ars.me>
2022-07-27 04:06:00 +08:00
#self.assertEqual(timedelta.min, timedelta(-999999999))
#self.assertEqual(timedelta.max, timedelta(999999999, 24*3600-1, 1e6-1))
self.assertEqual(timedelta.resolution, timedelta(0, 0, 1))
Typechecker refactoring (#20) * Initial refactor commit * Support external vars * Simplify refactor; Python scoping [wip] * Python scoping [wip] * Python scoping [fix loops; wip] * Fix lambdas * Python scoping [test fixes; wip] * Fix scoping [wip] * Fix basic tests [no-ci] * Fix tests * CallExpr refactoring [wip] * CallExpr refactoring [wip] * Remove activeUnbounds tracking * Add core.codon * Move Function and other core types to core.codon; Revamp Function and Callable types * Refactor IntExpr, FloatExpr and CallExpr * Refactor ClassStmt * Refactor context, IdExpr and DotExpr * Refactor DotExpr and AssignStmt * Refactor ImportStmt * Refactor FunctionStmt * Refactor * Remove UpdateStmt * Refactor AssignReplacementVisitor * Make SimplifyVisitor in-place * Fix new scoping * Fix import type alias handling * Add docstrings; Complete Simplify refactoring * Fixes for seqtest * Refactor typecheck [wip] * Refactor typecheck [wip] * Refactor typecheck/access; Remove void anduse NoneType; Fix #18 * Refactor typecheck/assign * clang-format and cmake-format * Fix none types in IR * Multi-error support in simplify * Fix IR tests for new void * Simplify ClassStmt * Refactor cond.cpp * Refactor error.cpp * Refactor function.cpp and simplify unbounds * Refactor op.cpp * Refactor call.cpp [wip] [no-ci] * seqassertn updates [noci] * Refactor call.cpp * Refactor call.cpp * Refactor call.cpp * Refactor typecheck * clang-tidy updates [noci] * Refactor infer.cpp [wip] * Refactor infer.cpp * Refactor wrapExpr * Remove visitedAsts * Remove old base logic * Refactor typecheck ctx * Fix JIT bug * Fix JIT tests * Scoping fixes [wip] [noci] * Fix ImperativeForFlow var store * Add newlines [noci] * Dump IR module with log flag * Fix scoping bugs; Add &, ^ and | static operations; Address stylistic review issues * Fix side effect analysis for for-loops * Add support for class variables and ClassVar * Refactor special dot-member cases * Add codon app tests * Fix class variables; clang-tidy * Fix __argv__ * Add datetime constants and update tests * Fix #25; Add Py_None, Py_True and Py_False; External var support [wip] * External var support [wip] * Dump LLVM IR when debug flags are active * clang-format * Fix arg var construction * Extern var fixes * Undo extern var changes related to stdout etc. * Fix tuple magics * Fix extern vars and tuple magics * Fix duplicate var name error * Fix extern vars * Fix #16 * Fix side-effect analysis for try-catch * Move test C var to test executable * Add staticmethod * Fix var status for try-catch * Fix tests * Fix shell var name * Fix test * Fix app test * Fix scoping issue (remove dominated identifier from stack) * Fix no-pie issue * Use PIC when building library object * Don't use -no-pie when building library [noci] * Use -relocation-model=pic in test * Fix lib build on Linux * Fix lib build * Update exceptions to use subclasses vs. header * Fix __repr__ * Fix tests * Fix exceptions test * Don't build docs Co-authored-by: A. R. Shajii <ars@ars.me>
2022-07-27 04:06:00 +08:00
"""
def test_overflow(self):
tiny = timedelta(microseconds=1) # timedelta.resolution
td = timedelta.min + tiny
td -= tiny # no problem
self.assertRaises(OverflowError, td.__sub__, tiny)
self.assertRaises(OverflowError, td.__add__, -tiny)
td = timedelta.max - tiny
td += tiny # no problem
self.assertRaises(OverflowError, td.__add__, tiny)
self.assertRaises(OverflowError, td.__sub__, -tiny)
self.assertRaises(OverflowError, lambda: -timedelta.max)
day = timedelta(1)
self.assertRaises(OverflowError, day.__mul__, 10**9)
self.assertRaises(OverflowError, day.__mul__, 1e9)
self.assertRaises(OverflowError, day.__truediv__, 1e-20)
self.assertRaises(OverflowError, day.__truediv__, 1e-10)
self.assertRaises(OverflowError, day.__truediv__, 9e-10)
def _test_overflow_special(self):
day = timedelta(1)
INF = 1. / 0.
self.assertRaises(OverflowError, day.__mul__, INF)
self.assertRaises(OverflowError, day.__mul__, -INF)
2022-01-24 18:32:33 +08:00
"""
def test_microsecond_rounding(self):
td = timedelta
eq = self.assertEqual
# Single-field rounding.
2022-01-24 18:32:33 +08:00
eq(td(milliseconds=0.4 / 1000), td(0)) # rounds to 0
eq(td(milliseconds=-0.4 / 1000), td(0)) # rounds to 0
eq(td(milliseconds=0.5 / 1000), td(microseconds=0))
eq(td(milliseconds=-0.5 / 1000), td(microseconds=-0))
eq(td(milliseconds=0.6 / 1000), td(microseconds=1))
eq(td(milliseconds=-0.6 / 1000), td(microseconds=-1))
eq(td(milliseconds=1.5 / 1000), td(microseconds=2))
eq(td(milliseconds=-1.5 / 1000), td(microseconds=-2))
eq(td(seconds=0.5 / 10 ** 6), td(microseconds=0))
eq(td(seconds=-0.5 / 10 ** 6), td(microseconds=-0))
eq(td(seconds=1 / 2 ** 7), td(microseconds=7812))
eq(td(seconds=-1 / 2 ** 7), td(microseconds=-7812))
# Rounding due to contributions from more than one field.
us_per_hour = 3600e6
us_per_day = us_per_hour * 24
2022-01-24 18:32:33 +08:00
eq(td(days=0.4 / us_per_day), td(0))
eq(td(hours=0.2 / us_per_hour), td(0))
eq(td(days=0.4 / us_per_day, hours=0.2 / us_per_hour), td(microseconds=1))
2022-01-24 18:32:33 +08:00
eq(td(days=-0.4 / us_per_day), td(0))
eq(td(hours=-0.2 / us_per_hour), td(0))
eq(td(days=-0.4 / us_per_day, hours=-0.2 / us_per_hour), td(microseconds=-1))
# Test for a patch in Issue 8860
2022-01-24 18:32:33 +08:00
eq(td(microseconds=0.5), 0.5 * td(microseconds=1.0))
resolution = td(microseconds=1) # td.resolution
2022-01-24 18:32:33 +08:00
eq(td(microseconds=0.5) // resolution, 0.5 * resolution // resolution)
def test_massive_normalization(self):
td = timedelta(microseconds=-1)
2022-01-24 18:32:33 +08:00
self.assertEqual(
(td.days, td.seconds, td.microseconds), (-1, 24 * 3600 - 1, 999999)
)
def test_bool(self):
self.assertTrue(timedelta(1))
self.assertTrue(timedelta(0, 1))
self.assertTrue(timedelta(0, 0, 1))
self.assertTrue(timedelta(microseconds=1))
self.assertFalse(timedelta(0))
def test_division(self):
t = timedelta(hours=1, minutes=24, seconds=19)
second = timedelta(seconds=1)
self.assertEqual(t / second, 5059.0)
self.assertEqual(t // second, 5059)
t = timedelta(minutes=2, seconds=30)
minute = timedelta(minutes=1)
self.assertEqual(t / minute, 2.5)
self.assertEqual(t // minute, 2)
zerotd = timedelta(0)
2022-01-24 18:32:33 +08:00
# self.assertRaises(ZeroDivisionError, truediv, t, zerotd)
# self.assertRaises(ZeroDivisionError, floordiv, t, zerotd)
def test_remainder(self):
t = timedelta(minutes=2, seconds=30)
minute = timedelta(minutes=1)
r = t % minute
self.assertEqual(r, timedelta(seconds=30))
t = timedelta(minutes=-2, seconds=30)
2022-01-24 18:32:33 +08:00
r = t % minute
self.assertEqual(r, timedelta(seconds=30))
zerotd = timedelta(0)
2022-01-24 18:32:33 +08:00
# self.assertRaises(ZeroDivisionError, mod, t, zerotd)
def test_divmod(self):
t = timedelta(minutes=2, seconds=30)
minute = timedelta(minutes=1)
q, r = divmod(t, minute)
self.assertEqual(q, 2)
self.assertEqual(r, timedelta(seconds=30))
t = timedelta(minutes=-2, seconds=30)
q, r = divmod(t, minute)
self.assertEqual(q, -2)
self.assertEqual(r, timedelta(seconds=30))
zerotd = timedelta(0)
2022-01-24 18:32:33 +08:00
# self.assertRaises(ZeroDivisionError, divmod, t, zerotd)
Dynamic Polymorphism (#58) * Use Static[] for static inheritance * Support .seq extension * Fix #36 * Polymorphic typechecking; vtables [wip] * v-table dispatch [wip] * vtable routing [wip; bug] * vtable routing [MVP] * Fix texts * Add union type support * Update FAQs * Clarify * Add BSL license * Add makeUnion * Add IR UnionType * Update union representation in LLVM * Update README * Update README.md * Update README * Update README.md * Add benchmarks * Add more benchmarks and README * Add primes benchmark * Update benchmarks * Fix cpp * Clean up list * Update faq.md * Add binary trees benchmark * Add fannkuch benchmark * Fix paths * Add PyPy * Abort on fail * More benchmarks * Add cpp word_count * Update set_partition cpp * Add nbody cpp * Add TAQ cpp; fix word_count timing * Update CODEOWNERS * Update README * Update README.md * Update CODEOWNERS * Fix bench script * Update binary_trees.cpp * Update taq.cpp * Fix primes benchmark * Add mandelbrot benchmark * Fix OpenMP init * Add Module::unsafeGetUnionType * UnionType [wip] [skip ci] * Integrate IR unions and Union * UnionType refactor [skip ci] * Update README.md * Update docs * UnionType [wip] [skip ci] * UnionType and automatic unions * Add Slack * Update faq.md * Refactor types * New error reporting [wip] * New error reporting [wip] * peglib updates [wip] [skip_ci] * Fix parsing issues * Fix parsing issues * Fix error reporting issues * Make sure random module matches Python * Update releases.md * Fix tests * Fix #59 * Fix #57 * Fix #50 * Fix #49 * Fix #26; Fix #51; Fix #47; Fix #49 * Fix collection extension methods * Fix #62 * Handle *args/**kwargs with Callable[]; Fix #43 * Fix #43 * Fix Ptr.__sub__; Fix polymorphism issues * Add typeinfo * clang-format * Upgrade fmtlib to v9; Use CPM for fmtlib; format spec support; __format__ support * Use CPM for semver and toml++ * Remove extension check * Revamp str methods * Update str.zfill * Fix thunk crashes [wip] [skip_ci] * Fix str.__reversed__ * Fix count_with_max * Fix vtable memory allocation issues * Add poly AST tests * Use PDQsort when stability does not matter * Fix dotted imports; Fix issues * Fix kwargs passing to Python * Fix #61 * Fix #37 * Add isinstance support for unions; Union methods return Union type if different * clang-format * Nicely format error tracebacks * Fix build issues; clang-format * Fix OpenMP init * Fix OpenMP init * Update README.md * Fix tests * Update license [skip ci] * Update license [ci skip] * Add copyright header to all source files * Fix super(); Fix error recovery in ClassStmt * Clean up whitespace [ci skip] * Use Python 3.9 on CI * Print info in random test * Fix single unions * Update random_test.codon * Fix polymorhic thunk instantiation * Fix random test * Add operator.attrgetter and operator.methodcaller * Add code documentation * Update documentation * Update README.md * Fix tests * Fix random init Co-authored-by: A. R. Shajii <ars@ars.me>
2022-12-05 08:45:21 +08:00
class TestDateOnly(Static[TestCase]):
def test_delta_non_days_ignored(self):
dt = date(2000, 1, 2)
2022-01-24 18:32:33 +08:00
delta = timedelta(days=1, hours=2, minutes=3, seconds=4, microseconds=5)
days = timedelta(delta.days)
self.assertEqual(days, timedelta(1))
dt2 = dt + delta
self.assertEqual(dt2, dt + days)
dt2 = delta + dt
self.assertEqual(dt2, dt + days)
dt2 = dt - delta
self.assertEqual(dt2, dt - days)
delta = -delta
days = timedelta(delta.days)
self.assertEqual(days, timedelta(-2))
dt2 = dt + delta
self.assertEqual(dt2, dt + days)
dt2 = delta + dt
self.assertEqual(dt2, dt + days)
dt2 = dt - delta
self.assertEqual(dt2, dt - days)
2022-01-24 18:32:33 +08:00
Dynamic Polymorphism (#58) * Use Static[] for static inheritance * Support .seq extension * Fix #36 * Polymorphic typechecking; vtables [wip] * v-table dispatch [wip] * vtable routing [wip; bug] * vtable routing [MVP] * Fix texts * Add union type support * Update FAQs * Clarify * Add BSL license * Add makeUnion * Add IR UnionType * Update union representation in LLVM * Update README * Update README.md * Update README * Update README.md * Add benchmarks * Add more benchmarks and README * Add primes benchmark * Update benchmarks * Fix cpp * Clean up list * Update faq.md * Add binary trees benchmark * Add fannkuch benchmark * Fix paths * Add PyPy * Abort on fail * More benchmarks * Add cpp word_count * Update set_partition cpp * Add nbody cpp * Add TAQ cpp; fix word_count timing * Update CODEOWNERS * Update README * Update README.md * Update CODEOWNERS * Fix bench script * Update binary_trees.cpp * Update taq.cpp * Fix primes benchmark * Add mandelbrot benchmark * Fix OpenMP init * Add Module::unsafeGetUnionType * UnionType [wip] [skip ci] * Integrate IR unions and Union * UnionType refactor [skip ci] * Update README.md * Update docs * UnionType [wip] [skip ci] * UnionType and automatic unions * Add Slack * Update faq.md * Refactor types * New error reporting [wip] * New error reporting [wip] * peglib updates [wip] [skip_ci] * Fix parsing issues * Fix parsing issues * Fix error reporting issues * Make sure random module matches Python * Update releases.md * Fix tests * Fix #59 * Fix #57 * Fix #50 * Fix #49 * Fix #26; Fix #51; Fix #47; Fix #49 * Fix collection extension methods * Fix #62 * Handle *args/**kwargs with Callable[]; Fix #43 * Fix #43 * Fix Ptr.__sub__; Fix polymorphism issues * Add typeinfo * clang-format * Upgrade fmtlib to v9; Use CPM for fmtlib; format spec support; __format__ support * Use CPM for semver and toml++ * Remove extension check * Revamp str methods * Update str.zfill * Fix thunk crashes [wip] [skip_ci] * Fix str.__reversed__ * Fix count_with_max * Fix vtable memory allocation issues * Add poly AST tests * Use PDQsort when stability does not matter * Fix dotted imports; Fix issues * Fix kwargs passing to Python * Fix #61 * Fix #37 * Add isinstance support for unions; Union methods return Union type if different * clang-format * Nicely format error tracebacks * Fix build issues; clang-format * Fix OpenMP init * Fix OpenMP init * Update README.md * Fix tests * Update license [skip ci] * Update license [ci skip] * Add copyright header to all source files * Fix super(); Fix error recovery in ClassStmt * Clean up whitespace [ci skip] * Use Python 3.9 on CI * Print info in random test * Fix single unions * Update random_test.codon * Fix polymorhic thunk instantiation * Fix random test * Add operator.attrgetter and operator.methodcaller * Add code documentation * Update documentation * Update README.md * Fix tests * Fix random init Co-authored-by: A. R. Shajii <ars@ars.me>
2022-12-05 08:45:21 +08:00
class TestDate(Static[TestCase]):
2022-01-24 18:32:33 +08:00
theclass: type
def test_basic_attributes(self):
dt = self.theclass(2002, 3, 1)
self.assertEqual(dt.year, 2002)
self.assertEqual(dt.month, 3)
self.assertEqual(dt.day, 1)
def test_ordinal_conversions(self):
# Check some fixed values.
2022-01-24 18:32:33 +08:00
for y, m, d, n in [
(1, 1, 1, 1), # calendar origin
(1, 12, 31, 365),
(2, 1, 1, 366),
# first example from "Calendrical Calculations"
(1945, 11, 12, 710347),
]:
dt = self.theclass(y, m, d)
self.assertEqual(n, dt.toordinal())
fromord = self.theclass.fromordinal(n)
self.assertEqual(dt, fromord)
if hasattr(fromord, "hour"):
2022-01-24 18:32:33 +08:00
# if we're checking something fancier than a date, verify
# the extra fields have been zeroed out
self.assertEqual(fromord.hour, 0)
self.assertEqual(fromord.minute, 0)
self.assertEqual(fromord.second, 0)
self.assertEqual(fromord.microsecond, 0)
# Check first and last days of year spottily across the whole
# range of years supported.
2022-01-24 18:32:33 +08:00
for year in range(MINYEAR, MAXYEAR + 1, 7):
# Verify (year, 1, 1) -> ordinal -> y, m, d is identity.
d = self.theclass(year, 1, 1)
n = d.toordinal()
d2 = self.theclass.fromordinal(n)
self.assertEqual(d, d2)
# Verify that moving back a day gets to the end of year-1.
if year > 1:
2022-01-24 18:32:33 +08:00
d = self.theclass.fromordinal(n - 1)
d2 = self.theclass(year - 1, 12, 31)
self.assertEqual(d, d2)
2022-01-24 18:32:33 +08:00
self.assertEqual(d2.toordinal(), n - 1)
# Test every day in a leap-year and a non-leap year.
dim = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
for year, isleap in (2000, True), (2002, False):
n = self.theclass(year, 1, 1).toordinal()
for month, maxday in zip(range(1, 13), dim):
if month == 2 and isleap:
maxday += 1
2022-01-24 18:32:33 +08:00
for day in range(1, maxday + 1):
d = self.theclass(year, month, day)
self.assertEqual(d.toordinal(), n)
self.assertEqual(d, self.theclass.fromordinal(n))
n += 1
2022-01-24 18:32:33 +08:00
"""
def test_extreme_ordinals(self):
a = self.theclass.min
a = self.theclass(a.year, a.month, a.day) # get rid of time parts
aord = a.toordinal()
b = a.fromordinal(aord)
self.assertEqual(a, b)
self.assertRaises(ValueError, lambda: a.fromordinal(aord - 1))
b = a + timedelta(days=1)
self.assertEqual(b.toordinal(), aord + 1)
self.assertEqual(b, self.theclass.fromordinal(aord + 1))
a = self.theclass.max
a = self.theclass(a.year, a.month, a.day) # get rid of time parts
aord = a.toordinal()
b = a.fromordinal(aord)
self.assertEqual(a, b)
self.assertRaises(ValueError, lambda: a.fromordinal(aord + 1))
b = a - timedelta(days=1)
self.assertEqual(b.toordinal(), aord - 1)
self.assertEqual(b, self.theclass.fromordinal(aord - 1))
2022-01-24 18:32:33 +08:00
"""
def test_bad_constructor_arguments(self):
# bad years
self.theclass(MINYEAR, 1, 1) # no exception
self.theclass(MAXYEAR, 1, 1) # no exception
def make(theclass, a, b, c):
return self.theclass(a, b, c)
2022-01-24 18:32:33 +08:00
self.assertRaises(ValueError, make(self.theclass, ...), MINYEAR - 1, 1, 1)
self.assertRaises(ValueError, make(self.theclass, ...), MAXYEAR + 1, 1, 1)
# bad months
2022-01-24 18:32:33 +08:00
self.theclass(2000, 1, 1) # no exception
self.theclass(2000, 12, 1) # no exception
self.assertRaises(ValueError, make(self.theclass, ...), 2000, 0, 1)
self.assertRaises(ValueError, make(self.theclass, ...), 2000, 13, 1)
# bad days
2022-01-24 18:32:33 +08:00
self.theclass(2000, 2, 29) # no exception
self.theclass(2004, 2, 29) # no exception
self.theclass(2400, 2, 29) # no exception
self.assertRaises(ValueError, make(self.theclass, ...), 2000, 2, 30)
self.assertRaises(ValueError, make(self.theclass, ...), 2001, 2, 29)
self.assertRaises(ValueError, make(self.theclass, ...), 2100, 2, 29)
self.assertRaises(ValueError, make(self.theclass, ...), 1900, 2, 29)
self.assertRaises(ValueError, make(self.theclass, ...), 2000, 1, 0)
self.assertRaises(ValueError, make(self.theclass, ...), 2000, 1, 32)
def test_hash_equality(self):
d = self.theclass(2000, 12, 31)
# same thing
e = self.theclass(2000, 12, 31)
self.assertEqual(d, e)
self.assertEqual(hash(d), hash(e))
dic = {d: 1}
dic[e] = 2
self.assertEqual(len(dic), 1)
self.assertEqual(dic[d], 2)
self.assertEqual(dic[e], 2)
2022-01-24 18:32:33 +08:00
d = self.theclass(2001, 1, 1)
# same thing
2022-01-24 18:32:33 +08:00
e = self.theclass(2001, 1, 1)
self.assertEqual(d, e)
self.assertEqual(hash(d), hash(e))
dic = {d: 1}
dic[e] = 2
self.assertEqual(len(dic), 1)
self.assertEqual(dic[d], 2)
self.assertEqual(dic[e], 2)
def test_computations(self):
a = self.theclass(2002, 1, 31)
b = self.theclass(1956, 1, 31)
2022-01-24 18:32:33 +08:00
c = self.theclass(2001, 2, 1)
2022-01-24 18:32:33 +08:00
diff = a - b
self.assertEqual(diff.days, 46 * 365 + len(range(1956, 2002, 4)))
self.assertEqual(diff.seconds, 0)
self.assertEqual(diff.microseconds, 0)
day = timedelta(1)
week = timedelta(7)
a = self.theclass(2002, 3, 2)
self.assertEqual(a + day, self.theclass(2002, 3, 3))
self.assertEqual(day + a, self.theclass(2002, 3, 3))
self.assertEqual(a - day, self.theclass(2002, 3, 1))
self.assertEqual(-day + a, self.theclass(2002, 3, 1))
self.assertEqual(a + week, self.theclass(2002, 3, 9))
self.assertEqual(a - week, self.theclass(2002, 2, 23))
2022-01-24 18:32:33 +08:00
self.assertEqual(a + 52 * week, self.theclass(2003, 3, 1))
self.assertEqual(a - 52 * week, self.theclass(2001, 3, 3))
self.assertEqual((a + week) - a, week)
self.assertEqual((a + day) - a, day)
self.assertEqual((a - week) - a, -week)
self.assertEqual((a - day) - a, -day)
self.assertEqual(a - (a + week), -week)
self.assertEqual(a - (a + day), -day)
self.assertEqual(a - (a - week), week)
self.assertEqual(a - (a - day), day)
self.assertEqual(c - (c - day), day)
2022-01-24 18:32:33 +08:00
"""
# Add/sub ints or floats should be illegal
for i in 1, 1.0:
self.assertRaises(TypeError, lambda: a+i)
self.assertRaises(TypeError, lambda: a-i)
self.assertRaises(TypeError, lambda: i+a)
self.assertRaises(TypeError, lambda: i-a)
# delta - date is senseless.
self.assertRaises(TypeError, lambda: day - a)
# mixing date and (delta or date) via * or // is senseless
self.assertRaises(TypeError, lambda: day * a)
self.assertRaises(TypeError, lambda: a * day)
self.assertRaises(TypeError, lambda: day // a)
self.assertRaises(TypeError, lambda: a // day)
self.assertRaises(TypeError, lambda: a * a)
self.assertRaises(TypeError, lambda: a // a)
# date + date is senseless
self.assertRaises(TypeError, lambda: a + a)
2022-01-24 18:32:33 +08:00
"""
2022-01-24 18:32:33 +08:00
"""
def test_overflow(self):
tiny = self.theclass.resolution
for delta in [tiny, timedelta(1), timedelta(2)]:
dt = self.theclass.min + delta
dt -= delta # no problem
self.assertRaises(OverflowError, dt.__sub__, delta)
self.assertRaises(OverflowError, dt.__add__, -delta)
dt = self.theclass.max - delta
dt += delta # no problem
self.assertRaises(OverflowError, dt.__add__, delta)
self.assertRaises(OverflowError, dt.__sub__, -delta)
2022-01-24 18:32:33 +08:00
"""
def test_fromtimestamp(self):
import time
# Try an arbitrary fixed value.
year, month, day = 1999, 9, 19
ts = time.mktime((year, month, day, 0, 0, 0, 0, 0, -1))
d = self.theclass.fromtimestamp(ts)
self.assertEqual(d.year, year)
self.assertEqual(d.month, month)
self.assertEqual(d.day, day)
def test_today(self):
import time
# We claim that today() is like fromtimestamp(time.time()), so
# prove it.
today = self.theclass.today()
todayagain = today
for dummy in range(3):
today = self.theclass.today()
ts = time.time()
todayagain = self.theclass.fromtimestamp(ts)
if today == todayagain:
break
# There are several legit reasons that could fail:
# 1. It recently became midnight, between the today() and the
# time() calls.
# 2. The platform time() has such fine resolution that we'll
# never get the same value twice.
# 3. The platform time() has poor resolution, and we just
# happened to call today() right before a resolution quantum
# boundary.
# 4. The system clock got fiddled between calls.
# In any case, wait a little while and try again.
time.sleep(0.1)
# It worked or it didn't. If it didn't, assume it's reason #2, and
# let the test pass if they're within half a second of each other.
if today != todayagain:
2022-01-24 18:32:33 +08:00
self.assertAlmostEqual(todayagain, today, delta=timedelta(seconds=0.5))
def test_weekday(self):
for i in range(7):
# March 4, 2002 is a Monday
2022-01-24 18:32:33 +08:00
self.assertEqual(self.theclass(2002, 3, 4 + i).weekday(), i)
self.assertEqual(self.theclass(2002, 3, 4 + i).isoweekday(), i + 1)
# January 2, 1956 is a Monday
2022-01-24 18:32:33 +08:00
self.assertEqual(self.theclass(1956, 1, 2 + i).weekday(), i)
self.assertEqual(self.theclass(1956, 1, 2 + i).isoweekday(), i + 1)
def test_isocalendar(self):
# Check examples from
# http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
week_mondays = [
2022-01-24 18:32:33 +08:00
((2003, 12, 22), (2003, 52, 1)),
((2003, 12, 29), (2004, 1, 1)),
((2004, 1, 5), (2004, 2, 1)),
((2009, 12, 21), (2009, 52, 1)),
((2009, 12, 28), (2009, 53, 1)),
((2010, 1, 4), (2010, 1, 1)),
]
test_cases = []
for cal_date, iso_date in week_mondays:
base_date = self.theclass(*cal_date)
# Adds one test case for every day of the specified weeks
for i in range(7):
new_date = base_date + timedelta(i)
new_iso = iso_date[0:2] + (iso_date[2] + i,)
test_cases.append((new_date, new_iso))
for d, exp_iso in test_cases:
self.assertEqual(d.isocalendar(), exp_iso)
# Check that the tuple contents are accessible by field name
t = d.isocalendar()
self.assertEqual((t.year, t.week, t.weekday), exp_iso)
def test_iso_long_years(self):
# Calculate long ISO years and compare to table from
# http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
ISO_LONG_YEARS_TABLE = """
4 32 60 88
9 37 65 93
15 43 71 99
20 48 76
26 54 82
105 133 161 189
111 139 167 195
116 144 172
122 150 178
128 156 184
201 229 257 285
207 235 263 291
212 240 268 296
218 246 274
224 252 280
303 331 359 387
308 336 364 392
314 342 370 398
320 348 376
325 353 381
"""
iso_long_years = sorted(map(int, ISO_LONG_YEARS_TABLE.split()))
L = []
for i in range(400):
2022-01-24 18:32:33 +08:00
d = self.theclass(2000 + i, 12, 31).isocalendar()
d1 = self.theclass(1600 + i, 12, 31).isocalendar()
self.assertEqual((d.week, d.weekday), (d1.week, d1.weekday))
if d.week == 53:
L.append(i)
self.assertEqual(L, iso_long_years)
def test_isoformat(self):
t = self.theclass(2, 3, 2)
self.assertEqual(t.isoformat(), "0002-03-02")
def test_ctime(self):
t = self.theclass(2002, 3, 2)
self.assertEqual(t.ctime(), "Sat Mar 2 00:00:00 2002")
def test_resolution_info(self):
self.assertTrue(self.theclass.max > self.theclass.min)
Typechecker refactoring (#20) * Initial refactor commit * Support external vars * Simplify refactor; Python scoping [wip] * Python scoping [wip] * Python scoping [fix loops; wip] * Fix lambdas * Python scoping [test fixes; wip] * Fix scoping [wip] * Fix basic tests [no-ci] * Fix tests * CallExpr refactoring [wip] * CallExpr refactoring [wip] * Remove activeUnbounds tracking * Add core.codon * Move Function and other core types to core.codon; Revamp Function and Callable types * Refactor IntExpr, FloatExpr and CallExpr * Refactor ClassStmt * Refactor context, IdExpr and DotExpr * Refactor DotExpr and AssignStmt * Refactor ImportStmt * Refactor FunctionStmt * Refactor * Remove UpdateStmt * Refactor AssignReplacementVisitor * Make SimplifyVisitor in-place * Fix new scoping * Fix import type alias handling * Add docstrings; Complete Simplify refactoring * Fixes for seqtest * Refactor typecheck [wip] * Refactor typecheck [wip] * Refactor typecheck/access; Remove void anduse NoneType; Fix #18 * Refactor typecheck/assign * clang-format and cmake-format * Fix none types in IR * Multi-error support in simplify * Fix IR tests for new void * Simplify ClassStmt * Refactor cond.cpp * Refactor error.cpp * Refactor function.cpp and simplify unbounds * Refactor op.cpp * Refactor call.cpp [wip] [no-ci] * seqassertn updates [noci] * Refactor call.cpp * Refactor call.cpp * Refactor call.cpp * Refactor typecheck * clang-tidy updates [noci] * Refactor infer.cpp [wip] * Refactor infer.cpp * Refactor wrapExpr * Remove visitedAsts * Remove old base logic * Refactor typecheck ctx * Fix JIT bug * Fix JIT tests * Scoping fixes [wip] [noci] * Fix ImperativeForFlow var store * Add newlines [noci] * Dump IR module with log flag * Fix scoping bugs; Add &, ^ and | static operations; Address stylistic review issues * Fix side effect analysis for for-loops * Add support for class variables and ClassVar * Refactor special dot-member cases * Add codon app tests * Fix class variables; clang-tidy * Fix __argv__ * Add datetime constants and update tests * Fix #25; Add Py_None, Py_True and Py_False; External var support [wip] * External var support [wip] * Dump LLVM IR when debug flags are active * clang-format * Fix arg var construction * Extern var fixes * Undo extern var changes related to stdout etc. * Fix tuple magics * Fix extern vars and tuple magics * Fix duplicate var name error * Fix extern vars * Fix #16 * Fix side-effect analysis for try-catch * Move test C var to test executable * Add staticmethod * Fix var status for try-catch * Fix tests * Fix shell var name * Fix test * Fix app test * Fix scoping issue (remove dominated identifier from stack) * Fix no-pie issue * Use PIC when building library object * Don't use -no-pie when building library [noci] * Use -relocation-model=pic in test * Fix lib build on Linux * Fix lib build * Update exceptions to use subclasses vs. header * Fix __repr__ * Fix tests * Fix exceptions test * Don't build docs Co-authored-by: A. R. Shajii <ars@ars.me>
2022-07-27 04:06:00 +08:00
"""
def test_extreme_timedelta(self):
big = self.theclass.max - self.theclass.min
# 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds
n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds
# n == 315537897599999999 ~= 2**58.13
justasbig = timedelta(0, 0, n)
self.assertEqual(big, justasbig)
self.assertEqual(self.theclass.min + big, self.theclass.max)
self.assertEqual(self.theclass.max - big, self.theclass.min)
2022-01-24 18:32:33 +08:00
"""
def test_timetuple(self):
from time import struct_time
2022-01-24 18:32:33 +08:00
for i in range(7):
# January 2, 1956 is a Monday (0)
2022-01-24 18:32:33 +08:00
d = self.theclass(1956, 1, 2 + i)
t = d.timetuple()
2022-01-24 18:32:33 +08:00
self.assertEqual(t, struct_time(1956, 1, 2 + i, 0, 0, 0, i, 2 + i, -1))
# February 1, 1956 is a Wednesday (2)
2022-01-24 18:32:33 +08:00
d = self.theclass(1956, 2, 1 + i)
t = d.timetuple()
2022-01-24 18:32:33 +08:00
self.assertEqual(
t, struct_time(1956, 2, 1 + i, 0, 0, 0, (2 + i) % 7, 32 + i, -1)
)
# March 1, 1956 is a Thursday (3), and is the 31+29+1 = 61st day
# of the year.
2022-01-24 18:32:33 +08:00
d = self.theclass(1956, 3, 1 + i)
t = d.timetuple()
2022-01-24 18:32:33 +08:00
self.assertEqual(
t, struct_time(1956, 3, 1 + i, 0, 0, 0, (3 + i) % 7, 61 + i, -1)
)
self.assertEqual(t.tm_year, 1956)
self.assertEqual(t.tm_mon, 3)
2022-01-24 18:32:33 +08:00
self.assertEqual(t.tm_mday, 1 + i)
self.assertEqual(t.tm_hour, 0)
self.assertEqual(t.tm_min, 0)
self.assertEqual(t.tm_sec, 0)
2022-01-24 18:32:33 +08:00
self.assertEqual(t.tm_wday, (3 + i) % 7)
self.assertEqual(t.tm_yday, 61 + i)
self.assertEqual(t.tm_isdst, -1)
def test_compare(self):
t1 = self.theclass(2, 3, 4)
t2 = self.theclass(2, 3, 4)
self.assertEqual(t1, t2)
self.assertTrue(t1 <= t2)
self.assertTrue(t1 >= t2)
self.assertFalse(t1 != t2)
self.assertFalse(t1 < t2)
self.assertFalse(t1 > t2)
for args in (3, 3, 3), (2, 4, 4), (2, 3, 5):
2022-01-24 18:32:33 +08:00
t2 = self.theclass(*args) # this is larger than t1
self.assertTrue(t1 < t2)
self.assertTrue(t2 > t1)
self.assertTrue(t1 <= t2)
self.assertTrue(t2 >= t1)
self.assertTrue(t1 != t2)
self.assertTrue(t2 != t1)
self.assertFalse(t1 == t2)
self.assertFalse(t2 == t1)
self.assertFalse(t1 > t2)
self.assertFalse(t2 < t1)
self.assertFalse(t1 >= t2)
self.assertFalse(t2 <= t1)
2022-01-24 18:32:33 +08:00
"""
for badarg in OTHERSTUFF:
self.assertEqual(t1 == badarg, False)
self.assertEqual(t1 != badarg, True)
self.assertEqual(badarg == t1, False)
self.assertEqual(badarg != t1, True)
self.assertRaises(TypeError, lambda: t1 < badarg)
self.assertRaises(TypeError, lambda: t1 > badarg)
self.assertRaises(TypeError, lambda: t1 >= badarg)
self.assertRaises(TypeError, lambda: badarg <= t1)
self.assertRaises(TypeError, lambda: badarg < t1)
self.assertRaises(TypeError, lambda: badarg > t1)
self.assertRaises(TypeError, lambda: badarg >= t1)
2022-01-24 18:32:33 +08:00
"""
def test_bool(self):
# All dates are considered true.
2022-01-24 18:32:33 +08:00
# self.assertTrue(self.theclass.min)
# self.assertTrue(self.theclass.max)
self.assertTrue(self.theclass(1, 1, 1))
def test_replace(self):
cls = self.theclass
args = (1, 2, 3)
base = cls(*args)
self.assertEqual(base, base.replace())
self.assertEqual(base.replace(year=2), cls(2, 2, 3))
self.assertEqual(base.replace(month=3), cls(1, 3, 3))
self.assertEqual(base.replace(day=4), cls(1, 2, 4))
# Out of bounds.
base = cls(2000, 2, 29)
self.assertRaises(ValueError, base.replace, year=2001)
def test_fromisoformat(self):
# Test that isoformat() is reversible
base_dates = [
(1, 1, 1),
(1000, 2, 14),
(1900, 1, 1),
(2000, 2, 29),
(2004, 11, 12),
(2004, 4, 3),
2022-01-24 18:32:33 +08:00
(2017, 5, 30),
]
for dt_tuple in base_dates:
dt = self.theclass(*dt_tuple)
dt_str = dt.isoformat()
dt_rt = self.theclass.fromisoformat(dt.isoformat())
self.assertEqual(dt, dt_rt)
def test_fromisoformat_fails(self):
# Test that fromisoformat() fails on invalid values
bad_strs = [
2022-01-24 18:32:33 +08:00
"", # Empty string
"\ud800", # bpo-34454: Surrogate code point
"009-03-04", # Not 10 characters
"123456789", # Not a date
"200a-12-04", # Invalid character in year
"2009-1a-04", # Invalid character in month
"2009-12-0a", # Invalid character in day
"2009-01-32", # Invalid day
"2009-02-29", # Invalid leap day
"20090228", # Valid ISO8601 output not from isoformat()
"2009\ud80002\ud80028", # Separators are surrogate codepoints
]
for bad_str in bad_strs:
self.assertRaises(ValueError, self.theclass.fromisoformat, bad_str)
def test_fromisocalendar(self):
# For each test case, assert that fromisocalendar is the
# inverse of the isocalendar function
dates = [
(2016, 4, 3),
2022-01-24 18:32:33 +08:00
(2005, 1, 2), # (2004, 53, 7)
(2008, 12, 30), # (2009, 1, 2)
(2010, 1, 2), # (2009, 53, 6)
(2009, 12, 31), # (2009, 53, 4)
(1900, 1, 1), # Unusual non-leap year (year % 100 == 0)
(1900, 12, 31),
2022-01-24 18:32:33 +08:00
(2000, 1, 1), # Unusual leap year (year % 400 == 0)
(2000, 12, 31),
2022-01-24 18:32:33 +08:00
(2004, 1, 1), # Leap year
(2004, 12, 31),
(1, 1, 1),
(9999, 12, 31),
(MINYEAR, 1, 1),
(MAXYEAR, 12, 31),
]
for datecomps in dates:
dobj = self.theclass(*datecomps)
isocal = dobj.isocalendar()
d_roundtrip = self.theclass.fromisocalendar(*isocal)
self.assertEqual(dobj, d_roundtrip)
def test_fromisocalendar_value_errors(self):
isocals = [
(2019, 0, 1),
(2019, -1, 1),
(2019, 54, 1),
(2019, 1, 0),
(2019, 1, -1),
(2019, 1, 8),
(2019, 53, 1),
(10000, 1, 1),
(0, 1, 1),
(9999999, 1, 1),
2022-01-24 18:32:33 +08:00
(2 << 32, 1, 1),
(2019, 2 << 32, 1),
(2019, 1, 2 << 32),
]
for isocal in isocals:
self.assertRaises(ValueError, self.theclass.fromisocalendar, *isocal)
2022-01-24 18:32:33 +08:00
Dynamic Polymorphism (#58) * Use Static[] for static inheritance * Support .seq extension * Fix #36 * Polymorphic typechecking; vtables [wip] * v-table dispatch [wip] * vtable routing [wip; bug] * vtable routing [MVP] * Fix texts * Add union type support * Update FAQs * Clarify * Add BSL license * Add makeUnion * Add IR UnionType * Update union representation in LLVM * Update README * Update README.md * Update README * Update README.md * Add benchmarks * Add more benchmarks and README * Add primes benchmark * Update benchmarks * Fix cpp * Clean up list * Update faq.md * Add binary trees benchmark * Add fannkuch benchmark * Fix paths * Add PyPy * Abort on fail * More benchmarks * Add cpp word_count * Update set_partition cpp * Add nbody cpp * Add TAQ cpp; fix word_count timing * Update CODEOWNERS * Update README * Update README.md * Update CODEOWNERS * Fix bench script * Update binary_trees.cpp * Update taq.cpp * Fix primes benchmark * Add mandelbrot benchmark * Fix OpenMP init * Add Module::unsafeGetUnionType * UnionType [wip] [skip ci] * Integrate IR unions and Union * UnionType refactor [skip ci] * Update README.md * Update docs * UnionType [wip] [skip ci] * UnionType and automatic unions * Add Slack * Update faq.md * Refactor types * New error reporting [wip] * New error reporting [wip] * peglib updates [wip] [skip_ci] * Fix parsing issues * Fix parsing issues * Fix error reporting issues * Make sure random module matches Python * Update releases.md * Fix tests * Fix #59 * Fix #57 * Fix #50 * Fix #49 * Fix #26; Fix #51; Fix #47; Fix #49 * Fix collection extension methods * Fix #62 * Handle *args/**kwargs with Callable[]; Fix #43 * Fix #43 * Fix Ptr.__sub__; Fix polymorphism issues * Add typeinfo * clang-format * Upgrade fmtlib to v9; Use CPM for fmtlib; format spec support; __format__ support * Use CPM for semver and toml++ * Remove extension check * Revamp str methods * Update str.zfill * Fix thunk crashes [wip] [skip_ci] * Fix str.__reversed__ * Fix count_with_max * Fix vtable memory allocation issues * Add poly AST tests * Use PDQsort when stability does not matter * Fix dotted imports; Fix issues * Fix kwargs passing to Python * Fix #61 * Fix #37 * Add isinstance support for unions; Union methods return Union type if different * clang-format * Nicely format error tracebacks * Fix build issues; clang-format * Fix OpenMP init * Fix OpenMP init * Update README.md * Fix tests * Update license [skip ci] * Update license [ci skip] * Add copyright header to all source files * Fix super(); Fix error recovery in ClassStmt * Clean up whitespace [ci skip] * Use Python 3.9 on CI * Print info in random test * Fix single unions * Update random_test.codon * Fix polymorhic thunk instantiation * Fix random test * Add operator.attrgetter and operator.methodcaller * Add code documentation * Update documentation * Update README.md * Fix tests * Fix random init Co-authored-by: A. R. Shajii <ars@ars.me>
2022-12-05 08:45:21 +08:00
class TestDateTime(Static[TestDate[theclass]]):
2022-01-24 18:32:33 +08:00
theclass: type
def test_basic_attributes(self):
dt = self.theclass(2002, 3, 1, 12, 0)
self.assertEqual(dt.year, 2002)
self.assertEqual(dt.month, 3)
self.assertEqual(dt.day, 1)
self.assertEqual(dt.hour, 12)
self.assertEqual(dt.minute, 0)
self.assertEqual(dt.second, 0)
self.assertEqual(dt.microsecond, 0)
def test_basic_attributes_nonzero(self):
# Make sure all attributes are non-zero so bugs in
# bit-shifting access show up.
dt = self.theclass(2002, 3, 1, 12, 59, 59, 8000)
self.assertEqual(dt.year, 2002)
self.assertEqual(dt.month, 3)
self.assertEqual(dt.day, 1)
self.assertEqual(dt.hour, 12)
self.assertEqual(dt.minute, 59)
self.assertEqual(dt.second, 59)
self.assertEqual(dt.microsecond, 8000)
def test_isoformat(self):
t = self.theclass(1, 2, 3, 4, 5, 1, 123)
2022-01-24 18:32:33 +08:00
self.assertEqual(t.isoformat(), "0001-02-03T04:05:01.000123")
self.assertEqual(t.isoformat("T"), "0001-02-03T04:05:01.000123")
self.assertEqual(t.isoformat(" "), "0001-02-03 04:05:01.000123")
self.assertEqual(t.isoformat("\x00"), "0001-02-03\x0004:05:01.000123")
# bpo-34482: Check that surrogates are handled properly.
2022-01-24 18:32:33 +08:00
self.assertEqual(t.isoformat("\ud800"), "0001-02-03\ud80004:05:01.000123")
self.assertEqual(t.isoformat(timespec="hours"), "0001-02-03T04")
self.assertEqual(t.isoformat(timespec="minutes"), "0001-02-03T04:05")
self.assertEqual(t.isoformat(timespec="seconds"), "0001-02-03T04:05:01")
self.assertEqual(
t.isoformat(timespec="milliseconds"), "0001-02-03T04:05:01.000"
)
self.assertEqual(
t.isoformat(timespec="microseconds"), "0001-02-03T04:05:01.000123"
)
self.assertEqual(t.isoformat(timespec="auto"), "0001-02-03T04:05:01.000123")
self.assertEqual(t.isoformat(sep=" ", timespec="minutes"), "0001-02-03 04:05")
# str is ISO format with the separator forced to a blank.
self.assertEqual(str(t), "0001-02-03 04:05:01.000123")
2022-01-24 18:32:33 +08:00
# t = self.theclass(1, 2, 3, 4, 5, 1, 999500, tzinfo=timezone.utc)
# self.assertEqual(t.isoformat(timespec='milliseconds'), "0001-02-03T04:05:01.999+00:00")
t = self.theclass(1, 2, 3, 4, 5, 1, 999500)
2022-01-24 18:32:33 +08:00
self.assertEqual(
t.isoformat(timespec="milliseconds"), "0001-02-03T04:05:01.999"
)
t = self.theclass(1, 2, 3, 4, 5, 1)
2022-01-24 18:32:33 +08:00
self.assertEqual(t.isoformat(timespec="auto"), "0001-02-03T04:05:01")
self.assertEqual(
t.isoformat(timespec="milliseconds"), "0001-02-03T04:05:01.000"
)
self.assertEqual(
t.isoformat(timespec="microseconds"), "0001-02-03T04:05:01.000000"
)
t = self.theclass(2, 3, 2)
2022-01-24 18:32:33 +08:00
self.assertEqual(t.isoformat(), "0002-03-02T00:00:00")
self.assertEqual(t.isoformat("T"), "0002-03-02T00:00:00")
self.assertEqual(t.isoformat(" "), "0002-03-02 00:00:00")
# str is ISO format with the separator forced to a blank.
self.assertEqual(str(t), "0002-03-02 00:00:00")
# ISO format with timezone
2022-01-24 18:32:33 +08:00
# tz = FixedOffset(timedelta(seconds=16), 'XXX')
# t = self.theclass(2, 3, 2, tzinfo=tz)
# self.assertEqual(t.isoformat(), "0002-03-02T00:00:00+00:00:16")
2022-01-24 18:32:33 +08:00
"""
def test_isoformat_timezone(self):
tzoffsets = [
('05:00', timedelta(hours=5)),
('02:00', timedelta(hours=2)),
('06:27', timedelta(hours=6, minutes=27)),
('12:32:30', timedelta(hours=12, minutes=32, seconds=30)),
('02:04:09.123456', timedelta(hours=2, minutes=4, seconds=9, microseconds=123456))
]
tzinfos = [
('', None),
('+00:00', timezone.utc),
('+00:00', timezone(timedelta(0))),
]
tzinfos += [
(prefix + expected, timezone(sign * td))
for expected, td in tzoffsets
for prefix, sign in [('-', -1), ('+', 1)]
]
dt_base = self.theclass(2016, 4, 1, 12, 37, 9)
exp_base = '2016-04-01T12:37:09'
for exp_tz, tzi in tzinfos:
dt = dt_base.replace(tzinfo=tzi)
exp = exp_base + exp_tz
with self.subTest(tzi=tzi):
assert dt.isoformat() == exp
2022-01-24 18:32:33 +08:00
"""
2022-01-24 18:32:33 +08:00
"""
def test_more_ctime(self):
# Test fields that TestDate doesn't touch.
import time
t = self.theclass(2002, 3, 2, 18, 3, 5, 123)
self.assertEqual(t.ctime(), "Sat Mar 2 18:03:05 2002")
# Oops! The next line fails on Win2K under MSVC 6, so it's commented
# out. The difference is that t.ctime() produces " 2" for the day,
# but platform ctime() produces "02" for the day. According to
# C99, t.ctime() is correct here.
# self.assertEqual(t.ctime(), time.ctime(time.mktime(t.timetuple())))
# So test a case where that difference doesn't matter.
t = self.theclass(2002, 3, 22, 18, 3, 5, 123)
self.assertEqual(t.ctime(), time.ctime(time.mktime(t.timetuple())))
2022-01-24 18:32:33 +08:00
"""
def test_tz_independent_comparing(self):
dt1 = self.theclass(2002, 3, 1, 9, 0, 0)
dt2 = self.theclass(2002, 3, 1, 10, 0, 0)
dt3 = self.theclass(2002, 3, 1, 9, 0, 0)
self.assertEqual(dt1, dt3)
self.assertTrue(dt2 > dt3)
# Make sure comparison doesn't forget microseconds, and isn't done
# via comparing a float timestamp (an IEEE double doesn't have enough
# precision to span microsecond resolution across years 1 through 9999,
# so comparing via timestamp necessarily calls some distinct values
# equal).
dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998)
us = timedelta(microseconds=1)
dt2 = dt1 + us
self.assertEqual(dt2 - dt1, us)
self.assertTrue(dt1 < dt2)
def test_bad_constructor_arguments(self):
# bad years
self.theclass(MINYEAR, 1, 1) # no exception
self.theclass(MAXYEAR, 1, 1) # no exception
make_dt1 = lambda a, b, c: self.theclass(a, b, c)
make_dt2 = lambda a, b, c, d: self.theclass(a, b, c, d)
make_dt3 = lambda a, b, c, d, e: self.theclass(a, b, c, d, e)
make_dt4 = lambda a, b, c, d, e, f: self.theclass(a, b, c, d, e, f)
make_dt5 = lambda a, b, c, d, e, f, g: self.theclass(a, b, c, d, e, f, g)
2022-01-24 18:32:33 +08:00
self.assertRaises(ValueError, make_dt1, MINYEAR - 1, 1, 1)
self.assertRaises(ValueError, make_dt1, MAXYEAR + 1, 1, 1)
# bad months
2022-01-24 18:32:33 +08:00
self.theclass(2000, 1, 1) # no exception
self.theclass(2000, 12, 1) # no exception
self.assertRaises(ValueError, make_dt1, 2000, 0, 1)
self.assertRaises(ValueError, make_dt1, 2000, 13, 1)
# bad days
2022-01-24 18:32:33 +08:00
self.theclass(2000, 2, 29) # no exception
self.theclass(2004, 2, 29) # no exception
self.theclass(2400, 2, 29) # no exception
self.assertRaises(ValueError, make_dt1, 2000, 2, 30)
self.assertRaises(ValueError, make_dt1, 2001, 2, 29)
self.assertRaises(ValueError, make_dt1, 2100, 2, 29)
self.assertRaises(ValueError, make_dt1, 1900, 2, 29)
self.assertRaises(ValueError, make_dt1, 2000, 1, 0)
self.assertRaises(ValueError, make_dt1, 2000, 1, 32)
# bad hours
2022-01-24 18:32:33 +08:00
self.theclass(2000, 1, 31, 0) # no exception
self.theclass(2000, 1, 31, 23) # no exception
self.assertRaises(ValueError, make_dt2, 2000, 1, 31, -1)
self.assertRaises(ValueError, make_dt2, 2000, 1, 31, 24)
# bad minutes
2022-01-24 18:32:33 +08:00
self.theclass(2000, 1, 31, 23, 0) # no exception
self.theclass(2000, 1, 31, 23, 59) # no exception
self.assertRaises(ValueError, make_dt3, 2000, 1, 31, 23, -1)
self.assertRaises(ValueError, make_dt3, 2000, 1, 31, 23, 60)
# bad seconds
2022-01-24 18:32:33 +08:00
self.theclass(2000, 1, 31, 23, 59, 0) # no exception
self.theclass(2000, 1, 31, 23, 59, 59) # no exception
self.assertRaises(ValueError, make_dt4, 2000, 1, 31, 23, 59, -1)
self.assertRaises(ValueError, make_dt4, 2000, 1, 31, 23, 59, 60)
# bad microseconds
2022-01-24 18:32:33 +08:00
self.theclass(2000, 1, 31, 23, 59, 59, 0) # no exception
self.theclass(2000, 1, 31, 23, 59, 59, 999999) # no exception
self.assertRaises(ValueError, make_dt5, 2000, 1, 31, 23, 59, 59, -1)
self.assertRaises(ValueError, make_dt5, 2000, 1, 31, 23, 59, 59, 1000000)
"""
# bad fold
self.assertRaises(ValueError, self.theclass,
2000, 1, 31, fold=-1)
self.assertRaises(ValueError, self.theclass,
2000, 1, 31, fold=2)
# Positional fold:
self.assertRaises(TypeError, self.theclass,
2000, 1, 31, 23, 59, 59, 0, None, 1)
2022-01-24 18:32:33 +08:00
"""
def test_hash_equality(self):
d = self.theclass(2000, 12, 31, 23, 30, 17)
e = self.theclass(2000, 12, 31, 23, 30, 17)
self.assertEqual(d, e)
self.assertEqual(hash(d), hash(e))
dic = {d: 1}
dic[e] = 2
self.assertEqual(len(dic), 1)
self.assertEqual(dic[d], 2)
self.assertEqual(dic[e], 2)
2022-01-24 18:32:33 +08:00
d = self.theclass(2001, 1, 1, 0, 5, 17)
e = self.theclass(2001, 1, 1, 0, 5, 17)
self.assertEqual(d, e)
self.assertEqual(hash(d), hash(e))
dic = {d: 1}
dic[e] = 2
self.assertEqual(len(dic), 1)
self.assertEqual(dic[d], 2)
self.assertEqual(dic[e], 2)
def test_computations(self):
a = self.theclass(2002, 1, 31)
b = self.theclass(1956, 1, 31)
2022-01-24 18:32:33 +08:00
diff = a - b
self.assertEqual(diff.days, 46 * 365 + len(range(1956, 2002, 4)))
self.assertEqual(diff.seconds, 0)
self.assertEqual(diff.microseconds, 0)
a = self.theclass(2002, 3, 2, 17, 6)
millisec = timedelta(0, 0, 1000)
hour = timedelta(0, 3600)
day = timedelta(1)
week = timedelta(7)
self.assertEqual(a + hour, self.theclass(2002, 3, 2, 18, 6))
self.assertEqual(hour + a, self.theclass(2002, 3, 2, 18, 6))
2022-01-24 18:32:33 +08:00
self.assertEqual(a + 10 * hour, self.theclass(2002, 3, 3, 3, 6))
self.assertEqual(a - hour, self.theclass(2002, 3, 2, 16, 6))
self.assertEqual(-hour + a, self.theclass(2002, 3, 2, 16, 6))
self.assertEqual(a - hour, a + -hour)
2022-01-24 18:32:33 +08:00
self.assertEqual(a - 20 * hour, self.theclass(2002, 3, 1, 21, 6))
self.assertEqual(a + day, self.theclass(2002, 3, 3, 17, 6))
self.assertEqual(a - day, self.theclass(2002, 3, 1, 17, 6))
self.assertEqual(a + week, self.theclass(2002, 3, 9, 17, 6))
self.assertEqual(a - week, self.theclass(2002, 2, 23, 17, 6))
2022-01-24 18:32:33 +08:00
self.assertEqual(a + 52 * week, self.theclass(2003, 3, 1, 17, 6))
self.assertEqual(a - 52 * week, self.theclass(2001, 3, 3, 17, 6))
self.assertEqual((a + week) - a, week)
self.assertEqual((a + day) - a, day)
self.assertEqual((a + hour) - a, hour)
self.assertEqual((a + millisec) - a, millisec)
self.assertEqual((a - week) - a, -week)
self.assertEqual((a - day) - a, -day)
self.assertEqual((a - hour) - a, -hour)
self.assertEqual((a - millisec) - a, -millisec)
self.assertEqual(a - (a + week), -week)
self.assertEqual(a - (a + day), -day)
self.assertEqual(a - (a + hour), -hour)
self.assertEqual(a - (a + millisec), -millisec)
self.assertEqual(a - (a - week), week)
self.assertEqual(a - (a - day), day)
self.assertEqual(a - (a - hour), hour)
self.assertEqual(a - (a - millisec), millisec)
2022-01-24 18:32:33 +08:00
self.assertEqual(
a + (week + day + hour + millisec),
self.theclass(2002, 3, 10, 18, 6, 0, 1000),
)
self.assertEqual(
a + (week + day + hour + millisec), (((a + week) + day) + hour) + millisec
)
self.assertEqual(
a - (week + day + hour + millisec),
self.theclass(2002, 2, 22, 16, 5, 59, 999000),
)
self.assertEqual(
a - (week + day + hour + millisec), (((a - week) - day) - hour) - millisec
)
"""
# Add/sub ints or floats should be illegal
for i in 1, 1.0:
self.assertRaises(TypeError, lambda: a+i)
self.assertRaises(TypeError, lambda: a-i)
self.assertRaises(TypeError, lambda: i+a)
self.assertRaises(TypeError, lambda: i-a)
# delta - datetime is senseless.
self.assertRaises(TypeError, lambda: day - a)
# mixing datetime and (delta or datetime) via * or // is senseless
self.assertRaises(TypeError, lambda: day * a)
self.assertRaises(TypeError, lambda: a * day)
self.assertRaises(TypeError, lambda: day // a)
self.assertRaises(TypeError, lambda: a // day)
self.assertRaises(TypeError, lambda: a * a)
self.assertRaises(TypeError, lambda: a // a)
# datetime + datetime is senseless
self.assertRaises(TypeError, lambda: a + a)
2022-01-24 18:32:33 +08:00
"""
def test_more_compare(self):
# The test_compare() inherited from TestDate covers the error cases.
# We just want to test lexicographic ordering on the members datetime
# has that date lacks.
args = (2000, 11, 29, 20, 58, 16, 999998)
newargsx = [
(2001, 11, 29, 20, 58, 16, 999998),
(2000, 12, 29, 20, 58, 16, 999998),
(2000, 11, 30, 20, 58, 16, 999998),
(2000, 11, 29, 21, 58, 16, 999998),
(2000, 11, 29, 20, 59, 16, 999998),
(2000, 11, 29, 20, 58, 17, 999998),
2022-01-24 18:32:33 +08:00
(2000, 11, 29, 20, 58, 16, 999999),
]
t1 = self.theclass(*args)
t2 = self.theclass(*args)
self.assertEqual(t1, t2)
self.assertTrue(t1 <= t2)
self.assertTrue(t1 >= t2)
self.assertFalse(t1 != t2)
self.assertFalse(t1 < t2)
self.assertFalse(t1 > t2)
for i in range(len(args)):
newargs = newargsx[i]
2022-01-24 18:32:33 +08:00
t2 = self.theclass(*newargs) # this is larger than t1
self.assertTrue(t1 < t2)
self.assertTrue(t2 > t1)
self.assertTrue(t1 <= t2)
self.assertTrue(t2 >= t1)
self.assertTrue(t1 != t2)
self.assertTrue(t2 != t1)
self.assertFalse(t1 == t2)
self.assertFalse(t2 == t1)
self.assertFalse(t1 > t2)
self.assertFalse(t2 < t1)
self.assertFalse(t1 >= t2)
self.assertFalse(t2 <= t1)
# A helper for timestamp constructor tests.
def verify_field_equality(self, expected, got):
self.assertEqual(expected.tm_year, got.year)
self.assertEqual(expected.tm_mon, got.month)
self.assertEqual(expected.tm_mday, got.day)
self.assertEqual(expected.tm_hour, got.hour)
self.assertEqual(expected.tm_min, got.minute)
self.assertEqual(expected.tm_sec, got.second)
def test_fromtimestamp(self):
import time
ts = time.time()
expected = time.localtime(int(ts))
got = self.theclass.fromtimestamp(ts)
self.verify_field_equality(expected, got)
2022-01-24 18:32:33 +08:00
"""
def test_utcfromtimestamp(self):
import time
ts = time.time()
expected = time.gmtime(int(ts))
got = self.theclass.utcfromtimestamp(ts)
self.verify_field_equality(expected, got)
2022-01-24 18:32:33 +08:00
"""
def test_timestamp_naive(self):
2022-01-24 18:32:33 +08:00
"""
t = self.theclass(1970, 1, 1)
self.assertEqual(t.timestamp(), 18000.0)
t = self.theclass(1970, 1, 1, 1, 2, 3, 4)
self.assertEqual(t.timestamp(),
18000.0 + 3600 + 2*60 + 3 + 4*1e-6)
2022-01-24 18:32:33 +08:00
"""
t = self.theclass(1970, 1, 1)
self.assertEqual(t.timestamp(), 0)
t = self.theclass(1970, 1, 1, 1, 2, 3, 4)
2022-01-24 18:32:33 +08:00
self.assertEqual(t.timestamp(), 3600 + 2 * 60 + 3 + 4 * 1e-6)
2022-01-24 18:32:33 +08:00
"""
# Missing hour
t0 = self.theclass(2012, 3, 11, 2, 30)
t1 = t0.replace(fold=1)
self.assertEqual(self.theclass.fromtimestamp(t1.timestamp()),
t0 - timedelta(hours=1))
self.assertEqual(self.theclass.fromtimestamp(t0.timestamp()),
t1 + timedelta(hours=1))
# Ambiguous hour defaults to DST
t = self.theclass(2012, 11, 4, 1, 30)
self.assertEqual(self.theclass.fromtimestamp(t.timestamp()), t)
# Timestamp may raise an overflow error on some platforms
# XXX: Do we care to support the first and last year?
for t in [self.theclass(2,1,1), self.theclass(9998,12,12)]:
s = None
try:
s = t.timestamp()
except OverflowError:
continue
self.assertEqual(self.theclass.fromtimestamp(s), t)
2022-01-24 18:32:33 +08:00
"""
2022-01-24 18:32:33 +08:00
"""
def test_timestamp_aware(self):
t = self.theclass(1970, 1, 1, tzinfo=timezone.utc)
self.assertEqual(t.timestamp(), 0.0)
t = self.theclass(1970, 1, 1, 1, 2, 3, 4, tzinfo=timezone.utc)
self.assertEqual(t.timestamp(),
3600 + 2*60 + 3 + 4*1e-6)
t = self.theclass(1970, 1, 1, 1, 2, 3, 4,
tzinfo=timezone(timedelta(hours=-5), 'EST'))
self.assertEqual(t.timestamp(),
18000 + 3600 + 2*60 + 3 + 4*1e-6)
2022-01-24 18:32:33 +08:00
"""
"""
def test_microsecond_rounding(self):
for fts in (self.theclass.fromtimestamp,
self.theclass.utcfromtimestamp):
zero = fts(0)
self.assertEqual(zero.second, 0)
self.assertEqual(zero.microsecond, 0)
one = fts(1e-6)
minus_one = fts(-1e-6)
self.assertEqual(minus_one.second, 59)
self.assertEqual(minus_one.microsecond, 999999)
t = fts(-1e-8)
self.assertEqual(t, zero)
t = fts(-9e-7)
self.assertEqual(t, minus_one)
t = fts(-1e-7)
self.assertEqual(t, zero)
t = fts(-1/2**7)
self.assertEqual(t.second, 59)
self.assertEqual(t.microsecond, 992188)
t = fts(1e-7)
self.assertEqual(t, zero)
t = fts(9e-7)
self.assertEqual(t, one)
t = fts(0.99999949)
self.assertEqual(t.second, 0)
self.assertEqual(t.microsecond, 999999)
t = fts(0.9999999)
self.assertEqual(t.second, 1)
self.assertEqual(t.microsecond, 0)
t = fts(1/2**7)
self.assertEqual(t.second, 0)
self.assertEqual(t.microsecond, 7812)
2022-01-24 18:32:33 +08:00
"""
"""
def test_timestamp_limits(self):
# minimum timestamp
min_dt = self.theclass.min.replace(tzinfo=timezone.utc)
min_ts = min_dt.timestamp()
try:
# date 0001-01-01 00:00:00+00:00: timestamp=-62135596800
self.assertEqual(self.theclass.fromtimestamp(min_ts, tz=timezone.utc),
min_dt)
except (OverflowError, OSError) as exc:
# the date 0001-01-01 doesn't fit into 32-bit time_t,
# or platform doesn't support such very old date
self.skipTest(str(exc))
# maximum timestamp: set seconds to zero to avoid rounding issues
max_dt = self.theclass.max.replace(tzinfo=timezone.utc,
second=0, microsecond=0)
max_ts = max_dt.timestamp()
# date 9999-12-31 23:59:00+00:00: timestamp 253402300740
self.assertEqual(self.theclass.fromtimestamp(max_ts, tz=timezone.utc),
max_dt)
# number of seconds greater than 1 year: make sure that the new date
# is not valid in datetime.datetime limits
delta = 3600 * 24 * 400
# too small
ts = min_ts - delta
# converting a Python int to C time_t can raise a OverflowError,
# especially on 32-bit platforms.
self.assertRaises(ValueError, self.theclass.fromtimestamp, ts)
self.assertRaises(ValueError, self.theclass.utcfromtimestamp, ts)
# too big
ts = max_dt.timestamp() + delta
self.assertRaises(ValueError, self.theclass.fromtimestamp, ts)
self.assertRaises(ValueError, self.theclass.utcfromtimestamp, ts)
2022-01-24 18:32:33 +08:00
"""
def test_negative_float_fromtimestamp(self):
# The result is tz-dependent; at least test that this doesn't
# fail (like it did before bug 1646728 was fixed).
self.theclass.fromtimestamp(-1.05)
2022-01-24 18:32:33 +08:00
"""
def test_negative_float_utcfromtimestamp(self):
d = self.theclass.utcfromtimestamp(-1.05)
self.assertEqual(d, self.theclass(1969, 12, 31, 23, 59, 58, 950000))
2022-01-24 18:32:33 +08:00
"""
def test_utcnow(self):
import time
# Call it a success if utcnow() and utcfromtimestamp() are within
# a second of each other.
from_timestamp = None
from_now = None
tolerance = timedelta(seconds=1)
for dummy in range(3):
from_now = self.theclass.utcnow()
from_timestamp = self.theclass.utcfromtimestamp(time.time())
if abs(from_timestamp.__val__() - from_now.__val__()) <= tolerance:
break
# Else try again a few times.
self.assertLessEqual(abs(from_timestamp.__val__() - from_now.__val__()), tolerance)
def test_extract(self):
dt = self.theclass(2002, 3, 4, 18, 45, 3, 1234)
self.assertEqual(dt.date(), date(2002, 3, 4))
self.assertEqual(dt.time(), time(18, 45, 3, 1234))
def test_combine(self):
d = date(2002, 3, 4)
t = time(18, 45, 3, 1234)
expected = self.theclass(2002, 3, 4, 18, 45, 3, 1234)
combine = self.theclass.combine
dt = combine(d, t)
self.assertEqual(dt, expected)
dt = combine(time=t, date=d)
self.assertEqual(dt, expected)
self.assertEqual(d, dt.date())
self.assertEqual(t, dt.time())
self.assertEqual(dt, combine(dt.date(), dt.time()))
2022-01-24 18:32:33 +08:00
"""
self.assertRaises(TypeError, combine) # need an arg
self.assertRaises(TypeError, combine, d) # need two args
self.assertRaises(TypeError, combine, t, d) # args reversed
self.assertRaises(TypeError, combine, d, t, 1) # wrong tzinfo type
self.assertRaises(TypeError, combine, d, t, 1, 2) # too many args
self.assertRaises(TypeError, combine, "date", "time") # wrong types
self.assertRaises(TypeError, combine, d, "time") # wrong type
self.assertRaises(TypeError, combine, "date", t) # wrong type
# tzinfo= argument
dt = combine(d, t, timezone.utc)
self.assertIs(dt.tzinfo, timezone.utc)
dt = combine(d, t, tzinfo=timezone.utc)
self.assertIs(dt.tzinfo, timezone.utc)
t = time()
dt = combine(dt, t)
self.assertEqual(dt.date(), d)
self.assertEqual(dt.time(), t)
2022-01-24 18:32:33 +08:00
"""
def test_replace(self):
cls = self.theclass
args = (1, 2, 3, 4, 5, 6, 7)
base = cls(*args)
self.assertEqual(base, base.replace())
self.assertEqual(base.replace(year=2), cls(2, 2, 3, 4, 5, 6, 7))
self.assertEqual(base.replace(month=3), cls(1, 3, 3, 4, 5, 6, 7))
self.assertEqual(base.replace(day=4), cls(1, 2, 4, 4, 5, 6, 7))
self.assertEqual(base.replace(hour=5), cls(1, 2, 3, 5, 5, 6, 7))
self.assertEqual(base.replace(minute=6), cls(1, 2, 3, 4, 6, 6, 7))
self.assertEqual(base.replace(second=7), cls(1, 2, 3, 4, 5, 7, 7))
self.assertEqual(base.replace(microsecond=8), cls(1, 2, 3, 4, 5, 6, 8))
# Out of bounds.
base = cls(2000, 2, 29)
self.assertRaises(ValueError, lambda: base.replace(year=2001))
2022-01-24 18:32:33 +08:00
"""
def test_astimezone(self):
dt = self.theclass.now()
f = FixedOffset(44, "0044")
dt_utc = dt.replace(tzinfo=timezone(timedelta(hours=-4), 'EDT'))
self.assertEqual(dt.astimezone(), dt_utc) # naive
self.assertRaises(TypeError, dt.astimezone, f, f) # too many args
self.assertRaises(TypeError, dt.astimezone, dt) # arg wrong type
dt_f = dt.replace(tzinfo=f) + timedelta(hours=4, minutes=44)
self.assertEqual(dt.astimezone(f), dt_f) # naive
self.assertEqual(dt.astimezone(tz=f), dt_f) # naive
class Bogus(tzinfo):
def utcoffset(self, dt): return None
def dst(self, dt): return timedelta(0)
bog = Bogus()
self.assertRaises(ValueError, dt.astimezone, bog) # naive
self.assertEqual(dt.replace(tzinfo=bog).astimezone(f), dt_f)
class AlsoBogus(tzinfo):
def utcoffset(self, dt): return timedelta(0)
def dst(self, dt): return None
alsobog = AlsoBogus()
self.assertRaises(ValueError, dt.astimezone, alsobog) # also naive
class Broken(tzinfo):
def utcoffset(self, dt): return 1
def dst(self, dt): return 1
broken = Broken()
dt_broken = dt.replace(tzinfo=broken)
with self.assertRaises(TypeError):
dt_broken.astimezone()
2022-01-24 18:32:33 +08:00
"""
def test_fromisoformat_datetime(self):
# Test that isoformat() is reversible
2022-01-24 18:32:33 +08:00
base_dates = [(1, 1, 1), (1900, 1, 1), (2004, 11, 12), (2017, 5, 30)]
base_times = [
(0, 0, 0, 0),
(0, 0, 0, 241000),
(0, 0, 0, 234567),
2022-01-24 18:32:33 +08:00
(12, 30, 45, 234567),
]
2022-01-24 18:32:33 +08:00
separators = [" ", "T"]
2022-01-24 18:32:33 +08:00
dts = [
self.theclass(*date_tuple, *time_tuple)
for date_tuple in base_dates
for time_tuple in base_times
]
for dt in dts:
for sep in separators:
dtstr = dt.isoformat(sep=sep)
dt_rt = self.theclass.fromisoformat(dtstr)
self.assertEqual(dt, dt_rt)
def test_fromisoformat_separators(self):
2022-01-24 18:32:33 +08:00
separators = [" ", "T"]
for sep in separators:
dt = self.theclass(2018, 1, 31, 23, 59, 47, 124789)
dtstr = dt.isoformat(sep=sep)
dt_rt = self.theclass.fromisoformat(dtstr)
self.assertEqual(dt, dt_rt)
def test_fromisoformat_ambiguous(self):
# Test strings like 2018-01-31+12:15 (where +12:15 is not a time zone)
2022-01-24 18:32:33 +08:00
separators = ["+", "-"]
for sep in separators:
dt = self.theclass(2018, 1, 31, 12, 15)
dtstr = dt.isoformat(sep=sep)
dt_rt = self.theclass.fromisoformat(dtstr)
self.assertEqual(dt, dt_rt)
def test_fromisoformat_timespecs(self):
2022-01-24 18:32:33 +08:00
datetime_bases = [(2009, 12, 4, 8, 17, 45, 123456), (2009, 12, 4, 8, 17, 45, 0)]
2022-01-24 18:32:33 +08:00
timespecs = ["hours", "minutes", "seconds", "milliseconds", "microseconds"]
for dt_tuple in datetime_bases:
dt = self.theclass(*(dt_tuple[0:4]))
2022-01-24 18:32:33 +08:00
dtstr = dt.isoformat(timespec="hours")
dt_rt = self.theclass.fromisoformat(dtstr)
self.assertEqual(dt, dt_rt)
dt = self.theclass(*(dt_tuple[0:5]))
2022-01-24 18:32:33 +08:00
dtstr = dt.isoformat(timespec="minutes")
dt_rt = self.theclass.fromisoformat(dtstr)
self.assertEqual(dt, dt_rt)
dt = self.theclass(*(dt_tuple[0:6]))
2022-01-24 18:32:33 +08:00
dtstr = dt.isoformat(timespec="seconds")
dt_rt = self.theclass.fromisoformat(dtstr)
self.assertEqual(dt, dt_rt)
new_microseconds = 1000 * (dt_tuple[6] // 1000)
dt_tuple2 = (*dt_tuple[0:6], new_microseconds)
dt = self.theclass(*(dt_tuple2[0:7]))
2022-01-24 18:32:33 +08:00
dtstr = dt.isoformat(timespec="milliseconds")
dt_rt = self.theclass.fromisoformat(dtstr)
self.assertEqual(dt, dt_rt)
dt = self.theclass(*(dt_tuple[0:8]))
2022-01-24 18:32:33 +08:00
dtstr = dt.isoformat(timespec="microseconds")
dt_rt = self.theclass.fromisoformat(dtstr)
self.assertEqual(dt, dt_rt)
def test_fromisoformat_fails_datetime(self):
# Test that fromisoformat() fails on invalid values
bad_strs = [
2022-01-24 18:32:33 +08:00
"", # Empty string
"\ud800", # bpo-34454: Surrogate code point
"2009.04-19T03", # Wrong first separator
"2009-04.19T03", # Wrong second separator
"2009-04-19T0a", # Invalid hours
"2009-04-19T03:1a:45", # Invalid minutes
"2009-04-19T03:15:4a", # Invalid seconds
"2009-04-19T03;15:45", # Bad first time separator
"2009-04-19T03:15;45", # Bad second time separator
"2009-04-19T03:15:4500:00", # Bad time zone separator
"2009-04-19T03:15:45.2345", # Too many digits for milliseconds
"2009-04-19T03:15:45.1234567", # Too many digits for microseconds
"2009-04-19T03:15:45.123456+24:30", # Invalid time zone offset
"2009-04-19T03:15:45.123456-24:30", # Invalid negative offset
"2009-04-10ᛇᛇᛇᛇᛇ12:15", # Too many unicode separators
"2009-04\ud80010T12:15", # Surrogate char in date
"2009-04-10T12\ud80015", # Surrogate char in time
"2009-04-19T1", # Incomplete hours
"2009-04-19T12:3", # Incomplete minutes
"2009-04-19T12:30:4", # Incomplete seconds
"2009-04-19T12:", # Ends with time separator
"2009-04-19T12:30:", # Ends with time separator
"2009-04-19T12:30:45.", # Ends with time separator
"2009-04-19T12:30:45.123456+", # Ends with timzone separator
"2009-04-19T12:30:45.123456-", # Ends with timzone separator
"2009-04-19T12:30:45.123456-05:00a", # Extra text
"2009-04-19T12:30:45.123-05:00a", # Extra text
"2009-04-19T12:30:45-05:00a", # Extra text
]
for bad_str in bad_strs:
self.assertRaises(ValueError, self.theclass.fromisoformat, bad_str)
2022-01-24 18:32:33 +08:00
Dynamic Polymorphism (#58) * Use Static[] for static inheritance * Support .seq extension * Fix #36 * Polymorphic typechecking; vtables [wip] * v-table dispatch [wip] * vtable routing [wip; bug] * vtable routing [MVP] * Fix texts * Add union type support * Update FAQs * Clarify * Add BSL license * Add makeUnion * Add IR UnionType * Update union representation in LLVM * Update README * Update README.md * Update README * Update README.md * Add benchmarks * Add more benchmarks and README * Add primes benchmark * Update benchmarks * Fix cpp * Clean up list * Update faq.md * Add binary trees benchmark * Add fannkuch benchmark * Fix paths * Add PyPy * Abort on fail * More benchmarks * Add cpp word_count * Update set_partition cpp * Add nbody cpp * Add TAQ cpp; fix word_count timing * Update CODEOWNERS * Update README * Update README.md * Update CODEOWNERS * Fix bench script * Update binary_trees.cpp * Update taq.cpp * Fix primes benchmark * Add mandelbrot benchmark * Fix OpenMP init * Add Module::unsafeGetUnionType * UnionType [wip] [skip ci] * Integrate IR unions and Union * UnionType refactor [skip ci] * Update README.md * Update docs * UnionType [wip] [skip ci] * UnionType and automatic unions * Add Slack * Update faq.md * Refactor types * New error reporting [wip] * New error reporting [wip] * peglib updates [wip] [skip_ci] * Fix parsing issues * Fix parsing issues * Fix error reporting issues * Make sure random module matches Python * Update releases.md * Fix tests * Fix #59 * Fix #57 * Fix #50 * Fix #49 * Fix #26; Fix #51; Fix #47; Fix #49 * Fix collection extension methods * Fix #62 * Handle *args/**kwargs with Callable[]; Fix #43 * Fix #43 * Fix Ptr.__sub__; Fix polymorphism issues * Add typeinfo * clang-format * Upgrade fmtlib to v9; Use CPM for fmtlib; format spec support; __format__ support * Use CPM for semver and toml++ * Remove extension check * Revamp str methods * Update str.zfill * Fix thunk crashes [wip] [skip_ci] * Fix str.__reversed__ * Fix count_with_max * Fix vtable memory allocation issues * Add poly AST tests * Use PDQsort when stability does not matter * Fix dotted imports; Fix issues * Fix kwargs passing to Python * Fix #61 * Fix #37 * Add isinstance support for unions; Union methods return Union type if different * clang-format * Nicely format error tracebacks * Fix build issues; clang-format * Fix OpenMP init * Fix OpenMP init * Update README.md * Fix tests * Update license [skip ci] * Update license [ci skip] * Add copyright header to all source files * Fix super(); Fix error recovery in ClassStmt * Clean up whitespace [ci skip] * Use Python 3.9 on CI * Print info in random test * Fix single unions * Update random_test.codon * Fix polymorhic thunk instantiation * Fix random test * Add operator.attrgetter and operator.methodcaller * Add code documentation * Update documentation * Update README.md * Fix tests * Fix random init Co-authored-by: A. R. Shajii <ars@ars.me>
2022-12-05 08:45:21 +08:00
class TestTime(Static[TestCase]):
2022-01-24 18:32:33 +08:00
theclass: type = time
def test_basic_attributes(self):
t = self.theclass(12, 0)
self.assertEqual(t.hour, 12)
self.assertEqual(t.minute, 0)
self.assertEqual(t.second, 0)
self.assertEqual(t.microsecond, 0)
def test_basic_attributes_nonzero(self):
# Make sure all attributes are non-zero so bugs in
# bit-shifting access show up.
t = self.theclass(12, 59, 59, 8000)
self.assertEqual(t.hour, 12)
self.assertEqual(t.minute, 59)
self.assertEqual(t.second, 59)
self.assertEqual(t.microsecond, 8000)
def test_comparing(self):
args = (1, 2, 3, 4)
2022-01-24 18:32:33 +08:00
newargsx = [(2, 2, 3, 4), (1, 3, 3, 4), (1, 2, 4, 4), (1, 2, 3, 5)]
t1 = self.theclass(*args)
t2 = self.theclass(*args)
self.assertEqual(t1, t2)
self.assertTrue(t1 <= t2)
self.assertTrue(t1 >= t2)
self.assertFalse(t1 != t2)
self.assertFalse(t1 < t2)
self.assertFalse(t1 > t2)
for i in range(len(args)):
newargs = newargsx[i]
2022-01-24 18:32:33 +08:00
t2 = self.theclass(*newargs) # this is larger than t1
self.assertTrue(t1 < t2)
self.assertTrue(t2 > t1)
self.assertTrue(t1 <= t2)
self.assertTrue(t2 >= t1)
self.assertTrue(t1 != t2)
self.assertTrue(t2 != t1)
self.assertFalse(t1 == t2)
self.assertFalse(t2 == t1)
self.assertFalse(t1 > t2)
self.assertFalse(t2 < t1)
self.assertFalse(t1 >= t2)
self.assertFalse(t2 <= t1)
2022-01-24 18:32:33 +08:00
"""
for badarg in OTHERSTUFF:
self.assertEqual(t1 == badarg, False)
self.assertEqual(t1 != badarg, True)
self.assertEqual(badarg == t1, False)
self.assertEqual(badarg != t1, True)
self.assertRaises(TypeError, lambda: t1 <= badarg)
self.assertRaises(TypeError, lambda: t1 < badarg)
self.assertRaises(TypeError, lambda: t1 > badarg)
self.assertRaises(TypeError, lambda: t1 >= badarg)
self.assertRaises(TypeError, lambda: badarg <= t1)
self.assertRaises(TypeError, lambda: badarg < t1)
self.assertRaises(TypeError, lambda: badarg > t1)
self.assertRaises(TypeError, lambda: badarg >= t1)
2022-01-24 18:32:33 +08:00
"""
def test_bad_constructor_arguments(self):
# bad hours
2022-01-24 18:32:33 +08:00
self.theclass(0, 0) # no exception
self.theclass(23, 0) # no exception
make_time1 = lambda a, b: self.theclass(a, b)
make_time2 = lambda a, b, c: self.theclass(a, b, c)
make_time3 = lambda a, b, c, d: self.theclass(a, b, c, d)
self.assertRaises(ValueError, make_time1, -1, 0)
self.assertRaises(ValueError, make_time1, 24, 0)
# bad minutes
2022-01-24 18:32:33 +08:00
self.theclass(23, 0) # no exception
self.theclass(23, 59) # no exception
self.assertRaises(ValueError, make_time1, 23, -1)
self.assertRaises(ValueError, make_time1, 23, 60)
# bad seconds
2022-01-24 18:32:33 +08:00
self.theclass(23, 59, 0) # no exception
self.theclass(23, 59, 59) # no exception
self.assertRaises(ValueError, make_time2, 23, 59, -1)
self.assertRaises(ValueError, make_time2, 23, 59, 60)
# bad microseconds
2022-01-24 18:32:33 +08:00
self.theclass(23, 59, 59, 0) # no exception
self.theclass(23, 59, 59, 999999) # no exception
self.assertRaises(ValueError, make_time3, 23, 59, 59, -1)
self.assertRaises(ValueError, make_time3, 23, 59, 59, 1000000)
def test_hash_equality(self):
d = self.theclass(23, 30, 17)
e = self.theclass(23, 30, 17)
self.assertEqual(d, e)
self.assertEqual(hash(d), hash(e))
dic = {d: 1}
dic[e] = 2
self.assertEqual(len(dic), 1)
self.assertEqual(dic[d], 2)
self.assertEqual(dic[e], 2)
2022-01-24 18:32:33 +08:00
d = self.theclass(0, 5, 17)
e = self.theclass(0, 5, 17)
self.assertEqual(d, e)
self.assertEqual(hash(d), hash(e))
dic = {d: 1}
dic[e] = 2
self.assertEqual(len(dic), 1)
self.assertEqual(dic[d], 2)
self.assertEqual(dic[e], 2)
def test_isoformat(self):
t = self.theclass(4, 5, 1, 123)
self.assertEqual(t.isoformat(), "04:05:01.000123")
self.assertEqual(t.isoformat(), str(t))
t = self.theclass()
self.assertEqual(t.isoformat(), "00:00:00")
self.assertEqual(t.isoformat(), str(t))
t = self.theclass(microsecond=1)
self.assertEqual(t.isoformat(), "00:00:00.000001")
self.assertEqual(t.isoformat(), str(t))
t = self.theclass(microsecond=10)
self.assertEqual(t.isoformat(), "00:00:00.000010")
self.assertEqual(t.isoformat(), str(t))
t = self.theclass(microsecond=100)
self.assertEqual(t.isoformat(), "00:00:00.000100")
self.assertEqual(t.isoformat(), str(t))
t = self.theclass(microsecond=1000)
self.assertEqual(t.isoformat(), "00:00:00.001000")
self.assertEqual(t.isoformat(), str(t))
t = self.theclass(microsecond=10000)
self.assertEqual(t.isoformat(), "00:00:00.010000")
self.assertEqual(t.isoformat(), str(t))
t = self.theclass(microsecond=100000)
self.assertEqual(t.isoformat(), "00:00:00.100000")
self.assertEqual(t.isoformat(), str(t))
t = self.theclass(hour=12, minute=34, second=56, microsecond=123456)
2022-01-24 18:32:33 +08:00
self.assertEqual(t.isoformat(timespec="hours"), "12")
self.assertEqual(t.isoformat(timespec="minutes"), "12:34")
self.assertEqual(t.isoformat(timespec="seconds"), "12:34:56")
self.assertEqual(t.isoformat(timespec="milliseconds"), "12:34:56.123")
self.assertEqual(t.isoformat(timespec="microseconds"), "12:34:56.123456")
self.assertEqual(t.isoformat(timespec="auto"), "12:34:56.123456")
t = self.theclass(hour=12, minute=34, second=56, microsecond=999500)
2022-01-24 18:32:33 +08:00
self.assertEqual(t.isoformat(timespec="milliseconds"), "12:34:56.999")
t = self.theclass(hour=12, minute=34, second=56, microsecond=0)
2022-01-24 18:32:33 +08:00
self.assertEqual(t.isoformat(timespec="milliseconds"), "12:34:56.000")
self.assertEqual(t.isoformat(timespec="microseconds"), "12:34:56.000000")
self.assertEqual(t.isoformat(timespec="auto"), "12:34:56")
def test_str(self):
self.assertEqual(str(self.theclass(1, 2, 3, 4)), "01:02:03.000004")
self.assertEqual(str(self.theclass(10, 2, 3, 4000)), "10:02:03.004000")
self.assertEqual(str(self.theclass(0, 2, 3, 400000)), "00:02:03.400000")
self.assertEqual(str(self.theclass(12, 2, 3, 0)), "12:02:03")
self.assertEqual(str(self.theclass(23, 15, 0, 0)), "23:15:00")
def test_repr(self):
2022-01-24 18:32:33 +08:00
self.assertEqual(
repr(self.theclass(1, 2, 3, 4)),
"time(hour=1, minute=2, second=3, microsecond=4)",
)
self.assertEqual(
repr(self.theclass(10, 2, 3, 4000)),
"time(hour=10, minute=2, second=3, microsecond=4000)",
)
self.assertEqual(
repr(self.theclass(0, 2, 3, 400000)),
"time(hour=0, minute=2, second=3, microsecond=400000)",
)
self.assertEqual(
repr(self.theclass(12, 2, 3, 0)), "time(hour=12, minute=2, second=3)"
)
self.assertEqual(repr(self.theclass(23, 15, 0, 0)), "time(hour=23, minute=15)")
def test_resolution_info(self):
self.assertTrue(self.theclass.max > self.theclass.min)
def test_bool(self):
# time is always True.
cls = self.theclass
self.assertTrue(cls(1))
self.assertTrue(cls(0, 1))
self.assertTrue(cls(0, 0, 1))
self.assertTrue(cls(0, 0, 0, 1))
self.assertTrue(cls(0))
self.assertTrue(cls())
def test_replace(self):
cls = self.theclass
args = (1, 2, 3, 4)
base = cls(*args)
self.assertEqual(base, base.replace())
self.assertEqual(base.replace(hour=5), cls(5, 2, 3, 4))
self.assertEqual(base.replace(minute=6), cls(1, 6, 3, 4))
self.assertEqual(base.replace(second=7), cls(1, 2, 7, 4))
self.assertEqual(base.replace(microsecond=8), cls(1, 2, 3, 8))
# Out of bounds.
base = cls(1)
self.assertRaises(ValueError, lambda: base.replace(hour=24))
2022-01-24 18:32:33 +08:00
self.assertRaises(
ValueError, lambda: base.replace(minute=-2)
) # minute=-1 indicates default; changed to -2 for test
self.assertRaises(ValueError, lambda: base.replace(second=100))
self.assertRaises(ValueError, lambda: base.replace(microsecond=1000000))
2022-01-24 18:32:33 +08:00
case_td = TestTimeDelta()
case_td.test_computations()
case_td.test_constructor()
Typechecker refactoring (#20) * Initial refactor commit * Support external vars * Simplify refactor; Python scoping [wip] * Python scoping [wip] * Python scoping [fix loops; wip] * Fix lambdas * Python scoping [test fixes; wip] * Fix scoping [wip] * Fix basic tests [no-ci] * Fix tests * CallExpr refactoring [wip] * CallExpr refactoring [wip] * Remove activeUnbounds tracking * Add core.codon * Move Function and other core types to core.codon; Revamp Function and Callable types * Refactor IntExpr, FloatExpr and CallExpr * Refactor ClassStmt * Refactor context, IdExpr and DotExpr * Refactor DotExpr and AssignStmt * Refactor ImportStmt * Refactor FunctionStmt * Refactor * Remove UpdateStmt * Refactor AssignReplacementVisitor * Make SimplifyVisitor in-place * Fix new scoping * Fix import type alias handling * Add docstrings; Complete Simplify refactoring * Fixes for seqtest * Refactor typecheck [wip] * Refactor typecheck [wip] * Refactor typecheck/access; Remove void anduse NoneType; Fix #18 * Refactor typecheck/assign * clang-format and cmake-format * Fix none types in IR * Multi-error support in simplify * Fix IR tests for new void * Simplify ClassStmt * Refactor cond.cpp * Refactor error.cpp * Refactor function.cpp and simplify unbounds * Refactor op.cpp * Refactor call.cpp [wip] [no-ci] * seqassertn updates [noci] * Refactor call.cpp * Refactor call.cpp * Refactor call.cpp * Refactor typecheck * clang-tidy updates [noci] * Refactor infer.cpp [wip] * Refactor infer.cpp * Refactor wrapExpr * Remove visitedAsts * Remove old base logic * Refactor typecheck ctx * Fix JIT bug * Fix JIT tests * Scoping fixes [wip] [noci] * Fix ImperativeForFlow var store * Add newlines [noci] * Dump IR module with log flag * Fix scoping bugs; Add &, ^ and | static operations; Address stylistic review issues * Fix side effect analysis for for-loops * Add support for class variables and ClassVar * Refactor special dot-member cases * Add codon app tests * Fix class variables; clang-tidy * Fix __argv__ * Add datetime constants and update tests * Fix #25; Add Py_None, Py_True and Py_False; External var support [wip] * External var support [wip] * Dump LLVM IR when debug flags are active * clang-format * Fix arg var construction * Extern var fixes * Undo extern var changes related to stdout etc. * Fix tuple magics * Fix extern vars and tuple magics * Fix duplicate var name error * Fix extern vars * Fix #16 * Fix side-effect analysis for try-catch * Move test C var to test executable * Add staticmethod * Fix var status for try-catch * Fix tests * Fix shell var name * Fix test * Fix app test * Fix scoping issue (remove dominated identifier from stack) * Fix no-pie issue * Use PIC when building library object * Don't use -no-pie when building library [noci] * Use -relocation-model=pic in test * Fix lib build on Linux * Fix lib build * Update exceptions to use subclasses vs. header * Fix __repr__ * Fix tests * Fix exceptions test * Don't build docs Co-authored-by: A. R. Shajii <ars@ars.me>
2022-07-27 04:06:00 +08:00
case_td.test_resolution_info()
case_td.test_basic_attributes()
case_td.test_total_seconds()
case_td.test_carries()
case_td.test_hash_equality()
case_td.test_compare()
case_td.test_str()
case_td.test_repr()
case_td.test_microsecond_rounding()
case_td.test_massive_normalization()
case_td.test_bool()
case_td.test_division()
case_td.test_remainder()
case_td.test_divmod()
case_do = TestDateOnly()
case_do.test_delta_non_days_ignored()
case_dx = TestDate[date]()
case_dx.test_basic_attributes()
case_dx.test_ordinal_conversions()
# case_dx.test_extreme_ordinals()
case_dx.test_bad_constructor_arguments()
case_dx.test_hash_equality()
case_dx.test_computations()
case_dx.test_fromtimestamp()
case_dx.test_today()
case_dx.test_weekday()
case_dx.test_isocalendar()
case_dx.test_iso_long_years()
case_dx.test_isoformat()
case_dx.test_ctime()
case_dx.test_timetuple()
case_dx.test_compare()
case_dx.test_replace()
case_dx.test_fromisoformat()
case_dx.test_fromisoformat_fails()
case_dx.test_fromisocalendar()
case_dx.test_fromisocalendar_value_errors()
case_dt = TestDateTime[datetime]()
case_dt.test_ordinal_conversions()
case_dt.test_today()
case_dt.test_weekday()
case_dt.test_isocalendar()
case_dt.test_iso_long_years()
case_dt.test_ctime()
case_dt.test_timetuple()
case_dt.test_compare()
case_dt.test_fromisoformat()
case_dt.test_fromisoformat_fails()
case_dt.test_fromisocalendar_value_errors()
# ---
case_dt.test_basic_attributes()
case_dt.test_basic_attributes_nonzero()
case_dt.test_isoformat()
# case_dt.test_more_ctime()
case_dt.test_tz_independent_comparing()
case_dt.test_bad_constructor_arguments()
case_dt.test_hash_equality()
case_dt.test_computations()
case_dt.test_more_compare()
case_dt.test_fromtimestamp()
2022-01-24 18:32:33 +08:00
# case_dt.test_utcfromtimestamp()
case_dt.test_timestamp_naive()
# case_dt.test_microsecond_rounding()
# case_dt.test_timestamp_limits()
case_dt.test_negative_float_fromtimestamp()
# case_dt.test_negative_float_utcfromtimestamp()
case_dt.test_utcnow()
case_dt.test_extract()
case_dt.test_combine()
case_dt.test_replace()
case_dt.test_fromisoformat_datetime()
case_dt.test_fromisoformat_separators()
case_dt.test_fromisoformat_ambiguous()
case_dt.test_fromisoformat_timespecs()
case_dt.test_fromisoformat_fails_datetime()
case_tx = TestTime()
case_tx.test_basic_attributes()
case_tx.test_basic_attributes_nonzero()
case_tx.test_comparing()
case_tx.test_bad_constructor_arguments()
case_tx.test_hash_equality()
case_tx.test_isoformat()
case_tx.test_str()
case_tx.test_repr()
Typechecker refactoring (#20) * Initial refactor commit * Support external vars * Simplify refactor; Python scoping [wip] * Python scoping [wip] * Python scoping [fix loops; wip] * Fix lambdas * Python scoping [test fixes; wip] * Fix scoping [wip] * Fix basic tests [no-ci] * Fix tests * CallExpr refactoring [wip] * CallExpr refactoring [wip] * Remove activeUnbounds tracking * Add core.codon * Move Function and other core types to core.codon; Revamp Function and Callable types * Refactor IntExpr, FloatExpr and CallExpr * Refactor ClassStmt * Refactor context, IdExpr and DotExpr * Refactor DotExpr and AssignStmt * Refactor ImportStmt * Refactor FunctionStmt * Refactor * Remove UpdateStmt * Refactor AssignReplacementVisitor * Make SimplifyVisitor in-place * Fix new scoping * Fix import type alias handling * Add docstrings; Complete Simplify refactoring * Fixes for seqtest * Refactor typecheck [wip] * Refactor typecheck [wip] * Refactor typecheck/access; Remove void anduse NoneType; Fix #18 * Refactor typecheck/assign * clang-format and cmake-format * Fix none types in IR * Multi-error support in simplify * Fix IR tests for new void * Simplify ClassStmt * Refactor cond.cpp * Refactor error.cpp * Refactor function.cpp and simplify unbounds * Refactor op.cpp * Refactor call.cpp [wip] [no-ci] * seqassertn updates [noci] * Refactor call.cpp * Refactor call.cpp * Refactor call.cpp * Refactor typecheck * clang-tidy updates [noci] * Refactor infer.cpp [wip] * Refactor infer.cpp * Refactor wrapExpr * Remove visitedAsts * Remove old base logic * Refactor typecheck ctx * Fix JIT bug * Fix JIT tests * Scoping fixes [wip] [noci] * Fix ImperativeForFlow var store * Add newlines [noci] * Dump IR module with log flag * Fix scoping bugs; Add &, ^ and | static operations; Address stylistic review issues * Fix side effect analysis for for-loops * Add support for class variables and ClassVar * Refactor special dot-member cases * Add codon app tests * Fix class variables; clang-tidy * Fix __argv__ * Add datetime constants and update tests * Fix #25; Add Py_None, Py_True and Py_False; External var support [wip] * External var support [wip] * Dump LLVM IR when debug flags are active * clang-format * Fix arg var construction * Extern var fixes * Undo extern var changes related to stdout etc. * Fix tuple magics * Fix extern vars and tuple magics * Fix duplicate var name error * Fix extern vars * Fix #16 * Fix side-effect analysis for try-catch * Move test C var to test executable * Add staticmethod * Fix var status for try-catch * Fix tests * Fix shell var name * Fix test * Fix app test * Fix scoping issue (remove dominated identifier from stack) * Fix no-pie issue * Use PIC when building library object * Don't use -no-pie when building library [noci] * Use -relocation-model=pic in test * Fix lib build on Linux * Fix lib build * Update exceptions to use subclasses vs. header * Fix __repr__ * Fix tests * Fix exceptions test * Don't build docs Co-authored-by: A. R. Shajii <ars@ars.me>
2022-07-27 04:06:00 +08:00
case_tx.test_resolution_info()
case_tx.test_bool()
case_tx.test_replace()
Typechecker refactoring (#20) * Initial refactor commit * Support external vars * Simplify refactor; Python scoping [wip] * Python scoping [wip] * Python scoping [fix loops; wip] * Fix lambdas * Python scoping [test fixes; wip] * Fix scoping [wip] * Fix basic tests [no-ci] * Fix tests * CallExpr refactoring [wip] * CallExpr refactoring [wip] * Remove activeUnbounds tracking * Add core.codon * Move Function and other core types to core.codon; Revamp Function and Callable types * Refactor IntExpr, FloatExpr and CallExpr * Refactor ClassStmt * Refactor context, IdExpr and DotExpr * Refactor DotExpr and AssignStmt * Refactor ImportStmt * Refactor FunctionStmt * Refactor * Remove UpdateStmt * Refactor AssignReplacementVisitor * Make SimplifyVisitor in-place * Fix new scoping * Fix import type alias handling * Add docstrings; Complete Simplify refactoring * Fixes for seqtest * Refactor typecheck [wip] * Refactor typecheck [wip] * Refactor typecheck/access; Remove void anduse NoneType; Fix #18 * Refactor typecheck/assign * clang-format and cmake-format * Fix none types in IR * Multi-error support in simplify * Fix IR tests for new void * Simplify ClassStmt * Refactor cond.cpp * Refactor error.cpp * Refactor function.cpp and simplify unbounds * Refactor op.cpp * Refactor call.cpp [wip] [no-ci] * seqassertn updates [noci] * Refactor call.cpp * Refactor call.cpp * Refactor call.cpp * Refactor typecheck * clang-tidy updates [noci] * Refactor infer.cpp [wip] * Refactor infer.cpp * Refactor wrapExpr * Remove visitedAsts * Remove old base logic * Refactor typecheck ctx * Fix JIT bug * Fix JIT tests * Scoping fixes [wip] [noci] * Fix ImperativeForFlow var store * Add newlines [noci] * Dump IR module with log flag * Fix scoping bugs; Add &, ^ and | static operations; Address stylistic review issues * Fix side effect analysis for for-loops * Add support for class variables and ClassVar * Refactor special dot-member cases * Add codon app tests * Fix class variables; clang-tidy * Fix __argv__ * Add datetime constants and update tests * Fix #25; Add Py_None, Py_True and Py_False; External var support [wip] * External var support [wip] * Dump LLVM IR when debug flags are active * clang-format * Fix arg var construction * Extern var fixes * Undo extern var changes related to stdout etc. * Fix tuple magics * Fix extern vars and tuple magics * Fix duplicate var name error * Fix extern vars * Fix #16 * Fix side-effect analysis for try-catch * Move test C var to test executable * Add staticmethod * Fix var status for try-catch * Fix tests * Fix shell var name * Fix test * Fix app test * Fix scoping issue (remove dominated identifier from stack) * Fix no-pie issue * Use PIC when building library object * Don't use -no-pie when building library [noci] * Use -relocation-model=pic in test * Fix lib build on Linux * Fix lib build * Update exceptions to use subclasses vs. header * Fix __repr__ * Fix tests * Fix exceptions test * Don't build docs Co-authored-by: A. R. Shajii <ars@ars.me>
2022-07-27 04:06:00 +08:00
@test
def test_constants():
assert str(timedelta.min) == '-106751992 days, 19:59:05.224192' # note: diff w/ Python
assert str(timedelta.max) == '106751991 days, 4:00:54.775807' # note: diff w/ Python
assert str(timedelta.resolution) == '0:00:00.000001'
assert str(date.min) == '0001-01-01'
assert str(date.max) == '9999-12-31'
assert str(date.resolution) == '1 day, 0:00:00'
assert str(time.min) == '00:00:00'
assert str(time.max) == '23:59:59.999999'
assert str(time.resolution) == '0:00:00.000001'
assert str(datetime.min) == '0001-01-01 00:00:00'
assert str(datetime.max) == '9999-12-31 23:59:59.999999'
assert str(datetime.resolution) == '0:00:00.000001'
test_constants()