Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make day parser more generalizable to complex combinations of days and day ranges #6

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions humanized_opening_hours/field.ebnf
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,20 @@ period : moment "-" moment

raw_consecutive_day_range : DAY "-" DAY

day_day_range : (raw_consecutive_day_range | DAY)

raw_consecutive_month_range : MONTH "-" MONTH

concerned_period : DAY ("," DAY)* ("," (PUBLIC_HOLIDAYS | SCHOOL_HOLIDAYS))* " " -> unconsecutive_days
concerned_period : day_day_range ("," day_day_range)* ("," (PUBLIC_HOLIDAYS | SCHOOL_HOLIDAYS))* " " -> days
| MONTH ("," MONTH)* ("," (PUBLIC_HOLIDAYS | SCHOOL_HOLIDAYS))* " " -> unconsecutive_months
| (PUBLIC_HOLIDAYS | SCHOOL_HOLIDAYS) ["," (PUBLIC_HOLIDAYS | SCHOOL_HOLIDAYS)] " " -> holiday
| raw_consecutive_day_range ("," DAY)* ("," (PUBLIC_HOLIDAYS | SCHOOL_HOLIDAYS))* " " -> consecutive_day_range
| raw_consecutive_month_range ("," MONTH)* ("," (PUBLIC_HOLIDAYS | SCHOOL_HOLIDAYS))* " " -> consecutive_month_range
| MONTH ("," MONTH)* " " DAY ("," DAY)* [":"] " " -> days_of_month
| MONTH ("," MONTH)* [":"] " " raw_consecutive_day_range ("," DAY)* " " -> consecutive_days_of_month
| MONTH ("," MONTH)* [":"] " " day_day_range ("," DAY)* " " -> consecutive_days_of_month
| raw_consecutive_month_range ("," MONTH)* [":"] " " DAY ("," DAY)* " " -> days_of_consecutive_months
| raw_consecutive_month_range [":"] " " raw_consecutive_day_range " " -> consecutive_days_of_consecutive_months //TODO : Support months or days after commas.
| raw_consecutive_month_range [":"] " " day_day_range " " -> consecutive_days_of_consecutive_months //TODO : Support months or days after commas.
| (PUBLIC_HOLIDAYS | SCHOOL_HOLIDAYS) " " DAY " " -> holidays_unconsecutive_days
| (PUBLIC_HOLIDAYS | SCHOOL_HOLIDAYS) " " raw_consecutive_day_range ("," DAY)* " " -> holidays_consecutive_days
| (PUBLIC_HOLIDAYS | SCHOOL_HOLIDAYS) " " day_day_range ("," DAY)* " " -> holidays_consecutive_days

day_periods : period ("," period)*
| "off" -> period_closed
Expand Down
62 changes: 30 additions & 32 deletions humanized_opening_hours/field_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ def digital_moment(self, arg):
else:
time = datetime.datetime.strptime(arg[0], "%H:%M").time()
return Moment(MomentKind.NORMAL, time=time)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is a common convention, but just to remain consistent and atomic, I think unindentation of blank lines should be done later, in another PR.


def solar_moment(self, arg):
return Moment(MomentKind[arg[0].upper()], delta=datetime.timedelta())

def solar_complex_moment(self, arg):
arg = arg[0].strip('()')
if arg.find('+') != -1:
Expand All @@ -42,51 +42,49 @@ def solar_complex_moment(self, arg):
) * offset_sign
offset = datetime.timedelta(seconds=offset_seconds)
return Moment(kind, delta=offset)

# Period
def period(self, args):
return Period(args[0], args[1])

def day_periods(self, args):
return args

def period_closed(self, args):
return []

# Concerned days
def unconsecutive_days(self, args):
return set([tk.value for tk in args])

def consecutive_day_range(self, args): # TODO : Fix this dirty hack.
if len(args) == 1:
return args[0]
s = args[0]
for day in args[1:]:
s.add(day.value)
def days(self, args):
s = set()
for d in args:
if hasattr(d, 'children'):
s.update(d.children[0])
else:
s.add(d)
return s

def raw_consecutive_day_range(self, args):
first_day = WEEKDAYS.index(args[0])
last_day = WEEKDAYS.index(args[1])
day_indexes = list(range(first_day, last_day+1))
return set([WEEKDAYS[i] for i in day_indexes])

def everyday_periods(self, args):
return (set('*'), args[0])

# Concerned months
def unconsecutive_months(self, args):
return set([tk.value for tk in args])

def consecutive_month_range(self, args):
return args[0]

def raw_consecutive_month_range(self, args):
first_month = MONTHS.index(args[0])
last_month = MONTHS.index(args[1])
month_indexes = list(range(first_month, last_month+1))
return set([MONTHS[i] for i in month_indexes])

def days_of_month(self, args):
# TODO : Check specifications.
output = set()
Expand All @@ -101,7 +99,7 @@ def days_of_month(self, args):
for wd in weekdays:
output.add(m + '-' + wd)
return output

def consecutive_days_of_month(self, args):
months = [tk.value for tk in args[:-1]]
days = args[-1]
Expand All @@ -110,7 +108,7 @@ def consecutive_days_of_month(self, args):
for d in days:
output.add(m + '-' + d)
return output

def days_of_consecutive_months(self, args):
months = args[0]
days = [tk.value for tk in args[1:]]
Expand All @@ -119,42 +117,42 @@ def days_of_consecutive_months(self, args):
for d in days:
output.add(m + '-' + d)
return output

def consecutive_days_of_consecutive_months(self, args):
output = set()
for m in args[0]:
for d in args[1]:
output.add(m + '-' + d)
return output

# Exceptional days
def exceptional_day(self, args):
# "month_index-day" - "Dec 25" -> "12-25"
return str(MONTHS.index(args[0])+1) + '-' + args[1]

def exceptional_dates(self, args):
return tuple((set(args[:-1]), args[-1]))

# Holidays
def holiday(self, args):
return set([tk.value for tk in args])

def holidays_unconsecutive_days(self, args):
return args[0].value + '-' + args[1].value

def holidays_consecutive_days(self, args):
output = []
for d in args[1]:
output.append(args[0].value + '-' + d)
return output

# Always open
def always_open(self, args):
return (set('*'), [self.period([
self.digital_moment(["00:00"]),
self.digital_moment(["24:00"])
])])

# Field part
def field_part(self, args):
for period in args[1]:
Expand Down Expand Up @@ -188,7 +186,7 @@ def __init__(self, tree):
self.exceptional_dates.append(((int(month), int(day)), part[1]))
except ValueError: # Temporary fix for "Jan Mo off"
pass

def get_periods_of_day(self, dt, is_PH=False, is_SH=False):
# Tries to get the opening periods of a day,
# with the following patterns:
Expand Down