Module src.parse.match

Expand source code
from lark import Lark, Transformer, v_args
from lark import logger
from lark.exceptions import UnexpectedInput, LarkError
import logging

from datetime import datetime

logger.setLevel(logging.DEBUG)

_period_grammar = """
    ?start: period
    
    ?period: datetime datetime

    datetime: date time
        | time      -> just_time
    
    date: month "/" day "/" year
    
    time: hour ":" minute ampm?
    
    ?ampm: AM | PM
    
    AM: "AM"i
    PM: "PM"i

    day: DIGIT12
    month: DIGIT12
    year: DIGIT4 | DIGIT2

    hour: DIGIT12
    minute: DIGIT2

    DIGIT12: /\d{1,2}/
    DIGIT4: /\d{4}/
    DIGIT2: /\d{2}/

    %import common.WS_INLINE
    %ignore WS_INLINE
"""

class _PeriodTree(Transformer):
    """
    Class:
        _PeriodTree
    Description:
        Converts a parsed grammar of 2 date and times into datetime objects
        Grammar is handled by lark library, and this object just manages conversion.
    """
    def period(self, t):
        initial = t[0]
        end = t[1]
        if t[1] <= t[0]:
            raise Exception("your starting date is after your ending date")
        return [t[0], t[1]]

    def datetime(self, t):
        mm, dd, yy = t[0]
        h, m = t[1]
        try:
            return datetime(yy, mm, dd, h, m)
        except:
            raise Exception("your entered date is not possible")

    def time(self, t):
        print(t)
        h = t[0]
        m = t[1]
        if len(t) == 3:
            if not( 1 <= h and h <= 12 ):
                raise Exception("you entered the time incorrectly")
            h %= 12
            if t[2].upper() == "PM":
                h += 12
        if not( 0 <= h and h <= 23 and 0 <= m and m <= 59 ):
            raise Exception("you entered the time incorrectly")
        return [h, m]
    
    def date(self, t):
        m = t[0]
        d = t[1]
        y = t[2]
        if len(str(y)) == 2:
            y = int("20" + str(y))
        if not( 1 <= m and m <= 12 and 1 <= d and d <= 31 ):
            raise Exception("you entered the date incorrectly")
        return [m, d, y]
    
    def hour(self, t):
        return int(t[0])
    def minute(self, t):
        return int(t[0])
    
    def day(self, t):
        return int(t[0])
    def month(self, t):
        return int(t[0])
    def year(self, t):
        return int(t[0])
    
    def pm(self,t): return "pm"
    

period_parser = Lark(_period_grammar, parser='lalr', debug=True, transformer=_PeriodTree())
period_grammar = period_parser.parse

#s = input('> ')
# print( dt(s) )

# def parse_period(period):
#     try:
#         return period_grammar(period)
#     except:
#         None

def parse_period(period):
    """
    Function:
        parse_period
    Description:
        Converts and validates two user inputs into 2 datetime objects
    Input:
        period - a string that may contain 2 dates
    Output:
        A list with two datetime object if conversion is successful
        An exception if conversion fails
    """
    try:
        return period_grammar(period)
    except (UnexpectedInput, LarkError):
        raise Exception("your dates were not in the requested format")
    except Exception as e:
        raise e

if __name__ == "__main__":
    # s = "4/20/2021 6:10 am 4/20/2021 12:10 pm"
    s = input("> ")
    print(s)
    print(parse_period(s))

Functions

def parse_period(period)

Function

parse_period

Description

Converts and validates two user inputs into 2 datetime objects

Input

period - a string that may contain 2 dates

Output

A list with two datetime object if conversion is successful An exception if conversion fails

Expand source code
def parse_period(period):
    """
    Function:
        parse_period
    Description:
        Converts and validates two user inputs into 2 datetime objects
    Input:
        period - a string that may contain 2 dates
    Output:
        A list with two datetime object if conversion is successful
        An exception if conversion fails
    """
    try:
        return period_grammar(period)
    except (UnexpectedInput, LarkError):
        raise Exception("your dates were not in the requested format")
    except Exception as e:
        raise e