Pregunta

Tengo una cadena que representa una fecha en francés local: 09-oct-08:

Necesito analizar esa Cadena, así que se me ocurrió este SimpleDateFormat:

String format2 = "dd-MMM-yy";

Pero tengo un problema con la parte del mes, que parece esperarse con un punto final:

df2.format(new Date());

me da:

 28-oct.-09

¿Cuál es ahora la mejor manera para mí de hacer que SimpleDateFormat entienda (" 09-oct-08 ")?

Código completo:

String format2 = "dd-MMM-yy"; 
DateFormat df2 = new SimpleDateFormat(format2,Locale.FRENCH); 
date = df2.parse("09-oct-08"); 

Esto me da: java.text.ParseException: Fecha no analizable: " 09-oct-08 "

Y si luego intento iniciar sesión:

df2.format(new Date()); 

Obtengo: 28-oct-09

¿Fue útil?

Solución

Esto parece funcionar:

    DateFormatSymbols dfsFr = new DateFormatSymbols(Locale.FRENCH);
    String[] oldMonths = dfsFr.getShortMonths();
    String[] newMonths = new String[oldMonths.length];
    for (int i = 0, len = oldMonths.length; i < len; ++ i) {
        String oldMonth = oldMonths[i];

        if (oldMonth.endsWith(".")) {
            newMonths[i] = oldMonth.substring(0, oldMonths[i].length() - 1);
        } else {
            newMonths[i] = oldMonth;
        }
    }
    dfsFr.setShortMonths(newMonths);
    DateFormat dfFr = new SimpleDateFormat(
        "dd-MMM-yy", dfsFr);

    // English date parser for creating some test data.
    DateFormat dfEn = new SimpleDateFormat(
        "dd-MMM-yy", Locale.ENGLISH);
    System.out.println(dfFr.format(dfEn.parse("10-Oct-09")));
    System.out.println(dfFr.format(dfEn.parse("10-May-09")));
    System.out.println(dfFr.format(dfEn.parse("10-Feb-09")));

Editar: Parece que St. Shadow me ganó.

Otros consejos

Simplemente puede eliminar el ". " ;:

df2.format(new Date()).replaceAll("\\.", ""));

Editar, con respecto a la respuesta limón :

Parece que hay un problema con el formato cuando se usa la configuración regional en francés. Por lo tanto, le sugiero que simplemente use la eliminación de . como expliqué.

De hecho, el siguiente código:

    String format2 = "dd-MMM-yy";
    Date date = Calendar.getInstance().getTime();
    SimpleDateFormat sdf = new SimpleDateFormat(format2, Locale.FRENCH);
    System.out.println(sdf.format(date));
    sdf = new SimpleDateFormat(format2, Locale.ENGLISH);
    System.out.println(sdf.format(date));

muestra el siguiente resultado:

28-oct.-09
28-Oct-09

Editar de nuevo

Ok, tengo tu problema ahora mismo.

Realmente no sé cómo puede resolver este problema sin procesar primero su Cadena. La idea es reemplazar el mes en la Cadena original por un mes completo:

        String[] givenMonths = { "jan", "fév", "mars", "avr.", "mai", "juin", "juil", "août", "sept", "oct", "nov", "déc" };
        String[] realMonths = { "janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc." };
        String original = "09-oct-08";
        for (int i = 0; i < givenMonths.length; i++) {
            original = original.replaceAll(givenMonths[i], realMonths[i]);
        }
        String format2 = "dd-MMM-yy";
        DateFormat df2 = new SimpleDateFormat(format2, Locale.FRENCH);
        Date date = df2.parse(original);
        System.out.println("--> " + date);

Estoy de acuerdo, esto es horrible, pero no veo ninguna otra solución si utilizas las clases SimpleDateFormat y Date .

Otra solución es usar una biblioteca de fecha y hora real en lugar de las JDK originales, como Joda Time .

String format2 = "dd-MMM-yy";
Date date = Calendar.getInstance().getTime();
SimpleDateFormat sdf = new SimpleDateFormat(format2);
System.out.println(sdf.format(date));

Salidas 28-Oct-09

No veo ningún punto señor. ¿Has intentado volver a comprobar tus huellas? ¿Tal vez accidentalmente colocó un . al lado de su MMM ?


Obtendrá java.text.ParseException: fecha no analizable: " 09-oct-08 " ya que " 09-oct-08 " no coincide el formato de Locale.FRENCH usa la configuración regional predeterminada (creo que en EE. UU.) o agrega un . junto a tu oct

Ok, entonces intente & # 171; fuerza bruta & # 187; :)

DateFormatSymbols dfs = new DateFormatSymbols(Locale.FRENCH);
String[] months = new String[13]
<fill with correct month names or just replace these month, that are not fully correct>
dfs.setMonths(months);
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yy", dfs);
Date nweDate = sdf.parse("09-fév-08");

java.time

Veamos si el marco java.time puede ayudar.

Acerca de java.time

El java.time framework integrado en Java 8 y posterior suplanta a las viejas y problemáticas clases java.util.Date/.Calendar. Las nuevas clases están inspiradas en el exitoso marco Joda-Time , diseñado como su sucesor, similar en concepto pero rediseñado. Definido por JSR 310 . Extendido por el proyecto ThreeTen-Extra . Consulte el Tutorial .

LocalDate

A diferencia de las antiguas clases, java.time ofrece el LocalDate para representar un valor de solo fecha, sin hora del día ni zona horaria.

Abreviaturas francesas

Eche un vistazo a lo que esperan los formateadores en java.time para los nombres de mes abreviados en en Fran & # 231; ais .

Podemos recorrer el Month enumeración para obtener una lista de meses. Esta enumeración ofrece el getDisplayName método para generar un nombre localizado del mes. Este código demuestra que el método produce el mismo resultado que el formateador java.time.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "dd-MMM-yyyy" ).withLocale ( Locale.FRENCH );
for ( Month month : Month.values () ) {
    LocalDate localDate = LocalDate.of ( 2015 , month.getValue () , 1 );
    String output = formatter.format ( localDate );
    String displayName = month.getDisplayName ( TextStyle.SHORT , Locale.FRENCH );
    System.out.println ( "output: " + output + " | displayName: " + displayName );// System.out.println ( "input: " + input + " → " + localDate + " → " + output );
}
output: 01-janv.-2015 | displayName: janv.
output: 01-févr.-2015 | displayName: févr.
output: 01-mars-2015 | displayName: mars
output: 01-avr.-2015 | displayName: avr.
output: 01-mai-2015 | displayName: mai
output: 01-juin-2015 | displayName: juin
output: 01-juil.-2015 | displayName: juil.
output: 01-août-2015 | displayName: août
output: 01-sept.-2015 | displayName: sept.
output: 01-oct.-2015 | displayName: oct.
output: 01-nov.-2015 | displayName: nov.
output: 01-déc.-2015 | displayName: déc.

Encontramos una combinación de ortografía de 3 y 4 letras. Los nombres más largos se abrevian a cuatro caracteres más un punto ( PARADA COMPLETA ) Cuatro meses tienen nombres lo suficientemente cortos como para usarse sin abreviatura: mars , mai , juin , ao & # 251; t .

Entonces, como se discutió en las otras Respuestas, no hay una solución simple.

Arreglar la fuente de datos

Mi primera sugerencia es arreglar su fuente de datos. Al parecer, esa fuente no sigue las reglas francesas adecuadas para la abreviatura. Yale está de acuerdo con la comprensión que hace Java 8 del francés. Por cierto, si arreglas tu fuente de datos, te sugiero que uses años de cuatro dígitos como dos no conducen a un sinfín de confusión y ambigüedad.

Arreglar la entrada

Por supuesto, la fuente puede estar fuera de su control / influencia. En ese caso, al igual que con las otras Respuestas, es posible que deba hacer un reemplazo de fuerza bruta en lugar de intentar cualquier astucia. Por otro lado, si el único problema con su entrada es simplemente perder el punto (DETENCIÓN COMPLETA), entonces podría codificar mediante la enumeración Month en lugar de codificar los valores incorrectos.

Haría un intento de análisis inicial. Captura para el DateTimeParseException , antes de intentar una solución. Si se produce la excepción, arregle la entrada.

Para corregir la entrada, intente cada mes del año haciendo un bucle con el posible conjunto de instancias enum. Para cada mes, obtenga su nombre abreviado. Elimine el punto (PARADA COMPLETA) de esa abreviatura, para que coincida con lo que sospechamos es nuestro valor entrante incorrecto. Pruebe para ver si eso realmente coincide con la entrada. Si no, ve al próximo mes.

Cuando obtengamos una coincidencia, arregle la entrada para que se abrevie correctamente para las reglas de la configuración regional (reglas francesas en nuestro caso). Luego analiza la entrada fija. Este sería nuestro segundo intento de análisis, ya que hicimos un intento inicial en la parte superior. Si este segundo intento falla, algo está muy mal como se indica en el FIXME: visto aquí. Pero normalmente este segundo intento de análisis tendrá éxito, y podemos rescatarnos del bucle for de la enumeración Month .

Finalmente, puede verificar el éxito probando si el resultado sigue siendo el valor de bandera falso establecido inicialmente ( LocalDate.MIN ).

String input = "09-oct-08"; // Last two digits are Year.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "dd-MMM-yy" ).withLocale ( Locale.FRENCH );
LocalDate localDate = LocalDate.MIN; // Some folks prefer a bogus default value as a success/failure flag rather than using a NULL.
try {
    localDate = LocalDate.parse ( input , formatter );
} catch ( DateTimeParseException e ) {
    // Look for any month name abbreviation improperly missing the period (FULL STOP).
    for ( Month month : Month.values () ) {
        String abbreviation = month.getDisplayName ( TextStyle.SHORT , Locale.FRENCH );
        String abbreviationWithoutFullStop = abbreviation.replace ( "." , "" ); // Get short abbreviation, but drop any period (FULL STOP).
        String proper = "-" + abbreviation + "-";
        String improper = "-" + abbreviationWithoutFullStop + "-";
        if ( input.contains ( improper ) ) {
            String inputFixed = input.replace ( improper , proper );
            try {
                localDate = LocalDate.parse ( inputFixed , formatter );
            } catch ( DateTimeParseException e2 ) {
                // FIXME: Handle this error. We expected this second parse attempt to succeed.
            }
            break; // Bail-out of the loop as we got a hit, matching input with a particular improper value.
        }
    }
}
Boolean success =  ! ( localDate.equals ( LocalDate.MIN ) );
String formatted = formatter.format ( localDate );;
String outputImproper = formatted.replace ( "." , "" );  // Drop any period (FULL STOP).

Volcado a la consola.

System.out.println ( "success: " + success + ". input: " + input + " → localDate: " + localDate + " → formatted: " + formatted + " → outputImproper: " + outputImproper );
  

éxito: verdadero. entrada: 09-oct-08 & # 8594; localDate: 2008-10-09 & # 8594; formateado: 09-oct-08 & # 8594; outputImproper: 09-oct-08

Estaba teniendo el mismo problema (francés y los puntos extra) y creo que la forma correcta de resolver este problema es sobrescribiendo globalmente el idioma francés de esta manera:

import moment from 'moment';
moment.locale('fr', { monthsShort: 'janv_févr_mars_avr_mai_juin_juil_août_sept_oct_nov_déc'.split('_') });

El objeto original francés monthsShort tiene los puntos como janv._févr._mars_avr ._... , así que solo los estamos eliminando.

Aquí hay un enlace a documentos donde puede verificar qué se puede sobrescribir .

Tenga en cuenta que no necesitamos pasar un objeto de configuración regional completo si solo queremos sobrescribir, es decir: monthsShort .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top