1
votes

Comment convertir UTC DateTime en un autre fuseau horaire à l'aide de la bibliothèque Java 8?

final Timestamp rawDateTime = Timestamp.valueOf("2031-04-25 18:30:00");
final ZoneId zoneId = ZoneId.of("Asia/Calcutta");
final ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(
    Instant.ofEpochMilli(rawDateTime.getTime()), zoneId); 
// here we are getting output as 2031-04-25T18:30+05:30[Asia/Calcutta]

final ZonedDateTime zonedDateTime1 = 
ZonedDateTime.of(rawDateTime.toLocalDateTime(), zoneId);
// here we are getting output as 2031-04-25T18:30+05:30[Asia/Calcutta]
But I want to get the converted date time as 2031-04-26 00:00:00+5:30 as my timestamp value is in the UTC Timezone.Please help.

3 commentaires

Votre code ne se compile pas. Il vous manque un point-virgule sur la première ligne et "Asia / Calcutta" n'est pas un ZoneId , c'est une String . Veuillez vous assurer que votre code fait réellement ce que vous prétendez faire avant de le publier sur Stack Overflow.


Puisque vous utilisez java.time, l'API de date et d'heure Java moderne, vous devez éviter la classe Timestamp , elle appartient aux anciennes classes obsolètes qui ont maintenant été remplacées. Utilisez plutôt Instant (ou dans des cas particuliers LocalDateTime ).


Copie possible de Java: comment convertir un Horodatage UTC à l'heure locale? et bien d'autres questions. Veuillez rechercher et trouver.


3 Réponses :


7
votes

Premièrement, vous ne devez pas utiliser Timestamp . Vous pouvez utiliser DateTimeFormatter pour analyser en un LocalDateTime .

Vous zonez ensuite ce LocalDateTime en UTC avant de passer à la zone Calcutta avec ZonedDateTime.withZoneSameInstant .

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .append(DateTimeFormatter.ISO_LOCAL_DATE)
    .appendLiteral(' ')
    .append(DateTimeFormatter.ISO_LOCAL_TIME)
    .toFormatter();

LocalDateTime localDateTime = LocalDateTime.parse("2031-04-25 18:30:00", formatter);
ZoneId calcuttaZone = ZoneId.of("Asia/Calcutta");
ZonedDateTime calcuttaZonedDateTime = localDateTime.atZone(ZoneOffset.UTC)
    .withZoneSameInstant(calcuttaZone);


1 commentaires

DateTimeFormatter.ofPattern ("aaaa-MM-jj HH: mm: ss [XXX]"). Format (calcuttaZonedDateTime) doit indiquer la date formatée - c'est-à-dire 2031-04-26 00: 00: 00 + 5: 30 dans ce cas .



2
votes

Au lieu de ZonedDateTime avec des zones nommées ayant des normes (supra-) nationales comme les économies de jour, utilisez OffsetDateTime.

Instant raw = Instant.parse("2031-04-25T18:30:00Z");
ZonedDateTime zoned = raw.atZone(ZoneId.of("Asia/Calcutta"));
OffsetDateTime offset = OffsetDateTime.from(zoned);

L'analyse par défaut est pour le format ISO.

  • Z signifie zéro, UTC, +0: 00.
  • La mise en forme par défaut qui en résulte est 2031-04-26T00: 00 + 05: 30 .

Après commentaire d'Ole VV

Ce qui précède est particulièrement sujet aux erreurs si l'heure d'été est impliquée, comme dans Heure d'Europe centrale avec différents décalages +1: 00 et +2: 00.

OffsetDateTime utc = OffsetDateTime.parse("2031-04-25T18:30:00Z");
OffsetDateTime asia = utc.withOffsetSameInstant(ZoneOffset.ofHoursMinutes(5, 30));


4 commentaires

Pas vraiment recommandé. Alors que Asia / Calcutta explique pourquoi le décalage de +05: 30 est souhaité, ZoneOffset.ofHoursMinutes (5, 30) ne le fait pas. Et ce dernier se cassera si le Parlement indien décide un jour de passer à un nombre entier d'heures de UTC ou d'introduire l'heure d'été (DST) (le risque peut ne pas être grand dans ce cas particulier, mais en général, l'utilisation de l'ID de zone est le meilleur pratique; d'autres zones changent de décalage plus souvent que prévu).


@ OleV.V. Je suis d'accord, mais un décalage était nécessaire, et pas Asia / Calcutta. Pour cette raison, j'ai mentionné la différence, c'est-à-dire «norme nationale» et DST. Mais OffsetDateTime laisse en effet tomber des informations précieuses. Le PO voulait une date UTC représentée comme un décalage indien. Pour un CET avec l'heure d'été, je serais passé par un ZoneId.


Instant n'analysera pas la chaîne de la forme '2031-04-25 18:30:00', un DateTimeFormatter ou LocalDate.parse sera nécessaire pour créer un Instant, dans un premier temps.


@ user1653941 oui. L'ISO prescrit un T au lieu d'un espace devant la partie temps . Pour une analyse par défaut.



3
votes

Utilisation de DateTimeFormatter pour formater ZonedDateTime:

2031-04-26 00:00:00+5:30

Le résultat:

 final Timestamp rawDateTime = Timestamp.valueOf("2031-04-25 18:30:00");
        LocalDateTime ldt = rawDateTime.toLocalDateTime();
        final ZoneId zoneId = ZoneId.of("Asia/Calcutta");
        ZonedDateTime zdt = ldt.atZone(ZoneId.of("UTC"))
                .withZoneSameInstant(zoneId);


        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[XXX]");
        System.out.println(formatter.format(zdt));

Modifié: selon le commentaire de @Ole VV - L'heure de la date locale doit être convertie en heure de zone, avant d'appliquer le format:

2031-04-25 23:00:00+05:30
2031-04-25 18:30:00+05:30

Cela donnera la sortie:

    final Timestamp rawDateTime = Timestamp.valueOf("2031-04-25 18:30:00");
    final ZoneId zoneId = ZoneId.of("Asia/Calcutta");
    final ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(
            Instant.ofEpochMilli(rawDateTime.getTime()), zoneId);
    // here we are getting output as 2031-04-25T18:30+05:30[Asia/Calcutta]

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[XXX]");
    System.out.println(formatter.format(zonedDateTime));

    final ZonedDateTime zonedDateTime1 =
            ZonedDateTime.of(rawDateTime.toLocalDateTime(), zoneId);
    // here we are getting output as 2031-04-25T18:30+05:30[Asia/Calcutta]
    System.out.println(formatter.format(zonedDateTime1));


1 commentaires

À droite, l'heure de la date locale doit être convertie en heure de la zone dans la zone demandée. Ont édité, merci. Il doit donner le résultat souhaité.