Cómo comprobar si la cadena de partidos de la fecha en que el patrón de uso de la API de tiempo?

Mi programa es el análisis de una cadena de entrada a un LocalDate objeto. Para la mayoría de las veces la cadena parece 30.03.2014, pero de vez en cuando parece que 3/30/2014. Dependiendo de cual, necesito usar un patrón diferente para llamar DateTimeFormatter.ofPattern(String pattern) con. Básicamente, necesito comprobar si la cadena coincide con el patrón de dd.MM.yyyy o M/dd/yyyy antes de hacer el análisis.

El regex enfoque sería algo así como:

LocalDate date;
if (dateString.matches("^\\d?\\d/\\d{2}/\\d{4}$")) {
  date = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("M/dd/yyyy"));  
} else {
  date = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("dd.MM.yyyy"));  
}

Esto funciona, pero sería bueno utilizar la fecha de la cadena de patrón cuando la coincidencia de la cadena también.

Hay ningún estándar de maneras de hacer esto con el nuevo Java 8 de la API de tiempo, sin tener que recurrir a expresiones de coincidencia? Me he mirado en el google docs para DateTimeFormatter, pero no pude encontrar nada.

  • ¿Por qué no te la cadena de replace("//", ".") ?
  • Creo que no hay un método específico para comprobar si una fecha sigue un patrón determinado. Me gustaría utilizar el SimpleDateFormat.método parse y un ParseException. En caso de que usted está seguro de que la fecha es correcta y está en uno de los dos patrones, usted puede comprobar si hay ‘.’ en la cadena.
  • Debido a que el mes y el día no se coloca en el mismo lugar en ambos patrones.
  • Yo no soy de publicar esto como una respuesta porque no sé si va a ser una opción viable para usted para crear una clase para ello. Es? Como este: tryjava8.com/app/snippets/5368a343e4b0753f2af0f806
  • La clase SimpleDateFormat directamente no se puede analizar a un LocalDate, sólo para java.util.Date que es muy diferente.
  • Esa es una posible solución, si no hay otras soluciones que ya existe. Favor de hacer post como una respuesta de todos modos. Por CIERTO, ese sitio que enlaza error cuando me encontré con el ejemplo.
  • Mira mi respuesta actualizada, puede ser sencillo que crear una clase para eso.
  • Gracias, esa es una buena solución.

InformationsquelleAutor | 2014-05-06

2 Kommentare

  1. 13

    Bueno me voy por delante y publicarla como una respuesta. Una forma es crear la clase que contiene los patrones.

    public class Test {
        public static void main(String[] args){
            MyFormatter format = new MyFormatter("dd.MM.yyyy", "M/dd/yyyy");
            LocalDate  date = format.parse("3/30/2014"); //2014-03-30
            LocalDate  date2 = format.parse("30.03.2014"); //2014-03-30
        }
    }
    
    class MyFormatter {
        private final String[] patterns;
    
        public MyFormatter(String... patterns){
            this.patterns = patterns;
        }
    
        public LocalDate parse(String text){
            for(int i = 0; i < patterns.length; i++){
                try{
                    return LocalDate.parse(text, DateTimeFormatter.ofPattern(patterns[i]));
                }catch(DateTimeParseException excep){}
            }
            throw new IllegalArgumentException("Not able to parse the date for all patterns given");
        }
    }

    Podría mejorar esta como @MenoHochschild hizo directamente la creación de una matriz de DateTimeFormatter de la matriz de String pasa en el constructor.


    Otra forma sería utilizar un DateTimeFormatterBuilder, anexando los formatos que desee. Puede que existe otras formas de hacerlo, yo no ir profundamente a través de la documentación 🙂

    DateTimeFormatter dfs = new DateTimeFormatterBuilder()
                               .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd"))                                                                 
                               .appendOptional(DateTimeFormatter.ofPattern("dd.MM.yyyy"))                                                                                     
                               .toFormatter();
    LocalDate d = LocalDate.parse("2014-05-14", dfs); //2014-05-14
    LocalDate d2 = LocalDate.parse("14.05.2014", dfs); //2014-05-14
    • La segunda de las Opciones funciona genial, sin manejo de excepciones etc.
  2. 1

    El enfoque de @ZouZou es una posible solución.

    Con el fin de evitar el uso de excepciones para el programa de lógica tanto como sea posible (también no tan agradable performancewise) siguiente alternativa podría ser considerado:

    static final String[] PATTERNS = {"dd.MM.yyyy", "M/dd/yyyy"};
    static final DateTimeFormatter[] FORMATTERS = new DateTimeFormatter[PATTERNS.length];
    
    static {
      for (int i = 0; i < PATTERNS.length; i++) {
        FORMATTERS[i] = DateTimeFormatter.ofPattern(PATTERNS[i]);
      }
    }
    
    public static LocalDate parse(String input) {
      ParsePosition pos = new ParsePosition();
      for (int i = 0; i < patterns.length; i++) {
        try {
          TemporalAccessor tacc = FORMATTERS[i].parseUnresolved(input, pos);
          if (pos.getErrorIndex < 0) {
            return LocalDate.from(tacc); //possibly throwing DateTimeException => validation failure
          }
        } catch (DateTimeException ex) { //catches also possible DateTimeParseException
          //go to next pattern
        }
        pos.setIndex(0);
        pos.setErrorIndex(-1);
      }
      throw new IllegalArgumentException("Input does not match any pattern: " + input);
    }

    Una explicación más detallada sobre el método de parseUnresolved():

    Este método no sólo la primera fase de análisis, por lo que no hay una segunda fase que contiene la validación preliminar o la combinación de esfuerzo de analizar los campos. Sin embargo, LocalDate.from() no validar cada entrada, así que creo que esto es todavía suficiente. Y la ventaja es que parseUnresolved() utiliza el índice de error de ParsePosition. Esto está de acuerdo con la tradicional java.text.Format-comportamiento.

    Por desgracia, la alternativa y la más intuitiva método DateTimeFormater.parse(), primero se crea un DateTimeParseException y, a continuación, guarde el error de índice en esta excepción. Así que me decidí a no utilizar este método con el fin de evitar la creación de un innecesario excepción. Para mí, esta API-detalle es cuestionable la decisión de diseño.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea