|
10 | 10 |
|
11 | 11 |
|
12 | 12 | class Parser(object): |
| 13 | + """ |
| 14 | + Parser which parses common formats (like RFC3339 and ISO8601). |
| 15 | + """ |
| 16 | + |
13 | 17 | COMMON = re.compile( |
14 | 18 | # Date (optional) |
15 | 19 | '^' |
16 | | - '(' |
17 | | - ' (?P<date>' # Classic date (YYYY-MM-DD) or ordinal (YYYY-DDD) |
| 20 | + '(?P<date>' |
| 21 | + ' (?P<classic>' # Classic date (YYYY-MM-DD) or ordinal (YYYY-DDD) |
18 | 22 | ' (?P<year>\d{4})' # Year |
19 | 23 | ' (?P<monthday>' |
20 | 24 | ' (?P<monthsep>-|/)?(?P<month>\d{2})' # Month (optional) |
@@ -81,58 +85,57 @@ def parse_common(self, text): |
81 | 85 | has_date = False |
82 | 86 |
|
83 | 87 | if m: |
84 | | - if m.group('isocalendar'): |
85 | | - date = self._get_iso_8601_week( |
86 | | - m.group('isoyear'), |
87 | | - m.group('isoweek'), |
88 | | - m.group('isoweekday') |
89 | | - ) |
90 | | - |
91 | | - year = date['year'] |
92 | | - month = date['month'] |
93 | | - day = date['day'] |
94 | | - |
95 | | - parsed.update({ |
96 | | - 'year': year, |
97 | | - 'month': month, |
98 | | - 'day': day, |
99 | | - }) |
100 | | - elif m.group('date'): |
101 | | - has_date = True |
| 88 | + if m.group('date'): |
102 | 89 | # A date has been specified |
103 | | - year = int(m.group('year')) |
| 90 | + has_date = True |
| 91 | + |
| 92 | + if m.group('isocalendar'): |
| 93 | + # We have a ISO 8601 string defined |
| 94 | + # by week number |
| 95 | + date = self._get_iso_8601_week( |
| 96 | + m.group('isoyear'), |
| 97 | + m.group('isoweek'), |
| 98 | + m.group('isoweekday') |
| 99 | + ) |
104 | 100 |
|
105 | | - if not m.group('monthday'): |
106 | | - # No month and day |
107 | | - month = 1 |
108 | | - day = 1 |
| 101 | + year = date['year'] |
| 102 | + month = date['month'] |
| 103 | + day = date['day'] |
109 | 104 | else: |
110 | | - if m.group('month') and m.group('day'): |
111 | | - # Month and day |
112 | | - if len(m.group('day')) == 1: |
113 | | - # Ordinal day |
114 | | - dt = datetime.strptime( |
115 | | - '{}-{}'.format(year, m.group('month') + m.group('day')), |
116 | | - '%Y-%j' |
117 | | - ) |
118 | | - month = dt.month |
119 | | - day = dt.day |
120 | | - elif self._options['day_first']: |
121 | | - month = int(m.group('day')) |
122 | | - day = int(m.group('month')) |
| 105 | + # We have a classic date representation |
| 106 | + year = int(m.group('year')) |
| 107 | + |
| 108 | + if not m.group('monthday'): |
| 109 | + # No month and day |
| 110 | + month = 1 |
| 111 | + day = 1 |
| 112 | + else: |
| 113 | + if m.group('month') and m.group('day'): |
| 114 | + # Month and day |
| 115 | + if len(m.group('day')) == 1: |
| 116 | + # Ordinal day |
| 117 | + dt = datetime.strptime( |
| 118 | + '{}-{}'.format(year, m.group('month') + m.group('day')), |
| 119 | + '%Y-%j' |
| 120 | + ) |
| 121 | + month = dt.month |
| 122 | + day = dt.day |
| 123 | + elif self._options['day_first']: |
| 124 | + month = int(m.group('day')) |
| 125 | + day = int(m.group('month')) |
| 126 | + else: |
| 127 | + month = int(m.group('month')) |
| 128 | + day = int(m.group('day')) |
123 | 129 | else: |
| 130 | + # Only month |
| 131 | + if not m.group('monthsep'): |
| 132 | + # The date looks like 201207 |
| 133 | + # which is invalid for a date |
| 134 | + # But it might be a time in the form hhmmss |
| 135 | + ambiguous_date = True |
| 136 | + |
124 | 137 | month = int(m.group('month')) |
125 | | - day = int(m.group('day')) |
126 | | - else: |
127 | | - # Only month |
128 | | - if not m.group('monthsep'): |
129 | | - # The date looks like 201207 |
130 | | - # which is invalid for a date |
131 | | - # But it might be a time in the form hhmmss |
132 | | - ambiguous_date = True |
133 | | - |
134 | | - month = int(m.group('month')) |
135 | | - day = 1 |
| 138 | + day = 1 |
136 | 139 |
|
137 | 140 | parsed.update({ |
138 | 141 | 'year': year, |
@@ -271,6 +274,8 @@ def _parse(self, text): |
271 | 274 | if parsed: |
272 | 275 | return parsed |
273 | 276 |
|
| 277 | + # We couldn't parse the string |
| 278 | + # so we fallback on the dateutil parser |
274 | 279 | try: |
275 | 280 | dt = parser.parse(text, dayfirst=self._options['day_first']) |
276 | 281 | except ValueError: |
|
0 commit comments