web-dev-qa-db-fra.com

Conversion de fuseau horaire

Je dois convertir un fuseau horaire en un autre fuseau horaire dans mon projet.

Je peux convertir de mon fuseau horaire actuel à un autre mais pas d'un fuseau horaire différent à un autre.

Par exemple, je suis en Inde et je peux convertir de l'Inde aux États-Unis en utilisant Date d=new Date(); et en l'affectant à un objet de calendrier et en définissant le fuseau horaire.

Cependant, je ne peux pas faire cela d'un fuseau horaire différent à un autre fuseau horaire. Par exemple, je suis en Inde, mais j'ai du mal à convertir les fuseaux horaires des États-Unis au Royaume-Uni.

39
Senthilnathan

tl; dr

ZonedDateTime.now( ZoneId.of( "Pacific/Auckland" ))              // Current moment in a particular time zone.
             .withZoneSameInstant( ZoneId.of( "Asia/Kolkata" ))  // Same moment adjusted into another time zone. 

Détails

Aucun fuseau horaire n'a été attribué à la classe Java.util.Date., mais son implémentation toString applique de manière confuse le fuseau horaire par défaut de la JVM.

Évitez Java.util.Date et .Calendar

C'est l'une des nombreuses raisons pour éviter les classes Java.util.Date, .Calendar et SimpleDateFormat notoirement gênantes fournies avec Java. Évite-les. Utilisez plutôt:

Java.time

Java 8 et versions ultérieures ont le package Java.time intégré. Ce package a été inspiré par Joda-Time . Bien qu'ils partagent des similitudes et des noms de classe, ils sont différents; chacun a des caractéristiques que l'autre manque. Une différence notable est que Java.time évite les constructeurs, utilise à la place des méthodes d'instanciation statiques. Les deux cadres sont dirigés par le même homme, Stephen Colbourne .

Une grande partie de la fonctionnalité Java.time a été redirigée vers Java 6 & 7 dans le projet ThreeTen-Backport . Adapté davantage à Android dans le projet ThreeTenABP .

Dans le cas de cette Question, ils fonctionnent de la même manière. Spécifiez un fuseau horaire et appelez une méthode now pour obtenir l'instant actuel, puis créez une nouvelle instance basée sur l'ancienne instance immuable pour ajuster le fuseau horaire.

Notez les deux classes de fuseau horaire différentes. L'un est un fuseau horaire nommé comprenant toutes les règles de l'heure d'été et d'autres anomalies de ce type, plus un décalage par rapport à l'UTC, tandis que l'autre n'est que le décalage.

ZoneId zoneMontréal = ZoneId.of("America/Montreal"); 
ZonedDateTime nowMontréal = ZonedDateTime.now ( zoneMontréal );

ZoneId zoneTokyo = ZoneId.of("Asia/Tokyo"); 
ZonedDateTime nowTokyo = nowMontréal.withZoneSameInstant( zoneTokyo );

ZonedDateTime nowUtc = nowMontréal.withZoneSameInstant( ZoneOffset.UTC );

Joda-Time

Voici un exemple de code dans Joda-Time 2.3. Recherchez StackOveflow pour de nombreux autres exemples et de nombreuses discussions.

DateTimeZone timeZoneLondon = DateTimeZone.forID( "Europe/London" );
DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );

DateTime nowLondon = DateTime.now( timeZoneLondon ); // Assign a time zone rather than rely on implicit default time zone.
DateTime nowKolkata = nowLondon.withZone( timeZoneKolkata );
DateTime nowNewYork = nowLondon.withZone( timeZoneNewYork );
DateTime nowUtc = nowLondon.withZone( DateTimeZone.UTC );  // Built-in constant for UTC.

Nous avons quatre représentations du même moment dans la chronologie de l'Univers.


En fait, le Java.util.Date classe a un fuseau horaire enfoui dans son code source . Mais la classe ignore ce fuseau horaire à des fins plus pratiques. Donc, en sténographie, on dit souvent que j.u.Date n'a pas de fuseau horaire attribué. Déroutant? Oui. Évitez le désordre qui est j.u.Date et optez pour Joda-Time et/ou Java.time.

45
Basil Bourque

Quelques exemples

Convertir le temps entre le fuseau horaire

Conversion des temps entre les fuseaux horaires

import Java.util.Calendar;
import Java.util.GregorianCalendar;
import Java.util.TimeZone;

public class TimeZoneExample {
    public static void main(String[] args) {
        // Create a calendar object and set it time based on the local
        // time zone
        Calendar localTime = Calendar.getInstance();
        localTime.set(Calendar.HOUR, 17);
        localTime.set(Calendar.MINUTE, 15);
        localTime.set(Calendar.SECOND, 20);

        int hour = localTime.get(Calendar.HOUR);
        int minute = localTime.get(Calendar.MINUTE);
        int second = localTime.get(Calendar.SECOND);


        // Print the local time
        System.out.printf("Local time  : %02d:%02d:%02d\n", hour, minute, second);


        // Create a calendar object for representing a Germany time zone. Then we
        // wet the time of the calendar with the value of the local time

        Calendar germanyTime = new GregorianCalendar(TimeZone.getTimeZone("Europe/Berlin"));
        germanyTime.setTimeInMillis(localTime.getTimeInMillis());
        hour = germanyTime.get(Calendar.HOUR);
        minute = germanyTime.get(Calendar.MINUTE);
        second = germanyTime.get(Calendar.SECOND);


        // Print the local time in Germany time zone
        System.out.printf("Germany time: %02d:%02d:%02d\n", hour, minute, second);
    }
}
38
Srikanth Venkatesh
    Date date = new Date();
    String formatPattern = ....;
    SimpleDateFormat sdf = new SimpleDateFormat(formatPattern);

    TimeZone T1;
    TimeZone T2;

    // set the Calendar of sdf to timezone T1
    sdf.setTimeZone(T1);
    System.out.println(sdf.format(date));

    // set the Calendar of sdf to timezone T2
    sdf.setTimeZone(T2);
    System.out.println(sdf.format(date));

    // Use the 'calOfT2' instance-methods to get specific info
    // about the time-of-day for date 'date' in timezone T2.
    Calendar calOfT2 = sdf.getCalendar();
7
Rupok

Le fuseau horaire "par défaut" peut être entièrement évité en définissant simplement le fuseau horaire de manière appropriée pour l'objet Calendar. Cependant, je vous suggère personnellement d'utiliser Joda Time comme une API bien supérieure pour les opérations de date et d'heure en Java. Entre autres choses, la conversion de fuseau horaire est très simple dans Joda.

Il n'est pas clair à quoi ressemble votre code actuel et pourquoi vous ne pouvez convertir que via le fuseau horaire par défaut, mais dans Joda Time, vous devez simplement spécifier le fuseau horaire explicitement lors de la création (par exemple) d'un DateTime object, puis utilisez withZone(DateTimeZone zone).

Si vous pouviez nous en dire plus sur la façon dont vous obtenez les données d'entrée, nous pourrions donner un exemple plus complet.

5
Jon Skeet

Vous pouvez utiliser l'extrait de code suivant

String dateString = "14 Jul 2014 00:11:04 CEST";
date = formatter.parse(dateString);
System.out.println(formatter.format(date));

// Set the formatter to use a different timezone - Indochina Time
formatter.setTimeZone(TimeZone.getTimeZone("Asia/Bangkok"));
System.out.println("ICT time : "+formatter.format(date));
4
Srijani Ghosh

Si vous ne souhaitez pas utiliser Joda, voici une manière déterministe d'utiliser les bibliothèques intégrées.

Tout d'abord, je vous recommande de forcer votre JVM par défaut à un fuseau horaire. Cela résout les problèmes que vous pourriez rencontrer lorsque vous déplacez votre machine virtuelle Java d'une machine à une autre qui sont définis sur des fuseaux horaires différents, mais vos données source sont toujours un fuseau horaire particulier. Par exemple, supposons que vos données correspondent toujours au fuseau horaire PDT/PST, mais que vous exécutez sur une boîte définie sur le fuseau horaire UTC.

L'extrait de code suivant définit le fuseau horaire par défaut dans ma machine virtuelle Java:

 //You can either pass the JVM a parameter that 
 //enforces a TZ: Java -Duser.timezone=UTC or you can do it
 //programatically like this
 TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
 TimeZone.setDefault(tz);

Supposons maintenant que votre date source arrive en PDT/PST mais vous devez la convertir en UTC. Ce sont les étapes:

    DateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC"));

    String dateStrInPDT = "2016-05-19 10:00:00";
    Date dateInPDT = dateFormat.parse(dateStrInPDT);


    String dateInUtc = dateFormatUtc.format(dateInPDT);

    System.out.println("Date In UTC is " + dateInUtc);

La sortie serait:

Date In UTC is 2016-05-19 17:00:00
2
Amro Younes

Vous pouvez utiliser la méthode Java.time.ZoneDateTime#ofInstant():

import Java.time.*;

public class TimeZonesConversion {
    static ZonedDateTime convert(ZonedDateTime time, ZoneId newTimeZone) {
        return ZonedDateTime.ofInstant(
                time.toInstant(),
                newTimeZone);
    };

    public static void main(String... args) {
        ZonedDateTime mstTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("-07")); 
        ZonedDateTime localTime = convert(mstTime, Clock.systemDefaultZone().getZone());
        System.out.println("MST(" + mstTime + ") = " + localTime);
    }
}
1
Campa

Vous pouvez faire quelque chose comme ceci pour obtenir l'heure actuelle dans un autre fuseau horaire.

Calendar japanCal = new GregorianCalendar(TimeZone.getTimeZone("Japan"));
japanCal.setTimeInMillis(local.getTimeInMillis());
1

Ce n'est pas la réponse, mais cela pourrait aider quelqu'un qui essaie de générer des dates avec le même fuseau horaire et d'appliquer un autre décalage de fuseau horaire. Il est utile lorsque votre serveur d'applications s'exécute dans un fuseau horaire et votre base de données dans un autre.

public static Date toGreekTimezone (Date date) {
  ZoneId greek = ZoneId.of(EUROPE_ATHENS);
  ZonedDateTime greekDate = ZonedDateTime.ofInstant(date.toInstant(), greek);

  ZoneId def = ZoneId.systemDefault();
  ZonedDateTime defDate = greekDate.withZoneSameLocal(def);

  return Date.from(defDate.toInstant());
}
1
Αλέκος

Cela dépend de ce que vous entendez vraiment par "convertir".

Cela PEUT être aussi simple que de définir le fuseau horaire dans FORMATTER, et de ne pas du tout nettoyer avec Calendrier.

Calendar cal = Calendar.getInstance();

TimeZone tzUTC = TimeZone.getTimeZone( "UTC" );
TimeZone tzPST = TimeZone.getTimeZone( "PST8PDT" );

DateFormat dtfmt = new SimpleDateFormat( "EEE, yyyy-MM-dd KK:mm a z" );

dtfmt.setTimeZone( tzUTC );
System.out.println( "UTC: " + dtfmt.format( cal.getTime() ));

dtfmt.setTimeZone( tzPST );
System.out.println( "PST: " + dtfmt.format( cal.getTime() ));
1
Glenn