Skip to content

Instantly share code, notes, and snippets.

@giftig
Created August 23, 2017 15:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save giftig/9e74658233384588037be3440a372c8b to your computer and use it in GitHub Desktop.
Save giftig/9e74658233384588037be3440a372c8b to your computer and use it in GitHub Desktop.
import datetime
import string
class DateParser(object):
"""Parse various convenient date phrases"""
DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
@staticmethod
def _parse_timedelta(n, unit):
"""
Parse a timedelta in the given units (single chars or short strings)
Returns a timedelta
"""
mappings = {
's': 'seconds',
'm': 'minutes',
'h': 'hours',
'd': 'days',
'w': 'weeks'
}
if unit not in mappings:
raise ValueError('Unexpected unit: %s' % unit)
data = {}
data[mappings[unit]] = n
return datetime.timedelta(**data)
def _parse_token(self, s):
"""
Parse the string into a datetime or timedelta, and remainder
:param s: The string to parse
:returns: A datetime or timedelta representing the first token in the
string, and the unparsed remainder of the string
:rtype: ([datetime or timedelta], str)
"""
if s is None:
return None, None
s = s.strip()
if s == '':
return None, None
# If it starts with + or -, it'll be a timedelta
if s[0] in ['+', '-']:
mult = 1 if s[0] == '+' else -1
s = s[1:].lstrip()
phrase = s.split(' ')[0]
s = s[len(phrase):]
n = ''
for c in phrase:
if c not in string.digits:
break
n += c
unit = phrase[len(n):]
try:
n = int(n)
except ValueError:
raise ValueError(
'Expected a number after + or - but found %s' % n
)
return self._parse_timedelta(n, unit) * mult, s
now = datetime.datetime.now()
today = datetime.datetime(
year=now.year,
month=now.month,
day=now.day
)
frag = s.split(' ')[0]
s = s[len(frag):]
if frag.lower() == 'now':
return now, s
if frag.lower() == 'today':
return today, s
if frag.lower() == 'yesterday':
return today - datetime.timedelta(days=1), s
if frag.lower() == 'tomorrow':
return today + datetime.timedelta(days=1), s
return datetime.datetime.strptime(frag, self.DATE_FORMAT), s
def parse(self, s):
value, remainder = self._parse_token(s)
while remainder:
next_token, remainder = self._parse_token(remainder)
value += next_token
return value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment