Joda Time bug ou mon erreur? (Time Java Joda date comme l'analyse syntaxique des chaînes)

StackOverflow https://stackoverflow.com/questions/1525932

  •  20-09-2019
  •  | 
  •  

Question

donc j'avais un problème analyse d'une date, en utilisant la chronologie IslamicChronology JodaTime donc écrit un petit exemple pour illustrer mon problème.

Voici le code:

import org.joda.time.Chronology;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.chrono.IslamicChronology;

import java.util.Date;

/**
 * Test
 */
public class Test
{
    public static void main(String[] args)
    {
        Date now = new Date();

        String format = "dd MMM yyyy";
        Chronology calendarSystem = IslamicChronology.getInstance();
        DateTimeFormatter formatter = DateTimeFormat.forPattern(format).withChronology(calendarSystem);

        String nowAsString = formatter.print(now.getTime());

        System.out.println("nowAsString = " + nowAsString);

        long parsedNowTs = formatter.parseMillis(nowAsString);

        String parsedNowTsAsString = formatter.print(parsedNowTs);
    }
}

Et la sortie:

nowAsString = 16 10 1430
Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "16 10 1430" is malformed at "10 1430"
    at org.joda.time.format.DateTimeFormatter.parseMillis(DateTimeFormatter.java:634)
    at test.Test.main(Test.java:40)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    ...

Je pense que le problème est le nom du mois est numérique, mais suis-je raison? Quelqu'un at-il des suggestions? Cela ne peut pas être recréée si la chronologie est grégorienne.

Merci d'avance.

Était-ce utile?

La solution

Si quelqu'un est intéressé ... Je l'ai trouvé un travail autour de:

  • Créer une nouvelle classe par exemple IslamicChronologyWithNames qui délègue à une instance de IslamicChronology dans le paquet org.joda.time.DateTimeZone
  • Modifier la seule méthode; assemble(Fields fields): appeler la méthode du délégué, puis mis fields.monthOfYear (et peut-être dayOfWeek) pour vous-même sous-classe de BasicMonthOfYearDateTimeField
  • La sous-classe de BasicMonthOfYearDateTimeField peut alors rechercher dans les noms de fichiers de propriétés pour le mois (ou le jour de si DayOfWeek ...) nom. Sous-classe doit être dans le paquet org.joda.time.chrono pour pouvoir étendre BasicMonthOfYearDateTimeField.

Il y a encore un problème que le temps Joda semble valider la date à laquelle vous analysez avant d'appeler les méthodes de sous-classe comme getAsText(int fieldValue, Locale locale) et parce qu'il n'a pas connaissance des noms de mois que vos déclarations de classe, validation échoue et demande donc jamais les méthodes. Mon travail autour était d'avoir une méthode statique dans cette classe qui convertit une date comme une chaîne avec des noms de mois en islamic une date comme une chaîne avec des noms grégoriens mois en anglais. Donc, avant d'appeler parseDateTime(), appeler la méthode statique, puis la chaîne de date passe validation. Ensuite, au lieu de traiter les noms de mois islamiques dans la méthode convertText(), utilisez la valeur par défaut dans votre mise en œuvre grégorienne sous-classe:

protected int convertText(String text, Locale locale)
{
    return GJLocaleSymbols.forLocale(locale).monthOfYearTextToValue(text);
}

Cela devrait fonctionner! Espoir il est logique pour quelqu'un qui a le même problème.

Autres conseils

dans le MMM modèle de format indique le nom abrégé du mois. Un indice de mois numérique doit être indiqué par MM.

Après avoir lu vos commentaires sur la réponse de dtsazza, j'ai réalisé votre problème réel. :)

J'ai pris un coup d'oeil dans le code source JODA et il semble que le soutien à la chronlogy islamique est plutôt brisée. Tout d'abord, le formatter ne supporte pas les noms de mois, de sorte que les motifs MMM et MMMM sont formatés comme le nombre de mois, bien que, selon la documentation de DateTimeFormat, le nom du mois abrégé doit être utilisé pour MMM et le nom complet du mois pour MMMM .

Un problème avec votre exemple de code est que parseMillis utilise toujours la chronologie ISO, bien que la mise en forme a été configuré avec une autre chronologie. Ceci est également mentionné dans la documentation de l'API, mais pas particulièrement intuitive.

Si je remplace parseMillis avec parseDateTime, je me serais attendu à la chronologie à utiliser pour l'analyse syntaxique (au moins la documentation le dit), mais il semble que la mise en œuvre ne tient pas compte de la chronologie configurée et se poursuit avec la chronologie ISO ici bien.

Vous avez spécifié le format que dd MMM yyyy; selon le API ce que des moyens vous devez fournir le mois sous forme abrégée chaîne (dans ce cas, « octobre »). L'entrée vous avez passé en serait correctement analyser si le format était dd MM yyyy.

Edit: il semble que je manqué votre point un peu. Ce que vous avez trouvé est un cas où un formatter donné,

long input = ...; // whatever
formatter.parseMillis(formatter.print(input));

est de lancer une exception. Bien que je ne vois pas de explicites garantit que cela devrait toujours travailler, je serais certainement attendre à ce que ce soit le cas - donc oui, je soutiens votre demande que c'est un bogue probable dans Joda lui-même.

À tout le moins, si ce comportement est normal qu'il devrait y avoir une indication beaucoup plus claire que cela peut arriver.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top