Pergunta

Eu tenho um String que representa uma data no Francês locale: 09-Out-08:

Eu preciso parse que Cordas então eu vim com essa SimpleDateFormat:

String format2 = "dd-MMM-yy";

Mas eu tenho um problema com a parte do mês, que parece ser esperado com um ponto terminando:

df2.format(new Date());

dá-me:

 28-oct.-09

O que é agora a melhor maneira para mim fazer SimpleDateFormat entender ( "09-Out-08")?

Código completa:

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

Isto dá-me: java.text.ParseException: Data unparseable: "09-Out-08"

E se eu tente fazer logon:

df2.format(new Date()); 

eu recebo: 28-outubro-09

Foi útil?

Solução

Isso 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 St. Sombra chegou antes de mim

.

Outras dicas

Você pode simplesmente remover o "":

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

Editar, em relação ao limão resposta:

Parece ser um problema com a formatação ao usar a localidade francês. Assim, sugiro que você simplesmente usar a remoção . como expliquei.

Na verdade, o código a seguir:

    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));

exibe o seguinte resultado:

28-oct.-09
28-Oct-09

Editar novamente

Ok, eu tenho o seu problema no momento.

Eu realmente não sei como você pode resolver este problema sem a processar o seu String first. A ideia é substituir o mês na string original por um mês 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);

Eu concordo, isso é horrível, mas eu não vejo qualquer outra solução se você usar a classes SimpleDateFormat e Date.

Outra solução é usar um real data e hora biblioteca, em vez dos JDK originais, tais como Joda Tempo .

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

Saídas 28-Oct-09

Eu não vejo nenhum senhor pontos. Já experimentou suas impressões verificando re-? Talvez você colocou acidentalmente um . ao lado de seu MMM?


Você está recebendo java.text.ParseException: Unparseable date: "09-oct-08" desde "09-oct-08" não coincide com a formatação de Locale.FRENCH quer usar o local padrão (US eu acho) ou adicionar um . ao lado de seu oct

Ok, então tente «força bruta»:)

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

Vamos ver se o java.time framework pode ajudar.

Sobre java.time

O java.time estrutura construída em Java 8 e posterior suplanta as classes java.util.Date/.Calendar velhos problemáticos. As novas classes são inspirados pela estrutura altamente bem sucedido Joda-Time , concebido como seu sucessor, similar no conceito, mas re-arquitetado. Definido por JSR 310 . Prorrogado pelo projeto ThreeTen-Extra. Veja a Tutorial .

LocalDate

Ao contrário das classes de idade, ofertas java.time classe LocalDate para representar um valor de somente data, sem hora do dia nem fuso horário.

francês abreviações

Dê uma olhada no que os formatadores em java.time esperar de nomes abreviados mês em en Français .

Podemos repetir o Month enum para obter uma lista de meses. Esta enumeração oferece a getDisplayName método para a geração de um nome localizado do mês. Este código demonstra que o método produz a mesma saída que o formatador 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.

Nós encontramos uma mistura de 3 e 4 grafias carta. nomes mais longos são abreviados para quatro caracteres mais um período ( Ponto Final ). Quatro meses têm nomes curto o suficiente para ser usado sem abreviatura:. mars, mai, juin, août

Então, como discutido em outras respostas, há uma solução simples.

Corrigir a fonte de dados

A minha primeira sugestão é para corrigir o seu fonte de dados. Essa fonte, aparentemente, não consegue seguir as regras francesas adequadas para abreviatura. Yale concorda com o entendimento de Java 8 de francês. By the way, se a fixação de seu fonte de dados eu sugiro fortemente usar anos de quatro dígitos como dois chumbo sem fim de confusão e ambigüidade.

Corrigir a entrada

É claro que a fonte pode estar fora de seu controle / influência. Nesse caso, como acontece com as outras respostas, você pode precisar de fazer uma força-bruta substituir sim que tentar qualquer esperteza. Por outro lado, se o único problema com a sua entrada é simplesmente faltando o período (FULL STOP), então você pode soft-código usando o enum Month em vez de codificar os valores impróprios.

Gostaria de fazer uma tentativa de análise inicial. Armadilha para o DateTimeParseException , antes de tentar um conserto. Se a exceção é lançada, em seguida, corrigir a entrada.

Para corrigir a entrada, tente cada mês do ano por looping a possível conjunto de instâncias de enumeração. Para cada mês, obter o seu nome abreviado. Tira o período (FULL STOP) de que abreviatura, para coincidir com o que nós suspeitamos que é o nosso valor de entrada imprópria. Teste para ver se que na verdade é um jogo para a entrada. Se não, vá para o próximo mês.

Quando nós começamos um jogo, corrigir a entrada de ser devidamente abreviado para as regras da localidade (regulamentação francesa no nosso caso). Em seguida, analisar a entrada fixo. Esta seria a nossa segunda tentativa de análise, como nós fizemos uma tentativa inicial em cima. Se esta segunda tentativa falhar, algo está muito errado como nenhumated na FIXME: visto aqui. Mas normalmente esta segunda tentativa de análise terá sucesso, e nós podemos afiançar fora do circuito for do enum Month.

Finalmente, você pode verificar o sucesso testando se o resultado ainda é o valor definido bandeira falsa 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).

Dump para console.

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

sucesso: true. Entrada: 09-Out-08 ? LOCALDATE: 2008-10-09 ? formatado: 09-outubro-08 ? outputImproper: 09-Out-08

Eu estava tendo o mesmo problema (pontos franceses e os extras) e eu acredito que o caminho certo para resolver este problema é através da substituição globalmente a localidade francês assim:

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

O objeto original francês monthsShort tem os pontos como janv._févr._mars_avr._..., por isso estamos apenas removê-los.

Aqui está uma href="http://momentjs.com/docs/#/i18n/changing-locale/" ligação para docs onde você pode verificar o que pode ser substituído .

Note que não precisa passar um objeto de localidade completa se nós apenas deseja substituir ie .: monthsShort.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top