205 votes

Java SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") donne le fuseau horaire comme IST

J'ai le constructeur SimpleDateFormat comme

SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")

et je suis en train d'analyser la chaîne "2013-09-29T18:46:19Z".

J'ai lu que ici Z représente le fuseau horaire GMT/UTC. mais lorsque j'imprime cette date sur la console, elle affiche le fuseau horaire IST pour la date retournée.

Maintenant ma question est de savoir si ma sortie est correcte ou incorrecte?

32voto

Thirdman Points 36

Et si vous n'avez pas la possibilité d'utiliser Java 8, il vaut mieux utiliser 'yyyy-MM-dd'T'HH:mm:ssXXX' car cela sera correctement analysé à nouveau (alors qu'avec une seule X, ce n'est peut-être pas le cas... en fonction de votre fonction d'analyse)

X génère : +01

XXX génère : +01:00

10voto

Arvind Kumar Avinash Points 49501

'Z' n'est pas la même que Z

'Z' est juste un littéral de caractère tandis que Z est le indicateur de fuseau horaire pour un décalage de fuseau horaire nul. Il est abrégé sous Zulu et spécifie le fuseau horaire Etc/UTC (qui a un décalage de fuseau horaire de +00:00 heures).

Par conséquent, ne pas utiliser 'Z' dans le modèle pour l'analyse/formatage.

La java.time, l'API de Date-Heure moderne

L'API de Date-Heure moderne est basée sur ISO 8601 et ne nécessite pas d'utiliser explicitement un objet DateTimeFormatter tant que la chaîne Date-Heure est conforme aux normes ISO 8601. La chaîne Date-Heure, 2013-09-29T18:46:19Z est conforme aux normes ISO 8601.

Démonstration:

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.parse("2013-09-29T18:46:19Z");
        OffsetDateTime odt = OffsetDateTime.parse("2013-09-29T18:46:19Z");
        ZonedDateTime zdt = ZonedDateTime.parse("2013-09-29T18:46:19Z");

        System.out.println(instant);
        System.out.println(odt);
        System.out.println(zdt);
    }
}

Résultat:

2013-09-29T18:46:19Z
2013-09-29T18:46:19Z
2013-09-29T18:46:19Z

DEMO EN LIGNE

Un Instant représente un point instantané sur la ligne de temps en UTC. Le Z dans la sortie est l'indicateur de fuseau horaire pour un décalage de fuseau horaire nul. Il est abrégé sous Zulu et spécifie le fuseau horaire Etc/UTC (qui a un décalage de fuseau horaire de +00:00 heures).

Note#1: Au cas où vous auriez besoin de savoir quelle date et heure un Instant représente dans un fuseau horaire particulier, vous pouvez utiliser Instant#atZone par exemple le code suivant affichera la date et l'heure de cet Instant en Inde:

ZonedDateTime zdtInde = instant.atZone(ZoneId.of("Asia/Kolkata"));
System.out.println(zdtInde);

Vous pouvez même convertir un objet de ZonedDateTime d'un fuseau horaire à un autre en utilisant ZonedDateTime#withZoneSameInstant par exemple le code suivant convertira zdt en un objet de ZonedDateTime représentant la date et l'heure en Inde:

ZonedDateTime zdtInde = zdt.withZoneSameInstant(ZoneId.of("Asia/Kolkata"));
System.out.println(zdtInde);

Note#2: Pour toute raison, si vous avez besoin de convertir cet objet Instant en un objet de java.util.Date, vous pouvez le faire comme suit:

Date date = Date.from(instant);

Vous pouvez même convertir l'objet de OffsetDateTime et ZonedDateTime en un objet de java.util.Date, comme suit:

Date date = Date.from(odt.toInstant());

&

Date date = Date.from(zdt.toInstant());

En savoir plus sur la moderne API Date-Heure* à partir de Didacticiel: Date Heure.

Pourquoi votre objet java.util.Date affiche-t-il la date et l'heure de l'Inde?

Un objet java.util.Date représente simplement le nombre de millisecondes depuis le temps de base standard connu sous le nom d'"l'ère", à savoir le 1er janvier 1970, 00:00:00 GMT (ou UTC). Comme il ne contient aucune information de fuseau horaire, sa fonction toString applique le fuseau horaire de la JVM pour renvoyer une String dans le format, EEE MMM dd HH:mm:ss zzz yyyy, dérivé de cette valeur de millisecondes. Pour obtenir la représentation String de l'objet java.util.Date dans un format et un fuseau horaire différents, vous devez utiliser SimpleDateFormat avec le format désiré et le fuseau horaire applicable par exemple:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
String strDate = sdf.format(date);
System.out.println(strDate);

Démonstration:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
        Date date = sdf.parse("2013-09-29T18:46:19Z");

        // Dans le fuseau horaire de la JVM et format par défaut retourné par Date#toString
        System.out.println(date);

        // En UTC et format personnalisé
        sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
        String strDate = sdf.format(date);
        System.out.println(strDate);

        // En Inde et format personnalisé
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
        strDate = sdf.format(date);
        System.out.println(strDate);
    }
}

Résultat (mon fuseau horaire est Europe/Londres):

Dim Sep 29 19:46:19 BST 2013
2013-09-29T18:46:19Z
2013-09-30T00:16:19+05:30

DEMO EN LIGNE


* Pour toute raison, si vous devez vous en tenir à Java 6 ou Java 7, vous pouvez utiliser ThreeTen-Backport qui rétroporte la plupart des fonctionnalités de java.time vers Java 6 & 7. Si vous travaillez sur un projet Android et que votre niveau d'API Android n'est toujours pas conforme à Java 8, vérifiez les API Java 8+ disponibles via désuétude et Comment utiliser ThreeTenABP dans un projet Android.

4voto

niraj Points 124

Pour Java 8: Vous pouvez utiliser le java.time.format.DateTimeFormatter intégré pour réduire toute chance de fautes de frappe, comme

DateTimeFormatter formatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;

ISO_ZONED_DATE_TIME représente 2011-12-03T10:15:30+01:00[Europe/Paris] est l'un des formats de date et d'heure standard inclus fournis par Oracle lien

3voto

Preetam Purbia Points 1070

Exemples de formateurs existants de référence :

String date1 = "2022-06-19T01:26:05.000+00:00"; 
// en interne en utilisant DateTimeFormatter.ISO_OFFSET_DATE_TIME
System.out.println(OffsetDateTime.parse(date1));

// en interne en utilisant DateTimeFormatter.ISO_ZONED_DATE_TIME
System.out.println(ZonedDateTime.parse(date1));

String date2 = "2022-06-19T01:26:05"; 
// en interne en utilisant DateTimeFormatter.ISO_LOCAL_DATE_TIME)
System.out.println(LocalDateTime.parse(date2)); 

String date3 = "2022-06-19T01:26:05.00Z"; 
// en interne en utilisant DateTimeFormatter.ISO_INSTANT
System.out.println(Instant.parse(date3));

Sortie :

2022-06-19T01:26:05Z
2022-06-19T01:26:05Z
2022-06-19T01:26:05
2022-06-19T01:26:05Z

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X