Cómo verificar la cordura de una fecha en Java [cerrado]

83

Me parece curioso que la forma más obvia de crear Dateobjetos en Java haya quedado obsoleta y parece haber sido "sustituida" por un calendario poco obvio de usar.

¿Cómo se comprueba que una fecha, dada como una combinación de día, mes y año, es una fecha válida?

Por ejemplo, 2008-02-31 (como en aaaa-mm-dd) sería una fecha no válida.

Hervidor de sangre
fuente
Para cualquier persona con una pregunta similar, considere si necesita soporte de calendario no gregoriano.
MSalters
@JasonC Estoy completamente de acuerdo contigo, fusionarlos parece la mejor manera de hacerlo.
acm

Respuestas:

37

La forma actual es usar la clase de calendario. Tiene el método setLenient que validará la fecha y lanzará una excepción si está fuera de rango como en su ejemplo.

Olvidé agregar: Si obtiene una instancia de calendario y establece la hora usando su fecha, así es como obtiene la validación.

Calendar cal = Calendar.getInstance();
cal.setLenient(false);
cal.setTime(yourDate);
try {
    cal.getTime();
}
catch (Exception e) {
  System.out.println("Invalid date");
}
AdamC
fuente
2
no creo que esto funcione exactamente como está. Calendar.setTime toma java.util.Date, por lo que la conversión de la cadena ya ha ocurrido cuando obtiene un objeto "yourDate".
tardate
32
3 problemas con el código de ejemplo: 1. Después de obtener una instancia de Calendar, debe llamar a cal.setLenient (false). De lo contrario, una fecha como el 31 de febrero de 2007 se considerará válida. 2. Cal.setTime () no lanza una excepción. Debe llamar a cal.getTime () después de la llamada setTime (), que arroja una excepción en una fecha no válida. 3. Error tipográfico: Falta un '}' antes de la captura.
Liron Yahdav
Esto también es más lento que otros enfoques. Ver stackoverflow.com/questions/2149680/…
despot
5
Para su información, las problemáticas clases antiguas de fecha y hora como java.util.Date, java.util.Calendary java.text.SimpleDateFormatahora son heredadas , suplantadas por las clases java.time integradas en Java 8 y posteriores. Consulte el tutorial de Oracle .
Basil Bourque
3
no valida fechas como 31 de febrero
shikha singh
78

La clave es df.setLenient (falso); . Esto es más que suficiente para casos simples. Si está buscando una biblioteca más robusta (lo dudo) y / o alternativas como joda-time, mire la respuesta del usuario "tardate"

final static String DATE_FORMAT = "dd-MM-yyyy";

public static boolean isDateValid(String date) 
{
        try {
            DateFormat df = new SimpleDateFormat(DATE_FORMAT);
            df.setLenient(false);
            df.parse(date);
            return true;
        } catch (ParseException e) {
            return false;
        }
}
Aravind Yarram
fuente
2
Pruebe con "09-04-201a". Creará una cita loca.
ceklock
@ceklock esa es la forma en que funciona, no importa si usa setLeniento no: SimpleDateFormatsiempre analizará hasta que el patrón coincida e ignorará el resto de la cadena, por lo que obtendrá 201como año.
Daniel Naber
@ceklock Lo acabo de abordar en mi solución . Puede ahorrar uno o dos minutos para alguien.
Sufian
1
La incorporación del manejo de excepciones implica un gran impacto en el rendimiento, por lo que probablemente este sea un mal diseño SI espera una entrada mal formada en la operación normal (por ejemplo, validando la entrada del usuario). Pero si el método se usa como una doble verificación de las entradas que se supone que son válidas todo el tiempo (excepto para los errores), está bien.
Aaron
2
Para su información, las clases de fecha y hora antiguas terriblemente problemáticas como java.util.Date, java.util.Calendary java.text.SimpleDateFormatahora son heredadas , suplantadas por las clases java.time integradas en Java 8 y versiones posteriores. Consulte el tutorial de Oracle .
Basil Bourque
48

Como lo muestra @Maglob, el enfoque básico es probar la conversión de cadena a fecha usando SimpleDateFormat.parse . Eso detectará combinaciones inválidas de día / mes como 2008-02-31.

Sin embargo, en la práctica, eso rara vez es suficiente, ya que SimpleDateFormat.parse es extremadamente liberal. Hay dos comportamientos que pueden preocuparle:

Caracteres no válidos en la cadena de fecha Sorprendentemente, 2008-02-2x "pasará" como una fecha válida con el formato local = "aaaa-MM-dd", por ejemplo. Incluso cuando isLenient == false.

Años: ¿2, 3 o 4 dígitos? También es posible que desee aplicar años de 4 dígitos en lugar de permitir el comportamiento predeterminado de SimpleDateFormat (que interpretará "12-02-31" de manera diferente dependiendo de si su formato era "aaaa-MM-dd" o "aa-MM-dd" )

Una solución estricta con la biblioteca estándar

Entonces, una prueba de cadena completa hasta la fecha podría verse así: una combinación de coincidencia de expresiones regulares y luego una conversión de fecha forzada. El truco con la expresión regular es hacerlo compatible con la configuración regional.

  Date parseDate(String maybeDate, String format, boolean lenient) {
    Date date = null;

    // test date string matches format structure using regex
    // - weed out illegal characters and enforce 4-digit year
    // - create the regex based on the local format string
    String reFormat = Pattern.compile("d+|M+").matcher(Matcher.quoteReplacement(format)).replaceAll("\\\\d{1,2}");
    reFormat = Pattern.compile("y+").matcher(reFormat).replaceAll("\\\\d{4}");
    if ( Pattern.compile(reFormat).matcher(maybeDate).matches() ) {

      // date string matches format structure, 
      // - now test it can be converted to a valid date
      SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance();
      sdf.applyPattern(format);
      sdf.setLenient(lenient);
      try { date = sdf.parse(maybeDate); } catch (ParseException e) { }
    } 
    return date;
  } 

  // used like this:
  Date date = parseDate( "21/5/2009", "d/M/yyyy", false);

Tenga en cuenta que la expresión regular asume que la cadena de formato contiene solo día, mes, año y caracteres separadores. Aparte de eso, el formato puede estar en cualquier formato local: "d / MM / aa", "aaaa-MM-dd", etc. La cadena de formato para la configuración regional actual podría obtenerse así:

Locale locale = Locale.getDefault();
SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance(DateFormat.SHORT, locale );
String format = sdf.toPattern();

Joda Time - ¿Mejor alternativa?

He oído hablar de joda time recientemente y pensé en comparar. Dos puntos:

  1. Parece mejor ser estricto con los caracteres no válidos en la cadena de fecha, a diferencia de SimpleDateFormat
  2. Todavía no veo una manera de hacer cumplir años de 4 dígitos con él (pero supongo que podría crear su propio DateTimeFormatter para este propósito)

Es bastante simple de usar:

import org.joda.time.format.*;
import org.joda.time.DateTime;

org.joda.time.DateTime parseDate(String maybeDate, String format) {
  org.joda.time.DateTime date = null;
  try {
    DateTimeFormatter fmt = DateTimeFormat.forPattern(format);
    date =  fmt.parseDateTime(maybeDate);
  } catch (Exception e) { }
  return date;
}
tardate
fuente
Terminé con la alternativa de joda y verifiqué que el valor coincide con la longitud del patrón yo mismo ...
Xtreme Biker
Actualización: Los terribles clases heredadas de edad ( Date, SimpleDateFormat, etc.) ahora son suplantados por los modernos java.time clases. Asimismo, el proyecto Joda-Time está en modo de mantenimiento y aconseja la migración a las clases java.time .
Basil Bourque
38

Puede utilizar SimpleDateFormat

Por ejemplo algo como:

boolean isLegalDate(String s) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    sdf.setLenient(false);
    return sdf.parse(s, new ParsePosition(0)) != null;
}
Maglob
fuente
2
Uno de los problemas con este enfoque es que aceptará 0003-0002-001.
déspota
1
Otro problema es que la configuración de 13 en el mes devuelve una Fecha en la que el mes es 01 del año siguiente.
8bitjunkie
Para su información, las clases de fecha y hora antiguas terriblemente problemáticas como java.util.Date, java.util.Calendary java.text.SimpleDateFormatahora son heredadas , suplantadas por las clases java.time integradas en Java 8 y versiones posteriores. Consulte el tutorial de Oracle .
Basil Bourque
29

tl; dr

Utilice el modo estricto en java.time.DateTimeFormatterllegar a un análisis LocalDate. Trampa para el DateTimeParseException.

LocalDate.parse(                   // Represent a date-only value, without time-of-day and without time zone.
    "31/02/2000" ,                 // Input string.
    DateTimeFormatter              // Define a formatting pattern to match your input string.
    .ofPattern ( "dd/MM/uuuu" )
    .withResolverStyle ( ResolverStyle.STRICT )  // Specify leniency in tolerating questionable inputs.
)

Después de analizar, puede verificar el valor razonable. Por ejemplo, una fecha de nacimiento dentro de los últimos cien años.

birthDate.isAfter( LocalDate.now().minusYears( 100 ) )

Evite las clases de fecha y hora heredadas

Evite el uso de las problemáticas clases de fecha y hora que se incluyen con las primeras versiones de Java. Ahora reemplazado por las clases java.time .

LocalDate& DateTimeFormatter&ResolverStyle

La LocalDateclase representa un valor de solo fecha sin hora del día y sin zona horaria.

String input = "31/02/2000";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "dd/MM/uuuu" );
try {
    LocalDate ld = LocalDate.parse ( input , f );
    System.out.println ( "ld: " + ld );
} catch ( DateTimeParseException e ) {
    System.out.println ( "ERROR: " + e );
}

La java.time.DateTimeFormatterclase se puede configurar para analizar cadenas con cualquiera de los tres modos de indulgencia definidos en la ResolverStyleenumeración. Insertamos una línea en el código anterior para probar cada uno de los modos.

f = f.withResolverStyle ( ResolverStyle.LENIENT );

Los resultados:

  • ResolverStyle.LENIENT
    ld: 2000-03-02
  • ResolverStyle.SMART
    ld: 2000-02-29
  • ResolverStyle.STRICT
    ERROR: java.time.format.DateTimeParseException: No se pudo analizar el texto '31 / 02/2000 ': fecha no válida' 31 DE FEBRERO '

Podemos ver que en el ResolverStyle.LENIENTmodo, la fecha inválida se adelanta un número equivalente de días. En el ResolverStyle.SMARTmodo (el predeterminado), se toma una decisión lógica para mantener la fecha dentro del mes y continuar con el último día posible del mes, el 29 de febrero en un año bisiesto, ya que no hay día 31 en ese mes. El ResolverStyle.STRICTmodo lanza una excepción quejándose de que no existe tal fecha.

Los tres son razonables según el problema y las políticas de su negocio. Parece que, en su caso, desea que el modo estricto rechace la fecha no válida en lugar de ajustarla.


Tabla de todos los tipos de fecha y hora en Java, tanto modernos como heredados.


Acerca de java.time

El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases suplantar la vieja problemáticos heredados clases de fecha y hora como java.util.Date, Calendar, y SimpleDateFormat.

Para obtener más información, consulte el tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No se necesitan cuerdas, no se necesitan java.sql.*clases.

¿Dónde obtener las clases java.time?

Tabla de qué biblioteca java.time usar con qué versión de Java o Android

El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Usted puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuarter, y más .

Albahaca Bourque
fuente
Bueno, suponga que el proyecto se está compilando con java 8+, entonces su respuesta es correcta. También estoy usando estas clases cuando el proyecto está en Java 8. Pero a veces tengo que tocar esos scriptlets jsp antiguos y feos (que ni siquiera son compatibles con Java 7). Validar fechas es un fastidio. Por eso estoy aquí. Sin embargo, su respuesta es el enfoque más correcto ... Conclusión: Estoy jodido.
KarelG
@KarelG Vuelva a leer el penúltimo párrafo sobre el back-port a Java 6 y Java 7 . No he verificado este comportamiento en el back-port, pero le sugiero que lo pruebe.
Basil Bourque
13

java.time

Con la API de fecha y hora ( clases java.time ) integrada en Java 8 y versiones posteriores, puede usar la LocalDateclase.

public static boolean isDateValid(int year, int month, int day) {
    boolean dateIsValid = true;
    try {
        LocalDate.of(year, month, day);
    } catch (DateTimeException e) {
        dateIsValid = false;
    }
    return dateIsValid;
}
Matthias Braun
fuente
2
De forma predeterminada, este código utiliza ResolverStyle.SMARTque ajusta el valor resultante a una fecha válida en lugar de lanzar una excepción. Por lo tanto, este código no logrará el objetivo de la Pregunta. Consulte mi respuesta, por ejemplo, y para obtener una solución ResolverStyle.STRICT.
Basil Bourque
7

Una solución alternativa estricta que utiliza la biblioteca estándar es realizar lo siguiente:

1) Cree un SimpleDateFormat estricto usando su patrón

2) Intente analizar el valor ingresado por el usuario usando el objeto de formato

3) Si tiene éxito, vuelva a formatear la fecha resultante de (2) utilizando el mismo formato de fecha (de (1))

4) Compare la fecha reformateada con el valor original introducido por el usuario. Si son iguales, el valor ingresado coincide estrictamente con su patrón.

De esta manera, no necesita crear expresiones regulares complejas; en mi caso, necesitaba admitir toda la sintaxis de patrones de SimpleDateFormat, en lugar de limitarme a ciertos tipos, como solo días, meses y años.

Ben
fuente
Este es definitivamente el camino a seguir, vea también el código de muestra en dreamincode.net/forums/topic/…
Victor Ionescu
7

Sobre la base de la respuesta de Aravind para solucionar el problema señalado por ceklock en su comentario , agregué un método para verificar que dateStringno contiene ningún carácter no válido.

Así es como lo hago:

private boolean isDateCorrect(String dateString) {
    try {
        Date date = mDateFormatter.parse(dateString);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return matchesOurDatePattern(dateString);    //added my method
    }
    catch (ParseException e) {
        return false;
    }
}

/**
 * This will check if the provided string matches our date format
 * @param dateString
 * @return true if the passed string matches format 2014-1-15 (YYYY-MM-dd)
 */
private boolean matchesDatePattern(String dateString) {
    return dateString.matches("^\\d+\\-\\d+\\-\\d+");
}
Sufian
fuente
5

Creo que lo más simple es convertir una cadena en un objeto de fecha y volver a convertirla en una cadena. La cadena de fecha dada está bien si ambas cadenas aún coinciden.

public boolean isDateValid(String dateString, String pattern)
{   
    try
    {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        if (sdf.format(sdf.parse(dateString)).equals(dateString))
            return true;
    }
    catch (ParseException pe) {}

    return false;
}
mawa
fuente
4

Le sugiero que use la org.apache.commons.validator.GenericValidatorclase de apache.

GenericValidator.isDate(String value, String datePattern, boolean strict);

Nota: estricto: si se debe tener o no una coincidencia exacta del datePattern.

Ziya
fuente
2

Suponiendo que ambos son cadenas (de lo contrario, ya serían fechas válidas), aquí hay una forma:

package cruft;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateValidator
{
    private static final DateFormat DEFAULT_FORMATTER;

    static
    {
        DEFAULT_FORMATTER = new SimpleDateFormat("dd-MM-yyyy");
        DEFAULT_FORMATTER.setLenient(false);
    }

    public static void main(String[] args)
    {
        for (String dateString : args)
        {
            try
            {
                System.out.println("arg: " + dateString + " date: " + convertDateString(dateString));
            }
            catch (ParseException e)
            {
                System.out.println("could not parse " + dateString);
            }
        }
    }

    public static Date convertDateString(String dateString) throws ParseException
    {
        return DEFAULT_FORMATTER.parse(dateString);
    }
}

Aquí está la salida que obtengo:

java cruft.DateValidator 32-11-2010 31-02-2010 04-01-2011
could not parse 32-11-2010
could not parse 31-02-2010
arg: 04-01-2011 date: Tue Jan 04 00:00:00 EST 2011

Process finished with exit code 0

Como puede ver, maneja bien ambos casos.

duffymo
fuente
@duffymo la segunda declaración no arroja una excepción ... :(
maximus
@Pangea Realmente no .... intente esta fecha "31-01-2010" no arrojará ninguna excepción .......... Simplemente ejecútelo en su máquina y vea ... trabajo ....
sasidhar
Culpa mía. Eliminé mi comentario. Pero la segunda declaración me está lanzando una excepción. @duffymo - ¿qué jvm estás usando?
Aravind Yarram
@Pangea estoy usando jdk1.6.0_23 Intenté esto incluso con joda-time.sourceforge.net pero ni siquiera eso funcionó ...
sasidhar
1
Entiendo que esto es solo una prueba simple, pero para asegurarme de que la gente no copie esto literalmente, quiero decir que "DateFormat" NO ES SEGURO PARA HILOS. Por lo tanto, créelo siempre como una variable local o utilícelo con el hilo local.
Aravind Yarram
2

Esto está funcionando muy bien para mí. Enfoque sugerido anteriormente por Ben.

private static boolean isDateValid(String s) {
    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    try {
        Date d = asDate(s);
        if (sdf.format(d).equals(s)) {
            return true;
        } else {
            return false;
        }
    } catch (ParseException e) {
        return false;
    }
}
Gorrión de Dresde
fuente
1
no puede reconocer asDate. ¿Que es eso?
Susheel
2

parece que SimpleDateFormat no está comprobando el patrón estrictamente incluso después de setLenient (false); se aplica el método en él, por lo que he utilizado el método siguiente para validar si la fecha ingresada es una fecha válida o no según el patrón proporcionado.

import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public boolean isValidFormat(String dateString, String pattern) {
    boolean valid = true;
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
    try {
        formatter.parse(dateString);
    } catch (DateTimeParseException e) {
        valid = false;
    }
    return valid;
}
vijay
fuente
1

Dos comentarios sobre el uso de SimpleDateFormat.

debe declararse como una instancia estática si se declara como acceso estático debe sincronizarse ya que no es seguro para subprocesos

IME que es mejor que instanciar una instancia para cada análisis de una fecha.

Tom
fuente
buen punto Tom. Actualicé el ejemplo que proporcioné para asegurarme de usar una instancia estática de manera consistente.
tardate
El uso de una función sincronizada puede no escalar para algunos proyectos. Recomendaría poner SimpleDateFormat en una variable ThreadLocal en lugar de una variable estática a la que se accede a través de una función sincronizada.
user327961
0

Los métodos anteriores de análisis de fechas son agradables, acabo de agregar una nueva verificación en los métodos existentes que verifican dos veces la fecha convertida con la fecha original usando formater, por lo que funciona para casi todos los casos, como verifiqué. por ejemplo, el 29/02/2013 no es una fecha válida. La función dada analiza la fecha de acuerdo con los formatos de fecha aceptables actuales. Devuelve verdadero si la fecha no se analiza correctamente.

 public final boolean validateDateFormat(final String date) {
        String[] formatStrings = {"MM/dd/yyyy"};
        boolean isInvalidFormat = false;
        Date dateObj;
        for (String formatString : formatStrings) {
            try {
                SimpleDateFormat sdf = (SimpleDateFormat) DateFormat.getDateInstance();
                sdf.applyPattern(formatString);
                sdf.setLenient(false);
                dateObj = sdf.parse(date);
                System.out.println(dateObj);
                if (date.equals(sdf.format(dateObj))) {
                    isInvalidFormat = false;
                    break;
                }
            } catch (ParseException e) {
                isInvalidFormat = true;
            }
        }
        return isInvalidFormat;
    }
Imran
fuente
0

Esto es lo que hice para el entorno Node sin usar bibliotecas externas:

Date.prototype.yyyymmdd = function() {
   var yyyy = this.getFullYear().toString();
   var mm = (this.getMonth()+1).toString(); // getMonth() is zero-based
   var dd  = this.getDate().toString();
   return zeroPad([yyyy, mm, dd].join('-'));  
};

function zeroPad(date_string) {
   var dt = date_string.split('-');
   return dt[0] + '-' + (dt[1][1]?dt[1]:"0"+dt[1][0]) + '-' + (dt[2][1]?dt[2]:"0"+dt[2][0]);
}

function isDateCorrect(in_string) {
   if (!matchesDatePattern) return false;
   in_string = zeroPad(in_string);
   try {
      var idate = new Date(in_string);
      var out_string = idate.yyyymmdd();
      return in_string == out_string;
   } catch(err) {
      return false;
   }

   function matchesDatePattern(date_string) {
      var dateFormat = /[0-9]+-[0-9]+-[0-9]+/;
      return dateFormat.test(date_string); 
   }
}

Y así es como se usa:

isDateCorrect('2014-02-23')
true
TenisVisuales
fuente
0
// to return valid days of month, according to month and year
int returnDaysofMonth(int month, int year) {
    int daysInMonth;
    boolean leapYear;
    leapYear = checkLeap(year);
    if (month == 4 || month == 6 || month == 9 || month == 11)
        daysInMonth = 30;
    else if (month == 2)
        daysInMonth = (leapYear) ? 29 : 28;
    else
        daysInMonth = 31;
    return daysInMonth;
}

// to check a year is leap or not
private boolean checkLeap(int year) {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, year);
    return cal.getActualMaximum(Calendar.DAY_OF_YEAR) > 365;
}
ashishdhiman2007
fuente
0

Aquí es donde verificaría el formato de fecha:

 public static boolean checkFormat(String dateTimeString) {
    return dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}") || dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}")
            || dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}") || dateTimeString
            .matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z") ||
            dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}Z");
}
Dinesh Bhatia
fuente
Tenemos las clases modernas de java.time para este trabajo ahora. Escribir expresiones regulares complicadas no es probablemente el mejor uso de su tiempo. Vea el resumen en mi respuesta .
Basil Bourque
0
        public static String detectDateFormat(String inputDate, String requiredFormat) {
        String tempDate = inputDate.replace("/", "").replace("-", "").replace(" ", "");
        String dateFormat;

        if (tempDate.matches("([0-12]{2})([0-31]{2})([0-9]{4})")) {
            dateFormat = "MMddyyyy";
        } else if (tempDate.matches("([0-31]{2})([0-12]{2})([0-9]{4})")) {
            dateFormat = "ddMMyyyy";
        } else if (tempDate.matches("([0-9]{4})([0-12]{2})([0-31]{2})")) {
            dateFormat = "yyyyMMdd";
        } else if (tempDate.matches("([0-9]{4})([0-31]{2})([0-12]{2})")) {
            dateFormat = "yyyyddMM";
        } else if (tempDate.matches("([0-31]{2})([a-z]{3})([0-9]{4})")) {
            dateFormat = "ddMMMyyyy";
        } else if (tempDate.matches("([a-z]{3})([0-31]{2})([0-9]{4})")) {
            dateFormat = "MMMddyyyy";
        } else if (tempDate.matches("([0-9]{4})([a-z]{3})([0-31]{2})")) {
            dateFormat = "yyyyMMMdd";
        } else if (tempDate.matches("([0-9]{4})([0-31]{2})([a-z]{3})")) {
            dateFormat = "yyyyddMMM";
        } else {
            return "Pattern Not Added";
//add your required regex
        }
        try {
            String formattedDate = new SimpleDateFormat(requiredFormat, Locale.ENGLISH).format(new SimpleDateFormat(dateFormat).parse(tempDate));

            return formattedDate;
        } catch (Exception e) {
            //
            return "";
        }

    }
Suheb Rafique
fuente
0

Con el formato de fecha 'heredado', podemos formatear el resultado y compararlo con la fuente.

    public boolean isValidFormat(String source, String pattern) {
    SimpleDateFormat sd = new SimpleDateFormat(pattern);
    sd.setLenient(false);
    try {
        Date date = sd.parse(source);
        return date != null && sd.format(date).equals(source);
    } catch (Exception e) {
        return false;
    }
}

Este execerpt dice 'falso' a la fuente = 01.01.04 con el patrón '01 .01.2004 '

skay
fuente
-1

setLenient en false si desea una validación estricta

public boolean isThisDateValid(String dateToValidate, String dateFromat){

    if(dateToValidate == null){
        return false;
    }

    SimpleDateFormat sdf = new SimpleDateFormat(dateFromat);
    sdf.setLenient(false);

    try {

        //if not valid, it will throw ParseException
        Date date = sdf.parse(dateToValidate);
        System.out.println(date);

    } catch (ParseException e) {

        e.printStackTrace();
        return false;
    }

    return true;
}
Pravin
fuente