docs: def str_to_datetime(ts):
      """Format a string to a datetime object.
  
      This functions supports several date formats like YYYY-MM-DD,
      MM-DD-YYYY, YY-MM-DD, YYYY-MM-DD HH:mm:SS +HH:MM, among others.
      When the timezone is not provided, UTC+0 will be set as default
      (using `dateutil.tz.tzutc` object).
  
      :param ts: string to convert
  
      :returns: a datetime object
  
      :raises IvalidDateError: when the given string cannot be converted
          on a valid date
      """
      def parse_datetime(ts):
          dt = dateutil.parser.parse(ts)
          if not dt.tzinfo:
              dt = dt.replace(tzinfo=dateutil.tz.tzutc())
          return dt
  
      if not ts:
          raise InvalidDateError(date=str(ts))
  
      try:
          # Try to remove additional information after
          # timezone section because it cannot be parsed,
          # like in 'Wed, 26 Oct 2005 15:20:32 -0100 (GMT+1)'
          # or in 'Thu, 14 Aug 2008 02:07:59 +0200 CEST'.
          m = re.search(r"^.+?\s+[\+\-\d]\d{4}(\s+.+)$", ts)
          if m:
              ts = ts[:m.start(1)]
  
          try:
              dt = parse_datetime(ts)
          except ValueError as e:
              # Try to remove the timezone, usually it causes
              # problems.
              m = re.search(r"^(.+?)\s+[\+\-\d]\d{4}.*$", ts)
  
              if m:
                  dt = parse_datetime(m.group(1))
                  logger.warning("Date %s str does not have a valid timezone", ts)
                  logger.warning("Date converted removing timezone info")
                  return dt
  
              raise e
  
          return dt
  
      except ValueError as e:
          raise InvalidDateError(date=str(ts))