/src/googlecl/calendar/date_test.py

http://googlecl.googlecode.com/ · Python · 233 lines · 167 code · 48 blank · 18 comment · 7 complexity · 0daf20b10cc2d32d2a51cb43e560a6e6 MD5 · raw file

  1. #!/usr/bin/python
  2. #
  3. # Copyright (C) 2010 Google Inc.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. """Tests for calendar dates."""
  17. __author__ = 'thmiller@google.com (Tom Miller)'
  18. import date
  19. import unittest
  20. from datetime import datetime
  21. from datetime import timedelta
  22. # If "now" changes, the ONE_DAY, edge, and trick tests
  23. # below must be changed carefully!!
  24. def static_now():
  25. return datetime(year=2010,
  26. month=10,
  27. day=22,
  28. hour=14,
  29. minute=5)
  30. def static_today():
  31. return static_now().replace(hour=0,
  32. minute=0,
  33. second=0,
  34. microsecond=0)
  35. NOW = static_now()
  36. YEAR = NOW.year
  37. ONE_DAY = timedelta(hours=24)
  38. MONTH_DAY_TESTS = {'1/1': datetime(year=YEAR+1, month=1, day=1),
  39. '12/31': datetime(year=YEAR, month=12, day=31),
  40. '10/30': datetime(year=YEAR, month=10, day=30),
  41. '2/28': datetime(year=YEAR+1, month=2, day=28),
  42. '11/1': datetime(year=YEAR, month=11, day=1)}
  43. TIME_TESTS = {'7pm': NOW.replace(hour=19, minute=0),
  44. '8am': NOW.replace(hour=8, minute=0) + ONE_DAY,
  45. '01:00': NOW.replace(hour=1, minute=0) + ONE_DAY,
  46. '14:00': NOW.replace(hour=14, minute=0) + ONE_DAY}
  47. AMBIGUOUS_TESTS = {'6': NOW.replace(hour=18, minute=0),
  48. '7:01': NOW.replace(hour=7, minute=1) + ONE_DAY,
  49. '4:59': NOW.replace(hour=16, minute=59)}
  50. FULL_DATE_TESTS = {'7/15/2011': datetime(year=2011, month=7, day=15),
  51. '4/30/2000': datetime(year=2000, month=4, day=30),
  52. '2010-06-02': datetime(year=2010, month=6, day=2),
  53. '2010-9-2': datetime(year=2010, month=9, day=2),
  54. 'March 30 2010': datetime(year=2010, month=3, day=30),
  55. 'Jan 1 1970': datetime(year=1970, month=1, day=1)}
  56. JOINED_TESTS = {'06/15/11 at 6': datetime(year=2011, day=15, month=6, hour=18),
  57. '3/4@19:00': datetime(year=YEAR+1, day=4, month=3, hour=19),
  58. '10/22/2012 @ 12:53pm': datetime(year=2012, month=10, day=22,
  59. hour=12, minute=53),
  60. 'Aug 23 2020 at 5pm': datetime(year=2020, month=8, day=23,
  61. hour=17)}
  62. EDGE_TESTS = {'10/22/2010 @ 14:05': NOW,
  63. '10/22 @ 14:04': NOW.replace(minute=4),
  64. '2:05pm': NOW,
  65. 'tomorrow at 2:04': NOW.replace(minute=4) + ONE_DAY,
  66. '10/21 at 00:00': datetime(year=YEAR+1, month=10, day=21)}
  67. TRICK_TESTS = {'today at 2': NOW.replace(minute=0),
  68. '10/22 at 2': NOW.replace(minute=0)}
  69. DURATION_TESTS = {'+3': NOW + timedelta(hours=3),
  70. '+1:20': NOW + timedelta(hours=1, minutes=20),
  71. '+:45': NOW + timedelta(minutes=45)}
  72. FAIL_TESTS = [',', '@', '115', 'notadate', '1-4']
  73. RANGE_BASE_TEXT = '11/3 @ 9pm'
  74. RANGE_EXPECTED_START = datetime(year=YEAR, month=11, day=3, hour=21)
  75. class ParsingDatesTest(unittest.TestCase):
  76. def assertConvertedEqual(self, text, expected, actual):
  77. if expected != actual:
  78. self.fail('%s was not parsed correctly (%s != %s)'
  79. % (text, expected, actual))
  80. class ParseSingleDateTest(ParsingDatesTest):
  81. def setUp(self):
  82. self.parser = date.DateParser(static_today, static_now)
  83. def runTestSet(self, test_dict):
  84. for text, expected_date in test_dict.items():
  85. parsed_date = self.parser.parse(text)
  86. self.assertConvertedEqual(text, expected_date, parsed_date.local)
  87. def testDatetimeParse(self):
  88. parsed_date = self.parser.parse('2010-01-20T13:45:00')
  89. self.assertEqual(datetime(year=2010, month=1, day=20, hour=13, minute=45),
  90. parsed_date.local)
  91. def testMonthDayParsing(self):
  92. self.runTestSet(MONTH_DAY_TESTS)
  93. def testTimeParsing(self):
  94. self.runTestSet(TIME_TESTS)
  95. def testAmbiguous(self):
  96. self.runTestSet(AMBIGUOUS_TESTS)
  97. def testFullDateParsing(self):
  98. self.runTestSet(FULL_DATE_TESTS)
  99. def testJoined(self):
  100. self.runTestSet(JOINED_TESTS)
  101. def testEdge(self):
  102. self.runTestSet(EDGE_TESTS)
  103. def testTrick(self):
  104. self.runTestSet(TRICK_TESTS)
  105. def testDuration(self):
  106. self.runTestSet(DURATION_TESTS)
  107. def testFailures(self):
  108. for text in FAIL_TESTS:
  109. try:
  110. self.parser.parse(text)
  111. except date.ParsingError, err:
  112. pass
  113. else:
  114. self.fail('Expected ParsingError for %s' % text)
  115. class ParseDateRange(ParsingDatesTest):
  116. def setUp(self):
  117. self.parser = date.DateRangeParser(static_today, static_now)
  118. def testSingleDate(self):
  119. date_range = self.parser.parse(RANGE_BASE_TEXT)
  120. self.assertConvertedEqual(RANGE_BASE_TEXT,
  121. RANGE_EXPECTED_START,
  122. date_range.start.local)
  123. self.assertEqual(date_range.end.local, RANGE_EXPECTED_START)
  124. self.assertFalse(date_range.specified_as_range)
  125. def testStartRange(self):
  126. text = RANGE_BASE_TEXT + ','
  127. date_range = self.parser.parse(text)
  128. self.assertConvertedEqual(text,
  129. RANGE_EXPECTED_START,
  130. date_range.start.local)
  131. self.assertEqual(date_range.end, None)
  132. self.assertTrue(date_range.specified_as_range)
  133. def testStartAndDurationRange(self):
  134. text = RANGE_BASE_TEXT + ',+5'
  135. date_range = self.parser.parse(text)
  136. self.assertConvertedEqual(RANGE_BASE_TEXT,
  137. RANGE_EXPECTED_START,
  138. date_range.start.local)
  139. self.assertEqual(date_range.end.local,
  140. RANGE_EXPECTED_START + timedelta(hours=5))
  141. self.assertTrue(date_range.specified_as_range)
  142. def testAllDurationRange(self):
  143. text = '+2,+3'
  144. date_range = self.parser.parse(text)
  145. self.assertEqual(date_range.start.local,
  146. NOW + timedelta(hours=2))
  147. self.assertEqual(date_range.end.local,
  148. NOW + timedelta(hours=5))
  149. self.assertTrue(date_range.specified_as_range)
  150. def testEndDurationRange(self):
  151. text = ',+3'
  152. date_range = self.parser.parse(text)
  153. self.assertEqual(date_range.start, None)
  154. self.assertEqual(date_range.end.local,
  155. NOW + timedelta(hours=3))
  156. self.assertTrue(date_range.specified_as_range)
  157. def testDurationStart(self):
  158. text = '+1' + ',' + RANGE_BASE_TEXT
  159. date_range = self.parser.parse(text)
  160. self.assertEqual(date_range.start.local, NOW + timedelta(hours=1))
  161. self.assertConvertedEqual(RANGE_BASE_TEXT,
  162. RANGE_EXPECTED_START,
  163. date_range.end.local)
  164. self.assertTrue(date_range.specified_as_range)
  165. def testStartEndRange(self):
  166. end_text = '11/29'
  167. text = RANGE_BASE_TEXT + ',' + end_text
  168. date_range = self.parser.parse(text)
  169. self.assertConvertedEqual(RANGE_BASE_TEXT,
  170. RANGE_EXPECTED_START,
  171. date_range.start.local)
  172. self.assertConvertedEqual(end_text,
  173. datetime(year=YEAR, month=11, day=29),
  174. date_range.end.local)
  175. self.assertTrue(date_range.specified_as_range)
  176. def testEndRange(self):
  177. text = ',' + RANGE_BASE_TEXT
  178. date_range = self.parser.parse(text)
  179. self.assertEqual(date_range.start, None)
  180. self.assertConvertedEqual(text,
  181. RANGE_EXPECTED_START,
  182. date_range.end.local)
  183. self.assertTrue(date_range.specified_as_range)
  184. if __name__ == '__main__':
  185. unittest.main()