图片解析应用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

838 lines
29 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright (c) 2021, Brandon Nielsen
  3. # All rights reserved.
  4. #
  5. # This software may be modified and distributed under the terms
  6. # of the BSD license. See the LICENSE file for details.
  7. import unittest
  8. import aniso8601
  9. from aniso8601.builders import (
  10. BaseTimeBuilder,
  11. DatetimeTuple,
  12. DateTuple,
  13. DurationTuple,
  14. IntervalTuple,
  15. RepeatingIntervalTuple,
  16. TimeTuple,
  17. TimezoneTuple,
  18. TupleBuilder,
  19. cast,
  20. )
  21. from aniso8601.exceptions import (
  22. DayOutOfBoundsError,
  23. HoursOutOfBoundsError,
  24. ISOFormatError,
  25. LeapSecondError,
  26. MidnightBoundsError,
  27. MinutesOutOfBoundsError,
  28. MonthOutOfBoundsError,
  29. SecondsOutOfBoundsError,
  30. WeekOutOfBoundsError,
  31. )
  32. from aniso8601.tests.compat import mock
  33. class LeapSecondSupportingTestBuilder(BaseTimeBuilder):
  34. LEAP_SECONDS_SUPPORTED = True
  35. class TestBuilderFunctions(unittest.TestCase):
  36. def test_cast(self):
  37. self.assertEqual(cast("1", int), 1)
  38. self.assertEqual(cast("-2", int), -2)
  39. self.assertEqual(cast("3", float), float(3))
  40. self.assertEqual(cast("-4", float), float(-4))
  41. self.assertEqual(cast("5.6", float), 5.6)
  42. self.assertEqual(cast("-7.8", float), -7.8)
  43. def test_cast_exception(self):
  44. with self.assertRaises(ISOFormatError):
  45. cast("asdf", int)
  46. with self.assertRaises(ISOFormatError):
  47. cast("asdf", float)
  48. def test_cast_caughtexception(self):
  49. def tester(value):
  50. raise RuntimeError
  51. with self.assertRaises(ISOFormatError):
  52. cast("asdf", tester, caughtexceptions=(RuntimeError,))
  53. def test_cast_thrownexception(self):
  54. with self.assertRaises(RuntimeError):
  55. cast("asdf", int, thrownexception=RuntimeError)
  56. class TestBaseTimeBuilder(unittest.TestCase):
  57. def test_build_date(self):
  58. with self.assertRaises(NotImplementedError):
  59. BaseTimeBuilder.build_date()
  60. def test_build_time(self):
  61. with self.assertRaises(NotImplementedError):
  62. BaseTimeBuilder.build_time()
  63. def test_build_datetime(self):
  64. with self.assertRaises(NotImplementedError):
  65. BaseTimeBuilder.build_datetime(None, None)
  66. def test_build_duration(self):
  67. with self.assertRaises(NotImplementedError):
  68. BaseTimeBuilder.build_duration()
  69. def test_build_interval(self):
  70. with self.assertRaises(NotImplementedError):
  71. BaseTimeBuilder.build_interval()
  72. def test_build_repeating_interval(self):
  73. with self.assertRaises(NotImplementedError):
  74. BaseTimeBuilder.build_repeating_interval()
  75. def test_build_timezone(self):
  76. with self.assertRaises(NotImplementedError):
  77. BaseTimeBuilder.build_timezone()
  78. def test_range_check_date(self):
  79. # Check the calendar for day ranges
  80. with self.assertRaises(DayOutOfBoundsError):
  81. BaseTimeBuilder.range_check_date(YYYY="0007", MM="02", DD="30")
  82. with self.assertRaises(DayOutOfBoundsError):
  83. BaseTimeBuilder.range_check_date(YYYY="0007", DDD="366")
  84. with self.assertRaises(MonthOutOfBoundsError):
  85. BaseTimeBuilder.range_check_date(YYYY="4333", MM="30", DD="30")
  86. # 0 isn't a valid week number
  87. with self.assertRaises(WeekOutOfBoundsError):
  88. BaseTimeBuilder.range_check_date(YYYY="2003", Www="00")
  89. # Week must not be larger than 53
  90. with self.assertRaises(WeekOutOfBoundsError):
  91. BaseTimeBuilder.range_check_date(YYYY="2004", Www="54")
  92. # 0 isn't a valid day number
  93. with self.assertRaises(DayOutOfBoundsError):
  94. BaseTimeBuilder.range_check_date(YYYY="2001", Www="02", D="0")
  95. # Day must not be larger than 7
  96. with self.assertRaises(DayOutOfBoundsError):
  97. BaseTimeBuilder.range_check_date(YYYY="2001", Www="02", D="8")
  98. with self.assertRaises(DayOutOfBoundsError):
  99. BaseTimeBuilder.range_check_date(YYYY="1981", DDD="000")
  100. # Day must be 365, or 366, not larger
  101. with self.assertRaises(DayOutOfBoundsError):
  102. BaseTimeBuilder.range_check_date(YYYY="1234", DDD="000")
  103. with self.assertRaises(DayOutOfBoundsError):
  104. BaseTimeBuilder.range_check_date(YYYY="1234", DDD="367")
  105. # https://bitbucket.org/nielsenb/aniso8601/issues/14/parsing-ordinal-dates-should-only-allow
  106. with self.assertRaises(DayOutOfBoundsError):
  107. BaseTimeBuilder.range_check_date(YYYY="1981", DDD="366")
  108. # Make sure Nones pass through unmodified
  109. self.assertEqual(
  110. BaseTimeBuilder.range_check_date(rangedict={}),
  111. (None, None, None, None, None, None),
  112. )
  113. def test_range_check_time(self):
  114. # Leap seconds not supported
  115. # https://bitbucket.org/nielsenb/aniso8601/issues/10/sub-microsecond-precision-in-durations-is
  116. # https://bitbucket.org/nielsenb/aniso8601/issues/13/parsing-of-leap-second-gives-wildly
  117. with self.assertRaises(LeapSecondError):
  118. BaseTimeBuilder.range_check_time(hh="23", mm="59", ss="60")
  119. with self.assertRaises(SecondsOutOfBoundsError):
  120. BaseTimeBuilder.range_check_time(hh="00", mm="00", ss="60")
  121. with self.assertRaises(SecondsOutOfBoundsError):
  122. BaseTimeBuilder.range_check_time(hh="00", mm="00", ss="61")
  123. with self.assertRaises(MinutesOutOfBoundsError):
  124. BaseTimeBuilder.range_check_time(hh="00", mm="61")
  125. with self.assertRaises(MinutesOutOfBoundsError):
  126. BaseTimeBuilder.range_check_time(hh="00", mm="60")
  127. with self.assertRaises(MinutesOutOfBoundsError):
  128. BaseTimeBuilder.range_check_time(hh="00", mm="60.1")
  129. with self.assertRaises(HoursOutOfBoundsError):
  130. BaseTimeBuilder.range_check_time(hh="25")
  131. # Hour 24 can only represent midnight
  132. with self.assertRaises(MidnightBoundsError):
  133. BaseTimeBuilder.range_check_time(hh="24", mm="00", ss="01")
  134. with self.assertRaises(MidnightBoundsError):
  135. BaseTimeBuilder.range_check_time(hh="24", mm="00.1")
  136. with self.assertRaises(MidnightBoundsError):
  137. BaseTimeBuilder.range_check_time(hh="24", mm="01")
  138. with self.assertRaises(MidnightBoundsError):
  139. BaseTimeBuilder.range_check_time(hh="24.1")
  140. # Leap seconds not supported
  141. # https://bitbucket.org/nielsenb/aniso8601/issues/10/sub-microsecond-precision-in-durations-is
  142. # https://bitbucket.org/nielsenb/aniso8601/issues/13/parsing-of-leap-second-gives-wildly
  143. with self.assertRaises(LeapSecondError):
  144. BaseTimeBuilder.range_check_time(hh="23", mm="59", ss="60")
  145. # Make sure Nones pass through unmodified
  146. self.assertEqual(
  147. BaseTimeBuilder.range_check_time(rangedict={}), (None, None, None, None)
  148. )
  149. def test_range_check_time_leap_seconds_supported(self):
  150. self.assertEqual(
  151. LeapSecondSupportingTestBuilder.range_check_time(hh="23", mm="59", ss="60"),
  152. (23, 59, 60, None),
  153. )
  154. with self.assertRaises(SecondsOutOfBoundsError):
  155. LeapSecondSupportingTestBuilder.range_check_time(hh="01", mm="02", ss="60")
  156. def test_range_check_duration(self):
  157. self.assertEqual(
  158. BaseTimeBuilder.range_check_duration(),
  159. (None, None, None, None, None, None, None),
  160. )
  161. self.assertEqual(
  162. BaseTimeBuilder.range_check_duration(rangedict={}),
  163. (None, None, None, None, None, None, None),
  164. )
  165. def test_range_check_repeating_interval(self):
  166. self.assertEqual(
  167. BaseTimeBuilder.range_check_repeating_interval(), (None, None, None)
  168. )
  169. self.assertEqual(
  170. BaseTimeBuilder.range_check_repeating_interval(rangedict={}),
  171. (None, None, None),
  172. )
  173. def test_range_check_timezone(self):
  174. self.assertEqual(
  175. BaseTimeBuilder.range_check_timezone(), (None, None, None, None, "")
  176. )
  177. self.assertEqual(
  178. BaseTimeBuilder.range_check_timezone(rangedict={}),
  179. (None, None, None, None, ""),
  180. )
  181. def test_build_object(self):
  182. datetest = (
  183. DateTuple("1", "2", "3", "4", "5", "6"),
  184. {"YYYY": "1", "MM": "2", "DD": "3", "Www": "4", "D": "5", "DDD": "6"},
  185. )
  186. timetest = (
  187. TimeTuple("1", "2", "3", TimezoneTuple(False, False, "4", "5", "tz name")),
  188. {
  189. "hh": "1",
  190. "mm": "2",
  191. "ss": "3",
  192. "tz": TimezoneTuple(False, False, "4", "5", "tz name"),
  193. },
  194. )
  195. datetimetest = (
  196. DatetimeTuple(
  197. DateTuple("1", "2", "3", "4", "5", "6"),
  198. TimeTuple(
  199. "7", "8", "9", TimezoneTuple(True, False, "10", "11", "tz name")
  200. ),
  201. ),
  202. (
  203. DateTuple("1", "2", "3", "4", "5", "6"),
  204. TimeTuple(
  205. "7", "8", "9", TimezoneTuple(True, False, "10", "11", "tz name")
  206. ),
  207. ),
  208. )
  209. durationtest = (
  210. DurationTuple("1", "2", "3", "4", "5", "6", "7"),
  211. {
  212. "PnY": "1",
  213. "PnM": "2",
  214. "PnW": "3",
  215. "PnD": "4",
  216. "TnH": "5",
  217. "TnM": "6",
  218. "TnS": "7",
  219. },
  220. )
  221. intervaltests = (
  222. (
  223. IntervalTuple(
  224. DateTuple("1", "2", "3", "4", "5", "6"),
  225. DateTuple("7", "8", "9", "10", "11", "12"),
  226. None,
  227. ),
  228. {
  229. "start": DateTuple("1", "2", "3", "4", "5", "6"),
  230. "end": DateTuple("7", "8", "9", "10", "11", "12"),
  231. "duration": None,
  232. },
  233. ),
  234. (
  235. IntervalTuple(
  236. DateTuple("1", "2", "3", "4", "5", "6"),
  237. None,
  238. DurationTuple("7", "8", "9", "10", "11", "12", "13"),
  239. ),
  240. {
  241. "start": DateTuple("1", "2", "3", "4", "5", "6"),
  242. "end": None,
  243. "duration": DurationTuple("7", "8", "9", "10", "11", "12", "13"),
  244. },
  245. ),
  246. (
  247. IntervalTuple(
  248. None,
  249. TimeTuple(
  250. "1", "2", "3", TimezoneTuple(True, False, "4", "5", "tz name")
  251. ),
  252. DurationTuple("6", "7", "8", "9", "10", "11", "12"),
  253. ),
  254. {
  255. "start": None,
  256. "end": TimeTuple(
  257. "1", "2", "3", TimezoneTuple(True, False, "4", "5", "tz name")
  258. ),
  259. "duration": DurationTuple("6", "7", "8", "9", "10", "11", "12"),
  260. },
  261. ),
  262. )
  263. repeatingintervaltests = (
  264. (
  265. RepeatingIntervalTuple(
  266. True,
  267. None,
  268. IntervalTuple(
  269. DateTuple("1", "2", "3", "4", "5", "6"),
  270. DateTuple("7", "8", "9", "10", "11", "12"),
  271. None,
  272. ),
  273. ),
  274. {
  275. "R": True,
  276. "Rnn": None,
  277. "interval": IntervalTuple(
  278. DateTuple("1", "2", "3", "4", "5", "6"),
  279. DateTuple("7", "8", "9", "10", "11", "12"),
  280. None,
  281. ),
  282. },
  283. ),
  284. (
  285. RepeatingIntervalTuple(
  286. False,
  287. "1",
  288. IntervalTuple(
  289. DatetimeTuple(
  290. DateTuple("2", "3", "4", "5", "6", "7"),
  291. TimeTuple("8", "9", "10", None),
  292. ),
  293. DatetimeTuple(
  294. DateTuple("11", "12", "13", "14", "15", "16"),
  295. TimeTuple("17", "18", "19", None),
  296. ),
  297. None,
  298. ),
  299. ),
  300. {
  301. "R": False,
  302. "Rnn": "1",
  303. "interval": IntervalTuple(
  304. DatetimeTuple(
  305. DateTuple("2", "3", "4", "5", "6", "7"),
  306. TimeTuple("8", "9", "10", None),
  307. ),
  308. DatetimeTuple(
  309. DateTuple("11", "12", "13", "14", "15", "16"),
  310. TimeTuple("17", "18", "19", None),
  311. ),
  312. None,
  313. ),
  314. },
  315. ),
  316. )
  317. timezonetest = (
  318. TimezoneTuple(False, False, "1", "2", "+01:02"),
  319. {"negative": False, "Z": False, "hh": "1", "mm": "2", "name": "+01:02"},
  320. )
  321. with mock.patch.object(
  322. aniso8601.builders.BaseTimeBuilder, "build_date"
  323. ) as mock_build:
  324. mock_build.return_value = datetest[0]
  325. result = BaseTimeBuilder._build_object(datetest[0])
  326. self.assertEqual(result, datetest[0])
  327. mock_build.assert_called_once_with(**datetest[1])
  328. with mock.patch.object(
  329. aniso8601.builders.BaseTimeBuilder, "build_time"
  330. ) as mock_build:
  331. mock_build.return_value = timetest[0]
  332. result = BaseTimeBuilder._build_object(timetest[0])
  333. self.assertEqual(result, timetest[0])
  334. mock_build.assert_called_once_with(**timetest[1])
  335. with mock.patch.object(
  336. aniso8601.builders.BaseTimeBuilder, "build_datetime"
  337. ) as mock_build:
  338. mock_build.return_value = datetimetest[0]
  339. result = BaseTimeBuilder._build_object(datetimetest[0])
  340. self.assertEqual(result, datetimetest[0])
  341. mock_build.assert_called_once_with(*datetimetest[1])
  342. with mock.patch.object(
  343. aniso8601.builders.BaseTimeBuilder, "build_duration"
  344. ) as mock_build:
  345. mock_build.return_value = durationtest[0]
  346. result = BaseTimeBuilder._build_object(durationtest[0])
  347. self.assertEqual(result, durationtest[0])
  348. mock_build.assert_called_once_with(**durationtest[1])
  349. for intervaltest in intervaltests:
  350. with mock.patch.object(
  351. aniso8601.builders.BaseTimeBuilder, "build_interval"
  352. ) as mock_build:
  353. mock_build.return_value = intervaltest[0]
  354. result = BaseTimeBuilder._build_object(intervaltest[0])
  355. self.assertEqual(result, intervaltest[0])
  356. mock_build.assert_called_once_with(**intervaltest[1])
  357. for repeatingintervaltest in repeatingintervaltests:
  358. with mock.patch.object(
  359. aniso8601.builders.BaseTimeBuilder, "build_repeating_interval"
  360. ) as mock_build:
  361. mock_build.return_value = repeatingintervaltest[0]
  362. result = BaseTimeBuilder._build_object(repeatingintervaltest[0])
  363. self.assertEqual(result, repeatingintervaltest[0])
  364. mock_build.assert_called_once_with(**repeatingintervaltest[1])
  365. with mock.patch.object(
  366. aniso8601.builders.BaseTimeBuilder, "build_timezone"
  367. ) as mock_build:
  368. mock_build.return_value = timezonetest[0]
  369. result = BaseTimeBuilder._build_object(timezonetest[0])
  370. self.assertEqual(result, timezonetest[0])
  371. mock_build.assert_called_once_with(**timezonetest[1])
  372. def test_is_interval_end_concise(self):
  373. self.assertTrue(
  374. BaseTimeBuilder._is_interval_end_concise(TimeTuple("1", "2", "3", None))
  375. )
  376. self.assertTrue(
  377. BaseTimeBuilder._is_interval_end_concise(
  378. DateTuple(None, "2", "3", "4", "5", "6")
  379. )
  380. )
  381. self.assertTrue(
  382. BaseTimeBuilder._is_interval_end_concise(
  383. DatetimeTuple(
  384. DateTuple(None, "2", "3", "4", "5", "6"),
  385. TimeTuple("7", "8", "9", None),
  386. )
  387. )
  388. )
  389. self.assertFalse(
  390. BaseTimeBuilder._is_interval_end_concise(
  391. DateTuple("1", "2", "3", "4", "5", "6")
  392. )
  393. )
  394. self.assertFalse(
  395. BaseTimeBuilder._is_interval_end_concise(
  396. DatetimeTuple(
  397. DateTuple("1", "2", "3", "4", "5", "6"),
  398. TimeTuple("7", "8", "9", None),
  399. )
  400. )
  401. )
  402. def test_combine_concise_interval_tuples(self):
  403. testtuples = (
  404. (
  405. DateTuple("2020", "01", "01", None, None, None),
  406. DateTuple(None, None, "02", None, None, None),
  407. DateTuple("2020", "01", "02", None, None, None),
  408. ),
  409. (
  410. DateTuple("2008", "02", "15", None, None, None),
  411. DateTuple(None, "03", "14", None, None, None),
  412. DateTuple("2008", "03", "14", None, None, None),
  413. ),
  414. (
  415. DatetimeTuple(
  416. DateTuple("2007", "12", "14", None, None, None),
  417. TimeTuple("13", "30", None, None),
  418. ),
  419. TimeTuple("15", "30", None, None),
  420. DatetimeTuple(
  421. DateTuple("2007", "12", "14", None, None, None),
  422. TimeTuple("15", "30", None, None),
  423. ),
  424. ),
  425. (
  426. DatetimeTuple(
  427. DateTuple("2007", "11", "13", None, None, None),
  428. TimeTuple("09", "00", None, None),
  429. ),
  430. DatetimeTuple(
  431. DateTuple(None, None, "15", None, None, None),
  432. TimeTuple("17", "00", None, None),
  433. ),
  434. DatetimeTuple(
  435. DateTuple("2007", "11", "15", None, None, None),
  436. TimeTuple("17", "00", None, None),
  437. ),
  438. ),
  439. (
  440. DatetimeTuple(
  441. DateTuple("2007", "11", "13", None, None, None),
  442. TimeTuple("00", "00", None, None),
  443. ),
  444. DatetimeTuple(
  445. DateTuple(None, None, "16", None, None, None),
  446. TimeTuple("00", "00", None, None),
  447. ),
  448. DatetimeTuple(
  449. DateTuple("2007", "11", "16", None, None, None),
  450. TimeTuple("00", "00", None, None),
  451. ),
  452. ),
  453. (
  454. DatetimeTuple(
  455. DateTuple("2007", "11", "13", None, None, None),
  456. TimeTuple(
  457. "09", "00", None, TimezoneTuple(False, True, None, None, "Z")
  458. ),
  459. ),
  460. DatetimeTuple(
  461. DateTuple(None, None, "15", None, None, None),
  462. TimeTuple("17", "00", None, None),
  463. ),
  464. DatetimeTuple(
  465. DateTuple("2007", "11", "15", None, None, None),
  466. TimeTuple(
  467. "17", "00", None, TimezoneTuple(False, True, None, None, "Z")
  468. ),
  469. ),
  470. ),
  471. )
  472. for testtuple in testtuples:
  473. result = BaseTimeBuilder._combine_concise_interval_tuples(
  474. testtuple[0], testtuple[1]
  475. )
  476. self.assertEqual(result, testtuple[2])
  477. class TestTupleBuilder(unittest.TestCase):
  478. def test_build_date(self):
  479. datetuple = TupleBuilder.build_date()
  480. self.assertEqual(datetuple, DateTuple(None, None, None, None, None, None))
  481. datetuple = TupleBuilder.build_date(
  482. YYYY="1", MM="2", DD="3", Www="4", D="5", DDD="6"
  483. )
  484. self.assertEqual(datetuple, DateTuple("1", "2", "3", "4", "5", "6"))
  485. def test_build_time(self):
  486. testtuples = (
  487. ({}, TimeTuple(None, None, None, None)),
  488. (
  489. {"hh": "1", "mm": "2", "ss": "3", "tz": None},
  490. TimeTuple("1", "2", "3", None),
  491. ),
  492. (
  493. {
  494. "hh": "1",
  495. "mm": "2",
  496. "ss": "3",
  497. "tz": TimezoneTuple(False, False, "4", "5", "tz name"),
  498. },
  499. TimeTuple(
  500. "1", "2", "3", TimezoneTuple(False, False, "4", "5", "tz name")
  501. ),
  502. ),
  503. )
  504. for testtuple in testtuples:
  505. self.assertEqual(TupleBuilder.build_time(**testtuple[0]), testtuple[1])
  506. def test_build_datetime(self):
  507. testtuples = (
  508. (
  509. {
  510. "date": DateTuple("1", "2", "3", "4", "5", "6"),
  511. "time": TimeTuple("7", "8", "9", None),
  512. },
  513. DatetimeTuple(
  514. DateTuple("1", "2", "3", "4", "5", "6"),
  515. TimeTuple("7", "8", "9", None),
  516. ),
  517. ),
  518. (
  519. {
  520. "date": DateTuple("1", "2", "3", "4", "5", "6"),
  521. "time": TimeTuple(
  522. "7", "8", "9", TimezoneTuple(True, False, "10", "11", "tz name")
  523. ),
  524. },
  525. DatetimeTuple(
  526. DateTuple("1", "2", "3", "4", "5", "6"),
  527. TimeTuple(
  528. "7", "8", "9", TimezoneTuple(True, False, "10", "11", "tz name")
  529. ),
  530. ),
  531. ),
  532. )
  533. for testtuple in testtuples:
  534. self.assertEqual(TupleBuilder.build_datetime(**testtuple[0]), testtuple[1])
  535. def test_build_duration(self):
  536. testtuples = (
  537. ({}, DurationTuple(None, None, None, None, None, None, None)),
  538. (
  539. {
  540. "PnY": "1",
  541. "PnM": "2",
  542. "PnW": "3",
  543. "PnD": "4",
  544. "TnH": "5",
  545. "TnM": "6",
  546. "TnS": "7",
  547. },
  548. DurationTuple("1", "2", "3", "4", "5", "6", "7"),
  549. ),
  550. )
  551. for testtuple in testtuples:
  552. self.assertEqual(TupleBuilder.build_duration(**testtuple[0]), testtuple[1])
  553. def test_build_interval(self):
  554. testtuples = (
  555. ({}, IntervalTuple(None, None, None)),
  556. (
  557. {
  558. "start": DateTuple("1", "2", "3", "4", "5", "6"),
  559. "end": DateTuple("7", "8", "9", "10", "11", "12"),
  560. },
  561. IntervalTuple(
  562. DateTuple("1", "2", "3", "4", "5", "6"),
  563. DateTuple("7", "8", "9", "10", "11", "12"),
  564. None,
  565. ),
  566. ),
  567. (
  568. {
  569. "start": TimeTuple(
  570. "1", "2", "3", TimezoneTuple(True, False, "7", "8", "tz name")
  571. ),
  572. "end": TimeTuple(
  573. "4", "5", "6", TimezoneTuple(False, False, "9", "10", "tz name")
  574. ),
  575. },
  576. IntervalTuple(
  577. TimeTuple(
  578. "1", "2", "3", TimezoneTuple(True, False, "7", "8", "tz name")
  579. ),
  580. TimeTuple(
  581. "4", "5", "6", TimezoneTuple(False, False, "9", "10", "tz name")
  582. ),
  583. None,
  584. ),
  585. ),
  586. (
  587. {
  588. "start": DatetimeTuple(
  589. DateTuple("1", "2", "3", "4", "5", "6"),
  590. TimeTuple(
  591. "7",
  592. "8",
  593. "9",
  594. TimezoneTuple(True, False, "10", "11", "tz name"),
  595. ),
  596. ),
  597. "end": DatetimeTuple(
  598. DateTuple("12", "13", "14", "15", "16", "17"),
  599. TimeTuple(
  600. "18",
  601. "19",
  602. "20",
  603. TimezoneTuple(False, False, "21", "22", "tz name"),
  604. ),
  605. ),
  606. },
  607. IntervalTuple(
  608. DatetimeTuple(
  609. DateTuple("1", "2", "3", "4", "5", "6"),
  610. TimeTuple(
  611. "7",
  612. "8",
  613. "9",
  614. TimezoneTuple(True, False, "10", "11", "tz name"),
  615. ),
  616. ),
  617. DatetimeTuple(
  618. DateTuple("12", "13", "14", "15", "16", "17"),
  619. TimeTuple(
  620. "18",
  621. "19",
  622. "20",
  623. TimezoneTuple(False, False, "21", "22", "tz name"),
  624. ),
  625. ),
  626. None,
  627. ),
  628. ),
  629. (
  630. {
  631. "start": DateTuple("1", "2", "3", "4", "5", "6"),
  632. "end": None,
  633. "duration": DurationTuple("7", "8", "9", "10", "11", "12", "13"),
  634. },
  635. IntervalTuple(
  636. DateTuple("1", "2", "3", "4", "5", "6"),
  637. None,
  638. DurationTuple("7", "8", "9", "10", "11", "12", "13"),
  639. ),
  640. ),
  641. (
  642. {
  643. "start": None,
  644. "end": TimeTuple(
  645. "1", "2", "3", TimezoneTuple(True, False, "4", "5", "tz name")
  646. ),
  647. "duration": DurationTuple("6", "7", "8", "9", "10", "11", "12"),
  648. },
  649. IntervalTuple(
  650. None,
  651. TimeTuple(
  652. "1", "2", "3", TimezoneTuple(True, False, "4", "5", "tz name")
  653. ),
  654. DurationTuple("6", "7", "8", "9", "10", "11", "12"),
  655. ),
  656. ),
  657. )
  658. for testtuple in testtuples:
  659. self.assertEqual(TupleBuilder.build_interval(**testtuple[0]), testtuple[1])
  660. def test_build_repeating_interval(self):
  661. testtuples = (
  662. ({}, RepeatingIntervalTuple(None, None, None)),
  663. (
  664. {
  665. "R": True,
  666. "interval": IntervalTuple(
  667. DateTuple("1", "2", "3", "4", "5", "6"),
  668. DateTuple("7", "8", "9", "10", "11", "12"),
  669. None,
  670. ),
  671. },
  672. RepeatingIntervalTuple(
  673. True,
  674. None,
  675. IntervalTuple(
  676. DateTuple("1", "2", "3", "4", "5", "6"),
  677. DateTuple("7", "8", "9", "10", "11", "12"),
  678. None,
  679. ),
  680. ),
  681. ),
  682. (
  683. {
  684. "R": False,
  685. "Rnn": "1",
  686. "interval": IntervalTuple(
  687. DatetimeTuple(
  688. DateTuple("2", "3", "4", "5", "6", "7"),
  689. TimeTuple("8", "9", "10", None),
  690. ),
  691. DatetimeTuple(
  692. DateTuple("11", "12", "13", "14", "15", "16"),
  693. TimeTuple("17", "18", "19", None),
  694. ),
  695. None,
  696. ),
  697. },
  698. RepeatingIntervalTuple(
  699. False,
  700. "1",
  701. IntervalTuple(
  702. DatetimeTuple(
  703. DateTuple("2", "3", "4", "5", "6", "7"),
  704. TimeTuple("8", "9", "10", None),
  705. ),
  706. DatetimeTuple(
  707. DateTuple("11", "12", "13", "14", "15", "16"),
  708. TimeTuple("17", "18", "19", None),
  709. ),
  710. None,
  711. ),
  712. ),
  713. ),
  714. )
  715. for testtuple in testtuples:
  716. result = TupleBuilder.build_repeating_interval(**testtuple[0])
  717. self.assertEqual(result, testtuple[1])
  718. def test_build_timezone(self):
  719. testtuples = (
  720. ({}, TimezoneTuple(None, None, None, None, "")),
  721. (
  722. {"negative": False, "Z": True, "name": "UTC"},
  723. TimezoneTuple(False, True, None, None, "UTC"),
  724. ),
  725. (
  726. {"negative": False, "Z": False, "hh": "1", "mm": "2", "name": "+01:02"},
  727. TimezoneTuple(False, False, "1", "2", "+01:02"),
  728. ),
  729. (
  730. {"negative": True, "Z": False, "hh": "1", "mm": "2", "name": "-01:02"},
  731. TimezoneTuple(True, False, "1", "2", "-01:02"),
  732. ),
  733. )
  734. for testtuple in testtuples:
  735. result = TupleBuilder.build_timezone(**testtuple[0])
  736. self.assertEqual(result, testtuple[1])