10 import dateparse.dateparse_utils as du
11 import unittest_utils as uu
14 parsable_expressions = [
16 datetime.datetime(2021, 7, 2)),
18 datetime.datetime(2021, 7, 3)),
20 datetime.datetime(2021, 7, 1)),
22 datetime.datetime(2021, 7, 2, 21, 30, 0, 0)),
24 datetime.datetime(2021, 7, 2, 0, 1, 0, 0)),
26 datetime.datetime(2021, 7, 2, 12, 2, 0, 0)),
28 datetime.datetime(2021, 7, 2, 0, 3, 0, 0)),
30 datetime.datetime(2021, 6, 30)),
32 datetime.datetime(2021, 7, 7)),
34 datetime.datetime(2021, 7, 14)),
36 datetime.datetime(2021, 7, 6)),
38 datetime.datetime(2021, 6, 28)),
40 datetime.datetime(2021, 6, 28)),
42 datetime.datetime(2021, 6, 7)),
44 datetime.datetime(2021, 3, 2)),
46 datetime.datetime(2021, 6, 29)),
48 datetime.datetime(2021, 10, 1)),
50 datetime.datetime(2022, 7, 2)),
52 datetime.datetime(2021, 7, 30)),
54 datetime.datetime(2021, 6, 12)),
55 ('4 months from today',
56 datetime.datetime(2021, 11, 2)),
57 ('4 years from yesterday',
58 datetime.datetime(2025, 7, 1)),
59 ('4 weeks from tomorrow',
60 datetime.datetime(2021, 7, 31)),
62 datetime.datetime(2005, 4, 15)),
64 datetime.datetime(2021, 4, 14)),
65 ('9:30am on last wednesday',
66 datetime.datetime(2021, 6, 30, 9, 30)),
68 datetime.datetime(2005, 4, 15)),
70 datetime.datetime(2005, 4, 15)),
71 ('the 1st wednesday in may',
72 datetime.datetime(2021, 5, 5)),
74 datetime.datetime(2021, 6, 27)),
76 datetime.datetime(2021, 4, 4)),
78 datetime.datetime(2020, 12, 25)),
80 datetime.datetime(2020, 12, 25)),
82 datetime.datetime(1999, 12, 25)),
84 datetime.datetime(2022, 1, 17)),
86 datetime.datetime(2020, 10, 31)),
87 ('5 work days after independence day',
88 datetime.datetime(2021, 7, 12)),
89 ('50 working days from last wed',
90 datetime.datetime(2021, 9, 10)),
91 ('25 working days before columbus day',
92 datetime.datetime(2021, 9, 3)),
94 datetime.datetime(2021, 7, 9)),
96 datetime.datetime(2021, 6, 13)),
97 ('4 weeks before xmas, 1999',
98 datetime.datetime(1999, 11, 27)),
99 ('3 days before new years eve, 2000',
100 datetime.datetime(2000, 12, 28)),
102 datetime.datetime(2021, 7, 4)),
103 ('the ides of march',
104 datetime.datetime(2021, 3, 15)),
105 ('the nones of april',
106 datetime.datetime(2021, 4, 5)),
107 ('the kalends of may',
108 datetime.datetime(2021, 5, 1)),
110 datetime.datetime(2001, 9, 11)),
111 ('4 sundays before veterans\' day',
112 datetime.datetime(2021, 10, 17)),
114 datetime.datetime(2021, 12, 24)),
115 ('this friday at 5pm',
116 datetime.datetime(2021, 7, 9, 17, 0, 0)),
118 datetime.datetime(2021, 2, 15)),
119 ('memorial day, 1921',
120 datetime.datetime(1921, 5, 30)),
121 ('today -4 wednesdays',
122 datetime.datetime(2021, 6, 9)),
124 datetime.datetime(2021, 11, 25)),
126 datetime.datetime(2021, 6, 13)),
128 datetime.datetime(2021, 2, 23)),
130 datetime.datetime(2021, 5, 13)),
131 ('1st tuesday in nov, 2024',
132 datetime.datetime(2024, 11, 5)),
133 ('2 days before last xmas at 3:14:15.92a',
134 datetime.datetime(2020, 12, 23, 3, 14, 15, 92)),
135 ('3 weeks after xmas, 1995 at midday',
136 datetime.datetime(1996, 1, 15, 12, 0, 0)),
137 ('4 months before easter, 1992 at midnight',
138 datetime.datetime(1991, 12, 19)),
139 ('5 months before halloween, 1995 at noon',
140 datetime.datetime(1995, 5, 31, 12)),
141 ('4 days before last wednesday',
142 datetime.datetime(2021, 6, 26)),
143 ('44 months after today',
144 datetime.datetime(2025, 3, 2)),
145 ('44 years before today',
146 datetime.datetime(1977, 7, 2)),
148 datetime.datetime(2020, 8, 28)),
149 ('15 minutes to 3am',
150 datetime.datetime(2021, 7, 2, 2, 45)),
152 datetime.datetime(2021, 7, 2, 16, 15)),
154 datetime.datetime(2021, 7, 2, 9, 30)),
155 ('4 seconds to midnight',
156 datetime.datetime(2021, 7, 1, 23, 59, 56)),
157 ('4 seconds to midnight, tomorrow',
158 datetime.datetime(2021, 7, 2, 23, 59, 56)),
159 ('2021/apr/15T21:30:44.55',
160 datetime.datetime(2021, 4, 15, 21, 30, 44, 55)),
161 ('2021/apr/15 at 21:30:44.55',
162 datetime.datetime(2021, 4, 15, 21, 30, 44, 55)),
163 ('2021/4/15 at 21:30:44.55',
164 datetime.datetime(2021, 4, 15, 21, 30, 44, 55)),
165 ('2021/04/15 at 21:30:44.55',
166 datetime.datetime(2021, 4, 15, 21, 30, 44, 55)),
167 ('2021/04/15 at 21:30:44.55Z',
168 datetime.datetime(2021, 4, 15, 21, 30, 44, 55,
169 tzinfo=pytz.timezone('UTC'))),
170 ('2021/04/15 at 21:30:44.55EST',
171 datetime.datetime(2021, 4, 15, 21, 30, 44, 55,
172 tzinfo=pytz.timezone('EST'))),
173 ('13 days after last memorial day at 12 seconds before 4pm',
174 datetime.datetime(2020, 6, 7, 15, 59, 48)),
175 (' 2 days before yesterday at 9am ',
176 datetime.datetime(2021, 6, 29, 9)),
177 ('-3 days before today',
178 datetime.datetime(2021, 7, 5)),
179 ('3 days before yesterday at midnight EST',
180 datetime.datetime(2021, 6, 28, tzinfo=pytz.timezone('EST')))
184 class TestDateparseUtils(unittest.TestCase):
186 @uu.check_method_for_perf_regressions
187 def test_dateparsing(self):
189 override_now_for_test_purposes = datetime.datetime(2021, 7, 2)
192 for (txt, expected_dt) in parsable_expressions:
194 actual_dt = dp.parse(txt)
195 self.assertIsNotNone(actual_dt)
199 f'"{txt}", got "{actual_dt}" while expecting "{expected_dt}"'
201 except du.ParseException:
202 self.fail(f'Expected "{txt}" to parse successfully.')
204 def test_whitespace_handling(self):
206 override_now_for_test_purposes = datetime.datetime(2021, 7, 2)
209 for (txt, expected_dt) in parsable_expressions:
212 i = random.randint(2, 5)
213 replacement = ' ' * i
214 txt = re.sub('\s', replacement, txt)
215 actual_dt = dp.parse(txt)
216 self.assertIsNotNone(actual_dt)
220 f'"{txt}", got "{actual_dt}" while expecting "{expected_dt}"'
222 except du.ParseException:
223 self.fail(f'Expected "{txt}" to parse successfully.')
226 if __name__ == '__main__':