docs: def _parse_date(self, date_info: dict) -> Extraction or None:
          """
          parse a date string extracted to a datetime.datetime object
          apply the customizations like date range, date completion etc.
  
          """
  
          user_defined_pattern = None
  
          if date_info['pattern']:
              user_defined_pattern = re.findall(r'%[a-zA-Z]', date_info['pattern'])
  
          miss_day = miss_month = miss_year = miss_week = True
  
          i = 0
          pattern = list()
          formatted = list()
  
          for s in date_info['groups']:
              if s:
                  p = self._symbol_list[date_info['order']][i] if not user_defined_pattern else user_defined_pattern[i]
                  if p in units['D']:
                      miss_day = False
                  elif p in units['M']:
                      miss_month = False
                  elif p in units['Y']:
                      miss_year = False
                  elif p in units['W']:
                      miss_week = False
                  formatted_str = s.strip('.').strip().lower()
                  if p in ['%B', '%b', '%A', '%a']:
                      if formatted_str in foreign_to_english:
                          # TODO: rearrange language detection in a better way
                          if self._lan == 'en':
                              continue
                          formatted_str = foreign_to_english[formatted_str]
                  if p in ['%b', '%a']:
                      formatted_str = formatted_str[:3]
                  formatted.append(re.sub(r'[^0-9+\-]', '', formatted_str) if p == '%z' else formatted_str)
                  pattern.append(p)
              i += 1
  
          # TODO: deduplicate in the regex extraction part would be better
          exist, new_formatted, new_pattern = set(), [], []
          for i in range(len(pattern)):
              if pattern[i] not in exist:
                  if re.match(r'[a-zA-Z]', formatted[i]) and pattern[i] == '%a':
                      miss_week = True
                  else:
                      new_pattern.append(pattern[i])
                      new_formatted.append(formatted[i])
                      exist.add(pattern[i])
          formatted, pattern = new_formatted, new_pattern
  
          if formatted and pattern:
              try:
                  if self._settings[DATE_VALUE_RESOLUTION] == DateResolution.ORIGINAL:
                      self._settings[MIN_RESOLUTION] = DateResolutionHelper.min_resolution(pattern)
                  date = datetime.datetime.strptime('-'.join(formatted), '-'.join(pattern))
              except ValueError:
                  try:
                      date = datetime.datetime.strptime('-'.join(formatted[:-1]), '-'.join(pattern[:-1]))
                  except ValueError:
                      warn('DateExtractor: Failed to parse string to datetime object. \n'
                           'Patterns are not matched with string or the formats are not supported. ' +
                           '-'.join(formatted) + ' with ' + '-'.join(pattern))
                      return None
  
              if miss_year and miss_month and miss_day:
                  today = datetime.datetime.now()
                  if miss_week:
                      date = date.replace(day=today.day, month=today.month, year=today.year)
                  else:
                      date = today
                      week_of_day = formatted[0].strip().lower()
                      if week_of_day in foreign_to_english:
                          week_of_day = foreign_to_english[week_of_day]
                      target = day_of_week_to_number[week_of_day] if week_of_day in day_of_week_to_number \
                          else today.weekday()
                      if self._settings[PREFER_DATES_FROM] == 'past':
                          date = date + relativedelta(days=-(date.weekday()+7-target)%7)
                      elif self._settings[PREFER_DATES_FROM] == 'future':
                          date = date + relativedelta(days=(target+7-date.weekday())%7)
                      else:
                          delta = target - date.weekday()
                          if abs(delta) <= 3:
                              date = date + relativedelta(days=delta)
                          else:
                              date = date + relativedelta(days=delta-7)
  
              else:
                  if miss_day:
                      last = calendar.monthrange(date.year, date.month)[1]
                      if self._settings[PREFER_DAY_OF_MONTH] == 'current':
                          cur = datetime.datetime.now().day
                          date = date.replace(day=cur if cur <= last else last)
                      elif self._settings[PREFER_DAY_OF_MONTH] == 'last':
                          date = date.replace(day=last)
  
                  if miss_year:
                      today = datetime.datetime.now()
                      date = date.replace(year=today.year)
                      next_year = date.replace(year=today.year+1)
                      last_year = date.replace(year=today.year-1)
                      if self._settings[PREFER_DATES_FROM] == 'past':
                          date = last_year if date > today else date
                      elif self._settings[PREFER_DATES_FROM] == 'future':
                          date = next_year if date < today else date
                      else:
                          if date > today and (date-today > today-last_year):
                              date = last_year
                          elif date < today and (today-date > next_year-today):
                              date = next_year
  
              date = self._post_process_date(date)
  
              if date:
                  return self._wrap_extraction(date, date_info['value'], date_info['start'], date_info['end'])
          return None