// Path: src/main/java/org/gbif/common/parsers/core/ParseResult.java
// public class ParseResult<T> {
// 
//   // the result code of the parse operation
//   public enum STATUS {
//     SUCCESS, FAIL, ERROR
//   }
// 
//   // the confidence of the result, applicable if status=SUCCESS
//   public enum CONFIDENCE {
//     DEFINITE, PROBABLE, POSSIBLE
//   }
// 
//   // the details of the response
//   protected final STATUS status;
//   protected final CONFIDENCE confidence;
//   protected final T payload;
//   protected final List<T> alternativePayloads;
//   protected final Throwable error;
// 
//   /**
//    * @param <T1>       The generic type of the payload
//    * @param confidence The confidence in the result
//    * @param payload    The payload of the parse result
//    *
//    * @return The new ParseResult which has no error and status of SUCCESS
//    */
//   public static <T1> ParseResult<T1> success(CONFIDENCE confidence, T1 payload) {
//     return new ParseResult<T1>(STATUS.SUCCESS, confidence, payload, null, null);
//   }
// 
//   /**
//    * @return A new parse response with only the status set to FAIL
//    */
//   public static <T1> ParseResult<T1> fail() {
//     return new ParseResult<T1>(STATUS.FAIL, null, null, null, null);
//   }
// 
//   /**
//    * @return A new parse response configured to indicate an error
//    */
//   public static <T1> ParseResult<T1> error() {
//     return new ParseResult<T1>(STATUS.ERROR, null, null, null, null);
//   }
// 
//   /**
//    * @param cause The cause of the error
//    *
//    * @return A new parse response configured with error and the cause
//    */
//   public static <T1> ParseResult<T1> error(Throwable cause) {
//     return new ParseResult<T1>(STATUS.ERROR, null, null, null, cause);
//   }
// 
//   /**
//    * Forces all fields to be provided
//    *
//    * @param status     The status of the response
//    * @param confidence The confidence in the result
//    * @param payload    The payload of the response
//    * @param error      The error in the response
//    */
//   public ParseResult(STATUS status, CONFIDENCE confidence, T payload, List<T> alternativePayloads, Throwable error) {
//     this.status = status;
//     this.confidence = confidence;
//     this.alternativePayloads = alternativePayloads;
//     this.payload = payload;
//     this.error = error;
//   }
// 
//   public STATUS getStatus() {
//     return status;
//   }
// 
//   public CONFIDENCE getConfidence() {
//     return confidence;
//   }
// 
//   public T getPayload() {
//     return payload;
//   }
// 
//   public List<T> getAlternativePayloads() {
//     return alternativePayloads;
//   }
// 
//   public Throwable getError() {
//     return error;
//   }
// 
//   /**
//    * Returns true if {@link #getStatus()} returns SUCCESS.
//    *
//    * @return true if the parse operation was successful.
//    */
//   public boolean isSuccessful() {
//     return status == STATUS.SUCCESS;
//   }
// 
//   @Override
//   public String toString() {
//     return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
//       .append("status", getStatus())
//       .append("confidence", getConfidence())
//       .append("payload", getPayload())
//       .append("alternativePayloads", getAlternativePayloads())
//       .append("error", getError()).toString();
//   }
// }


import org.gbif.common.parsers.core.ParseResult;
import java.io.Serializable;
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.temporal.TemporalAccessor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
      matcher = ISO_DATE_RANGE_PATTERN.matcher(input);
    }

    if (matcher.matches()) {
      String from = matcher.group(1);
      // String to = matcher.group(2);
      return NUMERICAL_DATE_PARSER.parse(from, DateComponentOrdering.ISO_ETC);
    }

    // Check if the input text contains only punctuations and numbers
    // Also accept the T marker (e.g. 1978-12-21T02:12) from the ISO format
    // and the W week marker (e.g. 2018-W43).
    // We could also simply try to parse it but it is probably not optimal
    if (NUMERICAL_DATE_PATTERN.matcher(input).matches()) {
      return NUMERICAL_DATE_PARSER.parse(input, DateComponentOrdering.ISO_ETC);
    }

    TextualMonthDateTokenizer.DateTokens dt = TEXT_MONTH_TOKENIZER.tokenize(input);
    // for now we only handle cases where we can find year, month, day with confidence.
    if (!dt.containsDiscardedTokens() && dt.size() == 3) {
      DatePartsNormalizer.NormalizedYearMonthDay normalizedYearMonthDay = DATE_PARTS_NORMALIZER.normalize(
        dt.getToken(TextualMonthDateTokenizer.TokenType.INT_4).getToken(),
        dt.getToken(TextualMonthDateTokenizer.TokenType.TEXT).getToken(),
        dt.getToken(TextualMonthDateTokenizer.TokenType.INT_2).getToken());

      // no handling for partial dates with textual month for now
      if (normalizedYearMonthDay.getYear() != null &&
        normalizedYearMonthDay.getMonth() != null &&
        normalizedYearMonthDay.getDay() != null) {
        try {
// Path: src/main/java/org/gbif/common/parsers/core/ParseResult.java
// public class ParseResult<T> {
// 
//   // the result code of the parse operation
//   public enum STATUS {
//     SUCCESS, FAIL, ERROR
//   }
// 
//   // the confidence of the result, applicable if status=SUCCESS
//   public enum CONFIDENCE {
//     DEFINITE, PROBABLE, POSSIBLE
//   }
// 
//   // the details of the response
//   protected final STATUS status;
//   protected final CONFIDENCE confidence;
//   protected final T payload;
//   protected final List<T> alternativePayloads;
//   protected final Throwable error;
// 
//   /**
//    * @param <T1>       The generic type of the payload
//    * @param confidence The confidence in the result
//    * @param payload    The payload of the parse result
//    *
//    * @return The new ParseResult which has no error and status of SUCCESS
//    */
//   public static <T1> ParseResult<T1> success(CONFIDENCE confidence, T1 payload) {
//     return new ParseResult<T1>(STATUS.SUCCESS, confidence, payload, null, null);
//   }
// 
//   /**
//    * @return A new parse response with only the status set to FAIL
//    */
//   public static <T1> ParseResult<T1> fail() {
//     return new ParseResult<T1>(STATUS.FAIL, null, null, null, null);
//   }
// 
//   /**
//    * @return A new parse response configured to indicate an error
//    */
//   public static <T1> ParseResult<T1> error() {
//     return new ParseResult<T1>(STATUS.ERROR, null, null, null, null);
//   }
// 
//   /**
//    * @param cause The cause of the error
//    *
//    * @return A new parse response configured with error and the cause
//    */
//   public static <T1> ParseResult<T1> error(Throwable cause) {
//     return new ParseResult<T1>(STATUS.ERROR, null, null, null, cause);
//   }
// 
//   /**
//    * Forces all fields to be provided
//    *
//    * @param status     The status of the response
//    * @param confidence The confidence in the result
//    * @param payload    The payload of the response
//    * @param error      The error in the response
//    */
//   public ParseResult(STATUS status, CONFIDENCE confidence, T payload, List<T> alternativePayloads, Throwable error) {
//     this.status = status;
//     this.confidence = confidence;
//     this.alternativePayloads = alternativePayloads;
//     this.payload = payload;
//     this.error = error;
//   }
// 
//   public STATUS getStatus() {
//     return status;
//   }
// 
//   public CONFIDENCE getConfidence() {
//     return confidence;
//   }
// 
//   public T getPayload() {
//     return payload;
//   }
// 
//   public List<T> getAlternativePayloads() {
//     return alternativePayloads;
//   }
// 
//   public Throwable getError() {
//     return error;
//   }
// 
//   /**
//    * Returns true if {@link #getStatus()} returns SUCCESS.
//    *
//    * @return true if the parse operation was successful.
//    */
//   public boolean isSuccessful() {
//     return status == STATUS.SUCCESS;
//   }
// 
//   @Override
//   public String toString() {
//     return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
//       .append("status", getStatus())
//       .append("confidence", getConfidence())
//       .append("payload", getPayload())
//       .append("alternativePayloads", getAlternativePayloads())
//       .append("error", getError()).toString();
//   }
// }


// Path: src/main/java/org/gbif/common/parsers/date/TextDateParser.java
import org.gbif.common.parsers.core.ParseResult;
import java.io.Serializable;
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.temporal.TemporalAccessor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;

      matcher = ISO_DATE_RANGE_PATTERN.matcher(input);
    }

    if (matcher.matches()) {
      String from = matcher.group(1);
      // String to = matcher.group(2);
      return NUMERICAL_DATE_PARSER.parse(from, DateComponentOrdering.ISO_ETC);
    }

    // Check if the input text contains only punctuations and numbers
    // Also accept the T marker (e.g. 1978-12-21T02:12) from the ISO format
    // and the W week marker (e.g. 2018-W43).
    // We could also simply try to parse it but it is probably not optimal
    if (NUMERICAL_DATE_PATTERN.matcher(input).matches()) {
      return NUMERICAL_DATE_PARSER.parse(input, DateComponentOrdering.ISO_ETC);
    }

    TextualMonthDateTokenizer.DateTokens dt = TEXT_MONTH_TOKENIZER.tokenize(input);
    // for now we only handle cases where we can find year, month, day with confidence.
    if (!dt.containsDiscardedTokens() && dt.size() == 3) {
      DatePartsNormalizer.NormalizedYearMonthDay normalizedYearMonthDay = DATE_PARTS_NORMALIZER.normalize(
        dt.getToken(TextualMonthDateTokenizer.TokenType.INT_4).getToken(),
        dt.getToken(TextualMonthDateTokenizer.TokenType.TEXT).getToken(),
        dt.getToken(TextualMonthDateTokenizer.TokenType.INT_2).getToken());

      // no handling for partial dates with textual month for now
      if (normalizedYearMonthDay.getYear() != null &&
        normalizedYearMonthDay.getMonth() != null &&
        normalizedYearMonthDay.getDay() != null) {
        try {
          return ParseResult.success(ParseResult.CONFIDENCE.DEFINITE,