X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=dateparse%2Fdateparse_utils.py;h=21fdb832b5c556317989e4f9855dae8daae67552;hb=5f75cf834725ac26b289cc5f157af0cb71cd5f0e;hp=4decb81570bb0bbf02f066ec31993b20ea0ce6af;hpb=1574e8a3a8982fab9278ad534f9427d464e4bffb;p=python_utils.git diff --git a/dateparse/dateparse_utils.py b/dateparse/dateparse_utils.py index 4decb81..21fdb83 100755 --- a/dateparse/dateparse_utils.py +++ b/dateparse/dateparse_utils.py @@ -1,5 +1,10 @@ #!/usr/bin/env python3 +""" +Parse dates in a variety of formats. + +""" + import datetime import functools import holidays # type: ignore @@ -50,7 +55,6 @@ def debug_parse(enter_or_exit_f: Callable[[Any, Any], None]): class ParseException(Exception): """An exception thrown during parsing because of unrecognized input.""" def __init__(self, message: str) -> None: - logger.error(message) self.message = message @@ -59,7 +63,6 @@ class RaisingErrorListener(antlr4.DiagnosticErrorListener): def syntaxError( self, recognizer, offendingSymbol, line, column, msg, e ): - logger.error(msg) raise ParseException(msg) def reportAmbiguity( @@ -194,6 +197,8 @@ class DateParser(dateparse_utilsListener): This is the main entrypoint to this class for caller code. """ + date_string = date_string.strip() + date_string = re.sub('\s+', ' ', date_string) self._reset() listener = RaisingErrorListener() input_stream = antlr4.InputStream(date_string) @@ -249,6 +254,7 @@ class DateParser(dateparse_utilsListener): self.datetime: Optional[datetime.datetime] = None self.context: Dict[str, Any] = {} self.timedelta = datetime.timedelta(seconds=0) + self.saw_overt_year = False @staticmethod def _normalize_special_day_name(name: str) -> str: @@ -269,9 +275,9 @@ class DateParser(dateparse_utilsListener): return TimeUnit.MONTHS txt = orig.lower()[:3] if txt in self.day_name_to_number: - return(self.day_name_to_number[txt]) + return(TimeUnit(self.day_name_to_number[txt])) elif txt in self.delta_unit_to_constant: - return(self.delta_unit_to_constant[txt]) + return(TimeUnit(self.delta_unit_to_constant[txt])) raise ParseException(f'Invalid date unit: {orig}') def _figure_out_time_unit(self, orig: str) -> int: @@ -300,8 +306,10 @@ class DateParser(dateparse_utilsListener): next_last = self.context.get('special_next_last', '') if next_last == 'next': year += 1 + self.saw_overt_year = True elif next_last == 'last': year -= 1 + self.saw_overt_year = True # Holiday names if name == 'easte': @@ -360,6 +368,9 @@ class DateParser(dateparse_utilsListener): raise ParseException('Missing day') if 'year' not in self.context: self.context['year'] = self.today.year + self.saw_overt_year = False + else: + self.saw_overt_year = True # Handling "ides" and "nones" requires both the day and month. if ( @@ -385,7 +396,7 @@ class DateParser(dateparse_utilsListener): tz = pytz.timezone(txt) if tz is not None: return tz - except: + except Exception: pass # Try dateutil @@ -393,7 +404,7 @@ class DateParser(dateparse_utilsListener): tz = dateutil.tz.gettz(txt) if tz is not None: return tz - except: + except Exception: pass # Try constructing an offset in seconds @@ -406,7 +417,7 @@ class DateParser(dateparse_utilsListener): offset = sign * (hour * 60 * 60) + sign * (minute * 60) tzoffset = dateutil.tz.tzoffset(txt, offset) return tzoffset - except: + except Exception: pass return None @@ -507,7 +518,7 @@ class DateParser(dateparse_utilsListener): unit = self.context['delta_unit'] dt = n_timeunits_from_base( count, - unit, + TimeUnit(unit), date_to_datetime(self.date) ) self.date = datetime_to_date(dt) @@ -574,7 +585,7 @@ class DateParser(dateparse_utilsListener): unit = self._figure_out_date_unit( ctx.deltaUnit().getText().lower() ) - except: + except Exception: raise ParseException(f'Invalid Delta +/-: {ctx.getText()}') else: self.context['delta_int'] = n @@ -585,7 +596,7 @@ class DateParser(dateparse_utilsListener): ) -> None: try: unit = self._figure_out_date_unit(ctx.getText().lower()) - except: + except Exception: raise ParseException(f'Bad delta unit: {ctx.getText()}') else: self.context['delta_unit'] = unit @@ -595,7 +606,7 @@ class DateParser(dateparse_utilsListener): ) -> None: try: txt = ctx.getText().lower() - except: + except Exception: raise ParseException(f'Bad next/last: {ctx.getText()}') if ( 'month' in self.context or @@ -610,11 +621,13 @@ class DateParser(dateparse_utilsListener): self.context['day'] = self.now_datetime.day self.context['month'] = self.now_datetime.month self.context['year'] = self.now_datetime.year + self.saw_overt_year = True elif txt[:4] == 'last': self.context['delta_int'] = -1 self.context['day'] = self.now_datetime.day self.context['month'] = self.now_datetime.month self.context['year'] = self.now_datetime.year + self.saw_overt_year = True else: raise ParseException(f'Bad next/last: {ctx.getText()}') @@ -630,7 +643,7 @@ class DateParser(dateparse_utilsListener): ctx.deltaTimeUnit().getText().lower() ) self.context['time_delta_unit'] = unit - except: + except Exception: raise ParseException(f'Bad delta unit: {ctx.getText()}') if 'time_delta_before_after' not in self.context: raise ParseException( @@ -654,7 +667,7 @@ class DateParser(dateparse_utilsListener): ] = TimeUnit.MINUTES else: raise ParseException(f'Bad time fraction {ctx.getText()}') - except: + except Exception: raise ParseException(f'Bad time fraction {ctx.getText()}') def exitDeltaBeforeAfter( @@ -662,7 +675,7 @@ class DateParser(dateparse_utilsListener): ) -> None: try: txt = ctx.getText().lower() - except: + except Exception: raise ParseException(f'Bad delta before|after: {ctx.getText()}') else: self.context['delta_before_after'] = txt @@ -672,7 +685,7 @@ class DateParser(dateparse_utilsListener): ) -> None: try: txt = ctx.getText().lower() - except: + except Exception: raise ParseException(f'Bad delta before|after: {ctx.getText()}') else: self.context['time_delta_before_after'] = txt @@ -732,7 +745,7 @@ class DateParser(dateparse_utilsListener): self.context['month'] = month self.context['day'] = 1 self.main_type = DateParser.PARSE_TYPE_BASE_AND_OFFSET_EXPR - except: + except Exception: raise ParseException( f'Invalid nthWeekday expression: {ctx.getText()}' ) @@ -746,7 +759,7 @@ class DateParser(dateparse_utilsListener): def exitNth(self, ctx: dateparse_utilsParser.NthContext) -> None: try: i = self._get_int(ctx.getText()) - except: + except Exception: raise ParseException(f'Bad nth expression: {ctx.getText()}') else: self.context['nth'] = i @@ -764,7 +777,7 @@ class DateParser(dateparse_utilsListener): raise ParseException( f'Bad first|last expression: {ctx.getText()}' ) - except: + except Exception: raise ParseException(f'Bad first|last expression: {ctx.getText()}') else: self.context['nth'] = txt @@ -773,7 +786,7 @@ class DateParser(dateparse_utilsListener): try: dow = ctx.getText().lower()[:3] dow = self.day_name_to_number.get(dow, None) - except: + except Exception: raise ParseException('Bad day of week') else: self.context['dow'] = dow @@ -797,7 +810,7 @@ class DateParser(dateparse_utilsListener): raise ParseException( f'Bad dayOfMonth expression: {ctx.getText()}' ) - except: + except Exception: raise ParseException(f'Bad dayOfMonth expression: {ctx.getText()}') self.context['day'] = day @@ -814,7 +827,7 @@ class DateParser(dateparse_utilsListener): raise ParseException( f'Bad monthName expression: {ctx.getText()}' ) - except: + except Exception: raise ParseException(f'Bad monthName expression: {ctx.getText()}') else: self.context['month'] = month @@ -828,7 +841,7 @@ class DateParser(dateparse_utilsListener): raise ParseException( f'Bad monthNumber expression: {ctx.getText()}' ) - except: + except Exception: raise ParseException( f'Bad monthNumber expression: {ctx.getText()}' ) @@ -840,9 +853,10 @@ class DateParser(dateparse_utilsListener): year = self._get_int(ctx.getText()) if year < 1: raise ParseException(f'Bad year expression: {ctx.getText()}') - except: + except Exception: raise ParseException(f'Bad year expression: {ctx.getText()}') else: + self.saw_overt_year = True self.context['year'] = year def exitSpecialDateMaybeYearExpr( @@ -851,7 +865,7 @@ class DateParser(dateparse_utilsListener): try: special = ctx.specialDate().getText().lower() self.context['special'] = special - except: + except Exception: raise ParseException( f'Bad specialDate expression: {ctx.specialDate().getText()}' ) @@ -864,7 +878,7 @@ class DateParser(dateparse_utilsListener): self.context['special_next_last'] = 'next' elif mod.LAST() is not None: self.context['special_next_last'] = 'last' - except: + except Exception: raise ParseException( f'Bad specialDateNextLast expression: {ctx.getText()}' ) @@ -877,7 +891,7 @@ class DateParser(dateparse_utilsListener): count = self._get_int(ctx.unsignedInt().getText()) unit = ctx.deltaUnit().getText().lower() ago_from_now = ctx.AGO_FROM_NOW().getText() - except: + except Exception: raise ParseException( f'Bad NFoosFromTodayAgoExpr: {ctx.getText()}' ) @@ -888,7 +902,7 @@ class DateParser(dateparse_utilsListener): unit = self._figure_out_date_unit(unit) d = n_timeunits_from_base( count, - unit, + TimeUnit(unit), d) self.context['year'] = d.year self.context['month'] = d.month @@ -911,14 +925,14 @@ class DateParser(dateparse_utilsListener): f'Bad This/Next/Last modifier: {mod}' ) unit = ctx.deltaUnit().getText().lower() - except: + except Exception: raise ParseException( f'Bad DeltaRelativeToTodayExpr: {ctx.getText()}' ) unit = self._figure_out_date_unit(unit) d = n_timeunits_from_base( count, - unit, + TimeUnit(unit), d) self.context['year'] = d.year self.context['month'] = d.month @@ -929,7 +943,7 @@ class DateParser(dateparse_utilsListener): ) -> None: try: txt = ctx.specialTime().getText().lower() - except: + except Exception: raise ParseException( f'Bad special time expression: {ctx.getText()}' ) @@ -950,7 +964,7 @@ class DateParser(dateparse_utilsListener): try: tz = ctx.tzExpr().getText() self.context['tz'] = self._parse_tz(tz) - except: + except Exception: pass def exitTwelveHourTimeExpr( @@ -961,14 +975,14 @@ class DateParser(dateparse_utilsListener): while not hour[-1].isdigit(): hour = hour[:-1] hour = self._get_int(hour) - except: + except Exception: raise ParseException(f'Bad hour: {ctx.hour().getText()}') if hour <= 0 or hour > 12: raise ParseException(f'Bad hour (out of range): {hour}') try: minute = self._get_int(ctx.minute().getText()) - except: + except Exception: minute = 0 if minute < 0 or minute > 59: raise ParseException(f'Bad minute (out of range): {minute}') @@ -976,7 +990,7 @@ class DateParser(dateparse_utilsListener): try: seconds = self._get_int(ctx.second().getText()) - except: + except Exception: seconds = 0 if seconds < 0 or seconds > 59: raise ParseException(f'Bad second (out of range): {seconds}') @@ -984,7 +998,7 @@ class DateParser(dateparse_utilsListener): try: micros = self._get_int(ctx.micros().getText()) - except: + except Exception: micros = 0 if micros < 0 or micros > 1000000: raise ParseException(f'Bad micros (out of range): {micros}') @@ -992,7 +1006,7 @@ class DateParser(dateparse_utilsListener): try: ampm = ctx.ampm().getText() - except: + except Exception: raise ParseException(f'Bad ampm: {ctx.ampm().getText()}') if hour == 12: hour = 0 @@ -1003,7 +1017,7 @@ class DateParser(dateparse_utilsListener): try: tz = ctx.tzExpr().getText() self.context['tz'] = self._parse_tz(tz) - except: + except Exception: pass def exitTwentyFourHourTimeExpr( @@ -1014,7 +1028,7 @@ class DateParser(dateparse_utilsListener): while not hour[-1].isdigit(): hour = hour[:-1] hour = self._get_int(hour) - except: + except Exception: raise ParseException(f'Bad hour: {ctx.hour().getText()}') if hour < 0 or hour > 23: raise ParseException(f'Bad hour (out of range): {hour}') @@ -1022,7 +1036,7 @@ class DateParser(dateparse_utilsListener): try: minute = self._get_int(ctx.minute().getText()) - except: + except Exception: minute = 0 if minute < 0 or minute > 59: raise ParseException(f'Bad minute (out of range): {ctx.getText()}') @@ -1030,7 +1044,7 @@ class DateParser(dateparse_utilsListener): try: seconds = self._get_int(ctx.second().getText()) - except: + except Exception: seconds = 0 if seconds < 0 or seconds > 59: raise ParseException(f'Bad second (out of range): {ctx.getText()}') @@ -1038,7 +1052,7 @@ class DateParser(dateparse_utilsListener): try: micros = self._get_int(ctx.micros().getText()) - except: + except Exception: micros = 0 if micros < 0 or micros >= 1000000: raise ParseException(f'Bad micros (out of range): {ctx.getText()}') @@ -1047,7 +1061,7 @@ class DateParser(dateparse_utilsListener): try: tz = ctx.tzExpr().getText() self.context['tz'] = self._parse_tz(tz) - except: + except Exception: pass