-
Notifications
You must be signed in to change notification settings - Fork 14
/
datetime.py
64 lines (50 loc) · 1.74 KB
/
datetime.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import re
from dateutil import parser
def parse(string):
""" Try to parse a date expressed in natural language.
:param str string: Date in natural language
:return: dictionary with year, month, day
:type: dict
"""
class CustomDatetime:
""" Hackish way to extract extract day, month and year only when
they were defined in the original string
"""
result = {'year': None, 'month': None, 'day': None}
def replace(self, **kwargs):
self.result.update(kwargs)
@property
def year(self):
return self.result['year']
@property
def month(self):
return self.result['month']
@property
def day(self):
return self.result['day']
parsed = CustomDatetime()
try:
parser.parse(string, default=parsed)
except ValueError:
pass
if parsed.result != {'year': None, 'month': None, 'day': None}:
return parsed.result
else:
return _fallback(string)
_custom_patterns = map(
lambda (pattern, transform): (re.compile(pattern, re.UNICODE | re.IGNORECASE),
transform), [
(r'b\.c\. (?P<y>\d+)', lambda match: {'year': int('-' + match.group('y'))}),
(r'(?P<y>\d+)\s*bc', lambda match: {'year': int('-' + match.group('y'))}),
(r'\d{4}', lambda match: {'year': int(match.group(0))}),
]
)
def _fallback(string):
""" Try to parse the string even when dateutil fails """
result = {'year': None, 'month': None, 'day': None}
for regex, transform in _custom_patterns:
match = regex.match(string)
if match:
result.update(transform(match))
break
return result