Skip to content

Instantly share code, notes, and snippets.

@minsis
Created January 30, 2021 19:47
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 minsis/177eb893423a1ce46ed730e880c9d019 to your computer and use it in GitHub Desktop.
Save minsis/177eb893423a1ce46ed730e880c9d019 to your computer and use it in GitHub Desktop.
Simple library for parsing some human readable dates. Setup as a jinja2 filter
import re
import calendar
from datetime import datetime
from dateutil.relativedelta import relativedelta
_day_of_week_to_ = {
"day": 0,
"monday": 0,
"tuesday": 1,
"wednesday": 2,
"thursday": 3,
"friday": 4,
"saturday": 5,
"sunday": 6
}
_advance_to_ = {
"this": +0,
"the": +0,
"next": +1,
"last": -1
}
_time_period_to_ = {
"month": "months",
"week": "weeks"
}
class FilterModule:
def filters(self):
return {'parse_human_date': self.parse_date}
@staticmethod
def parse_date(human_date):
try:
num_value = int(re.match(r"(\d+)", human_date).group())
except (AttributeError, ValueError):
raise ValueError("It seems that you may not have specified a number of something. e.g. '5th' day")
try:
weekday = re.search(
r"(\bday\b|\bMo(nday)?\b|\bTu(e(sday)?)?\b|\bWe(d(nesday)?)?\b|\bTh(ur(sday)?)?\b|\bFr(i(day)?)?\b|\bSa(t(urday)?)?\b|\bSu(n(day)?)?\b)",
human_date
).group().lower()
except AttributeError:
raise ValueError("It seems that you may not have specified a day. e.g. 'day' or 'Friday'")
try:
advance = re.search(r"(\bnext\b|\blast\b|\bthis\b|\bthe\b)", human_date).group()
except AttributeError as e:
raise ValueError("It seems that you may not have specified a advance direction. e.g. 'next' or 'last' or 'this'")
try:
time_period = re.search(r"(\bmo(nth)?\b)", human_date).group()
except AttributeError:
raise ValueError("It seems that you may not have specified a time period. e.g. 'month' or 'week'")
today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
options = {
_time_period_to_[time_period]: _advance_to_[advance]
}
new_date = today + relativedelta(**options)
month_cal = calendar.monthcalendar(new_date.year, new_date.month)
if weekday == "day" and time_period == "month":
new_date = new_date.replace(day=num_value)
# issues getting to previous week or next week
# elif time_period == "week":
# for week in month_cal:
# if new_date.day in week:
# the_week = week
# break
# new_date = new_date.replace(
# day=the_week[num_value - 2]
# )
else:
first_week = month_cal[0]
the_day = first_week[_day_of_week_to_[weekday]]
new_date = new_date.replace(
day=month_cal[
num_value if the_day == 0 else num_value - 1
][
_day_of_week_to_[weekday]
]
)
return new_date
if __name__ == "__main__":
print(FilterModule.parse_date("1st day of next month"))
print(FilterModule.parse_date("2nd Friday of this month"))
print(FilterModule.parse_date("1st Sunday of next month"))
print(FilterModule.parse_date("5th day of next month"))
print(FilterModule.parse_date("2nd Tuesday of this month"))
# print(FilterModule.parse_date("1rd day of last week"))
# print(FilterModule.parse_date("1st day of next week"))
@minsis
Copy link
Author

minsis commented Jan 30, 2021

Main issue with this I'm having troubles with is getting "someday of last week". But I dont need it for what I'm using this library for so feel free to add to it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment