Reputation: 36
I have a string input where text contains data as "monday of next month" or "4 days before new year" need to convert into dates as suppose today is 25/11/2020, so next month monday is on 07/12/2020, so how should i do it in python (i've tried using datetime, dateutil but didn't help')
next week saturday
4 days before new year
3 days after new year
second wednesday of next month
i need output as
05/12/20
28/12/20
03/01/21
09/12/21
tried reading docs but didn't help can anyone shed some light on it.
here's my python code.
from datetime import datetime, timedelta
from dateutil import parser
from dateparser.search import search_dates
# Create your views here.
def converter_view(request):
form = DateStringForm()
if request.method == 'POST':
form = DateStringForm(request.POST)
if form.is_valid():
input_string = form.cleaned_data['string_date']
list_of_dates = []
if input_string.lower() == "today":
data = datetime.now()
list_of_dates.append(data.strftime('%d/%m/%Y'))
elif input_string.lower() == "tomorrow":
data = datetime.now() + timedelta(1)
list_of_dates.append(data.strftime('%d/%m/%Y'))
elif input_string.lower() == "yesterday":
data = datetime.now() - timedelta(1)
list_of_dates.append(data.strftime('%d/%m/%Y'))
else:
try:
# Using search_dates method we were extracting the keywords related to date, day or month
# So search_dates is going to return a "list of tuple" where 0th index is string and 1st is datetime
data = search_dates(input_string)
except Exception as msg:
print('Exception :', msg)
else:
try:
for i in data:
# So as we require to convert that date back in string format, we parse the extracted data in data
# where parser.parse() is taking 0th index which is string, and converting it to date and by using
# strftime function we get the required format
list_of_dates.append(parser.parse(i[0]).strftime('%d/%m/%Y'))
print(list_of_dates)
except TypeError as msg:
print("String does not contain any day or dates")
values = DateStringConvert(string_date=input_string, date=list_of_dates)
values.save()
return HttpResponseRedirect('/dateconverter')
return render(request, 'DateTimeConverter/index.html', {'form':form})
Upvotes: 0
Views: 177
Reputation: 2060
It's impossible to facilitate all possible combinations and pieces of text. However, you can cover most cases with a few basic patterns.
import re
import datetime
queries = [
"next week saturday",
"4 days before new year",
"3 days after new year",
"second wednesday of next month",
]
def parse_relative_string_date(text: str, start_date: datetime.datetime = datetime.datetime.now()) -> datetime.datetime:
def _next_week(weekday: str):
weekdays = {
"monday": 0,
"tuesday": 1,
"wednesday": 2,
"thursday": 3,
"friday": 4,
"saturday": 5,
"sunday": 6,
}
next_week = start_date + datetime.timedelta(weeks=1)
return next_week + datetime.timedelta((weekdays[weekday.lower()] - next_week.weekday()) % 7)
def _new_year(n_days: str, direction: str):
new_years = datetime.datetime(year=start_date.year + 1, month=1, day=1)
directions = {
"before": -1,
"after": 1,
}
return new_years + datetime.timedelta(directions[direction.lower()] * int(n_days))
patterns = {
r"next week (?P<weekday>\w+)": _next_week,
r"(?P<n_days>\d+) days (?P<direction>\w+) new year": _new_year,
# Add more patterns here
}
for pattern, callback in patterns.items():
found = re.search(pattern, text)
if found is not None:
return callback(**dict(found.groupdict()))
for query in queries:
print(parse_relative_string_date(query))
Upvotes: 1