web-dev-qa-db-fra.com

Caractère de modèle illégal 'T' lors de l'analyse d'une chaîne de date à Java.util.Date

J'ai une chaîne de date et je veux l'analyser à la date normale en utilisant l'API Java Date, voici mon code:

public static void main(String[] args) {
    String date="2010-10-02T12:23:23Z";
    String pattern="yyyy-MM-ddThh:mm:ssZ";
    SimpleDateFormat sdf=new SimpleDateFormat(pattern);
    try {
        Date d=sdf.parse(date);
        System.out.println(d.getYear());
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Cependant, j'ai une exception: Java.lang.IllegalArgumentException: Illegal pattern character 'T'

Je me demande donc si je dois séparer la chaîne et l’analyser manuellement?

BTW, j'ai essayé d'ajouter un seul caractère de citation de chaque côté du T:

String pattern="yyyy-MM-dd'T'hh:mm:ssZ";

Cela ne marche pas non plus.

158
hguser

Mise à jour pour Java 8 et supérieur

Vous pouvez maintenant simplement faire Instant.parse("2015-04-28T14:23:38.521Z") et obtenir la bonne chose maintenant, surtout que vous devriez utiliser Instant au lieu du Java.util.Date avec les versions les plus récentes de Java.

Vous devriez également utiliser DateTimeFormatter au lieu de SimpleDateFormatter.

Réponse originale:

L'explication ci-dessous est toujours valable en tant que ce que le format représente. Mais il était écrit avant Java 8 était omniprésent, il utilise donc les anciennes classes que vous ne devriez pas utiliser si vous utilisez Java 8 ou supérieur.).

Ceci fonctionne avec l'entrée avec le dernier Z suivant:

Dans le modèle, le T est échappé avec ' de chaque côté.

Le modèle pour le Z à la fin est en réalité XXX comme indiqué dans le JavaDoc pour SimpleDateFormat, il n’est tout simplement pas très clair comment l’utiliser depuis Z est également le marqueur des anciennes informations TimeZone.

Q2597083.Java

import Java.text.SimpleDateFormat;
import Java.util.Calendar;
import Java.util.Date;
import Java.util.GregorianCalendar;
import Java.util.TimeZone;

public class Q2597083
{
    /**
     * All Dates are normalized to UTC, it is up the client code to convert to the appropriate TimeZone.
     */
    public static final TimeZone UTC;

    /**
     * @see <a href="http://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations">Combined Date and Time Representations</a>
     */
    public static final String ISO_8601_24H_FULL_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";

    /**
     * 0001-01-01T00:00:00.000Z
     */
    public static final Date BEGINNING_OF_TIME;

    /**
     * 292278994-08-17T07:12:55.807Z
     */
    public static final Date END_OF_TIME;

    static
    {
        UTC = TimeZone.getTimeZone("UTC");
        TimeZone.setDefault(UTC);
        final Calendar c = new GregorianCalendar(UTC);
        c.set(1, 0, 1, 0, 0, 0);
        c.set(Calendar.MILLISECOND, 0);
        BEGINNING_OF_TIME = c.getTime();
        c.setTime(new Date(Long.MAX_VALUE));
        END_OF_TIME = c.getTime();
    }

    public static void main(String[] args) throws Exception
    {

        final SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_24H_FULL_FORMAT);
        sdf.setTimeZone(UTC);
        System.out.println("sdf.format(BEGINNING_OF_TIME) = " + sdf.format(BEGINNING_OF_TIME));
        System.out.println("sdf.format(END_OF_TIME) = " + sdf.format(END_OF_TIME));
        System.out.println("sdf.format(new Date()) = " + sdf.format(new Date()));
        System.out.println("sdf.parse(\"2015-04-28T14:23:38.521Z\") = " + sdf.parse("2015-04-28T14:23:38.521Z"));
        System.out.println("sdf.parse(\"0001-01-01T00:00:00.000Z\") = " + sdf.parse("0001-01-01T00:00:00.000Z"));
        System.out.println("sdf.parse(\"292278994-08-17T07:12:55.807Z\") = " + sdf.parse("292278994-08-17T07:12:55.807Z"));
    }
}

Produit la sortie suivante:

sdf.format(BEGINNING_OF_TIME) = 0001-01-01T00:00:00.000Z
sdf.format(END_OF_TIME) = 292278994-08-17T07:12:55.807Z
sdf.format(new Date()) = 2015-04-28T14:38:25.956Z
sdf.parse("2015-04-28T14:23:38.521Z") = Tue Apr 28 14:23:38 UTC 2015
sdf.parse("0001-01-01T00:00:00.000Z") = Sat Jan 01 00:00:00 UTC 1
sdf.parse("292278994-08-17T07:12:55.807Z") = Sun Aug 17 07:12:55 UTC 292278994
181
user177800

tl; dr

Instant.parse( "2010-10-02T12:23:23Z" )

ISO 8601

Ce format est défini par la norme ISO 8601 pour les formats de chaîne date-heure.

Tous les deux:

… Utilisez les formats ISO 8601 par défaut pour analyser et générer des chaînes.

Vous devez généralement éviter d'utiliser les anciennes classes Java.util.Date /. Calendar & Java.text.SimpleDateFormat car elles sont notoirement gênantes, déroutantes et imparfaites. . Si nécessaire pour l'interopérabilité, vous pouvez effectuer une conversion aller-retour.

Java.time

Construit dans Java 8 et versions ultérieures est le nouveau cadre Java.time . Inspiré par Joda-Time , défini par JSR 31 , et étendu par le projet ThreeTen-Extra .

Instant instant = Instant.parse( "2010-10-02T12:23:23Z" );  // `Instant` is always in UTC.

Convertir à l'ancienne classe.

Java.util.Date date = Java.util.Date.from( instant );  // Pass an `Instant` to the `from` method.

Fuseau horaire

Si nécessaire, vous pouvez attribuer un fuseau horaire.

ZoneId zoneId = ZoneId.of( "America/Montreal" ); // Define a time zone rather than rely implicitly on JVM’s current default time zone.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );  // Assign a time zone adjustment from UTC.

Convertir.

Java.util.Date date = Java.util.Date.from( zdt.toInstant() );  // Extract an `Instant` from the `ZonedDateTime` to pass to the `from` method.

Joda-Time

MISE À JOUR: le projet Joda-Time est maintenant en mode maintenance. L'équipe conseille la migration vers les classes Java.time .

Voici un exemple de code dans Joda-Time 2.8.

org.joda.time.DateTime dateTime_Utc = new DateTime( "2010-10-02T12:23:23Z" , DateTimeZone.UTC );  // Specifying a time zone to apply, rather than implicitly assigning the JVM’s current default.

Convertir à l'ancienne classe. Notez que le fuseau horaire attribué est perdu lors de la conversion car j.u.Date ne peut pas être affecté à un fuseau horaire.

Java.util.Date date = dateTime_Utc.toDate(); // The `toDate` method converts to old class.

Fuseau horaire

Si nécessaire, vous pouvez attribuer un fuseau horaire.

DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTime_Montreal = dateTime_Utc.withZone ( zone );

À propos de Java.time

Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent l'ancien problème - legacy classes date-heure telles que Java.util.Date , Calendar , & SimpleDateFormat .

Le projet Joda-Time , actuellement en mode de maintenance , conseille de migrer vers le Java.time = cours.

Pour en savoir plus, consultez le Oracle Tutorial . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 31 .

Vous pouvez échanger des objets Java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou une version ultérieure. Pas besoin de chaînes, pas besoin de Java.sql.* Des classes.

Où obtenir les classes Java.time?

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d’essai pour d’éventuels ajouts à Java.time. Vous pouvez trouver ici quelques classes utiles telles que Interval , YearWeek , YearQuarter , et plus .

21
Basil Bourque