+ def _parse_tz(self, txt: str) -> Any:
+ if txt == 'Z':
+ txt = 'UTC'
+
+ # Try pytz
+ try:
+ tz = pytz.timezone(txt)
+ if tz is not None:
+ return tz
+ except Exception:
+ pass
+
+ # Try dateutil
+ try:
+ tz = dateutil.tz.gettz(txt)
+ if tz is not None:
+ return tz
+ except Exception:
+ pass
+
+ # Try constructing an offset in seconds
+ try:
+ sign = txt[0]
+ if sign == '-' or sign == '+':
+ sign = +1 if sign == '+' else -1
+ hour = int(txt[1:3])
+ minute = int(txt[-2:])
+ offset = sign * (hour * 60 * 60) + sign * (minute * 60)
+ tzoffset = dateutil.tz.tzoffset(txt, offset)
+ return tzoffset
+ except Exception:
+ pass
+ return None
+
+ def _get_int(self, txt: str) -> int:
+ while not txt[0].isdigit() and txt[0] != '-' and txt[0] != '+':
+ txt = txt[1:]
+ while not txt[-1].isdigit():
+ txt = txt[:-1]
+ return int(txt)
+
+ # -- overridden methods invoked by parse walk --
+
+ def visitErrorNode(self, node: antlr4.ErrorNode) -> None:
+ pass
+
+ def visitTerminal(self, node: antlr4.TerminalNode) -> None:
+ pass
+
+ def exitParse(self, ctx: dateparse_utilsParser.ParseContext) -> None:
+ """Populate self.datetime."""
+ if self.date is None:
+ self.date = self.today
+ year = self.date.year
+ month = self.date.month
+ day = self.date.day
+
+ if self.time is None:
+ self.time = datetime.time(0, 0, 0)
+ hour = self.time.hour
+ minute = self.time.minute
+ second = self.time.second
+ micros = self.time.microsecond
+
+ self.datetime = datetime.datetime(
+ year, month, day, hour, minute, second, micros,
+ tzinfo=self.time.tzinfo
+ )
+
+ # Apply resudual adjustments to times here when we have a
+ # datetime.
+ self.datetime = self.datetime + self.timedelta
+ self.time = datetime.time(
+ self.datetime.hour,
+ self.datetime.minute,
+ self.datetime.second,
+ self.datetime.microsecond,
+ self.datetime.tzinfo
+ )
+
+ def enterDateExpr(self, ctx: dateparse_utilsParser.DateExprContext):
+ self.date = None
+ if ctx.singleDateExpr() is not None:
+ self.main_type = DateParser.PARSE_TYPE_SINGLE_DATE_EXPR
+ elif ctx.baseAndOffsetDateExpr() is not None:
+ self.main_type = DateParser.PARSE_TYPE_BASE_AND_OFFSET_EXPR
+
+ def enterTimeExpr(self, ctx: dateparse_utilsParser.TimeExprContext):
+ self.time = None
+ if ctx.singleTimeExpr() is not None:
+ self.time_type = DateParser.PARSE_TYPE_SINGLE_TIME_EXPR
+ elif ctx.baseAndOffsetTimeExpr() is not None:
+ self.time_type = DateParser.PARSE_TYPE_BASE_AND_OFFSET_TIME_EXPR
+