Afficher tous les fuseaux horaires avec GMT et UTC en Java

Afficher tous les fuseaux horaires avec GMT et UTC en Java

1. Vue d'ensemble

Chaque fois que nous traitons des heures et des dates, nous avons besoin d’un cadre de référence. La norme pour cela estUTC, mais nous voyons aussiGMT dans certaines applications.

En bref, UTC est la norme, tandis que GMT est un fuseau horaire.

Voici ce que Wikipedia nous dit concernant ce qu'il faut utiliser:

Dans la plupart des cas, l'heure UTC est considérée comme interchangeable avec l'heure GMT (Greenwich Mean Time), mais l'heure GMT n'est plus définie avec précision par la communauté scientifique.

En d'autres termes, une fois que nous avons compilé une liste avec des décalages de fuseau horaire en UTC, nous l'aurons également pour GMT.

Tout d'abord, nous allons examiner la façon dont Java 8 y parvient, puis nous verrons comment nous pouvons obtenir le même résultat en Java 7.

2. Obtenir une liste de zones

Pour commencer, nous devons extraire une liste de tous les fuseaux horaires définis.

Pour cela, la classeZoneId dispose d'une méthode statique pratique:

Set availableZoneIds = ZoneId.getAvailableZoneIds();

Ensuite, nous pouvons utiliser lesSet pour générer une liste triée de fuseaux horaires avec leurs décalages correspondants:

public List getTimeZoneList(OffsetBase base) {

    LocalDateTime now = LocalDateTime.now();
    return ZoneId.getAvailableZoneIds().stream()
      .map(ZoneId::of)
      .sorted(new ZoneComparator())
      .map(id -> String.format(
        "(%s%s) %s",
        base, getOffset(now, id), id.getId()))
      .collect(Collectors.toList());
}

La méthode ci-dessus utilise un paramètreenum qui représente le décalage que nous voulons voir:

public enum OffsetBase {
    GMT, UTC
}

Passons maintenant au code plus en détail.

Une fois que nous avons récupéré tous les ID de zone disponibles, nous avons besoin d'une référence de temps réel, représentée parLocalDateTime.now().

Ensuite, nous utilisons l’APIStream de Java pour parcourir chaque entrée de notre ensemble d’ID de fuseau horaireString et la transformer en une liste de fuseaux horaires formatés avec le décalage correspondant.

Pour chacune de ces entrées, nous générons une instanceZoneId avecmap(ZoneId::of).

3. Obtenir des décalages

Nous devons également rechercher les compensations UTC réelles. Par exemple, dans le cas de l'heure d'Europe centrale, le décalage serait de+01:00.

Pour obtenir le décalage UTC pour une zone donnée, nous pouvons utiliser la méthodeLocalDateTime’s getOffset().

Notez également que Java représente les décalages de+00:00 sous forme deZ.

Donc, pour avoir unString cohérent pour les fuseaux horaires avec le décalage zéro, nous allons remplacerZ par+00:00:

private String getOffset(LocalDateTime dateTime, ZoneId id) {
    return dateTime
      .atZone(id)
      .getOffset()
      .getId()
      .replace("Z", "+00:00");
}

4. Création de zonesComparable

Facultativement, nous pouvons également trier les fuseaux horaires en fonction du décalage.

Pour cela, nous utiliserons une classeZoneComparator:

private class ZoneComparator implements Comparator {

    @Override
    public int compare(ZoneId zoneId1, ZoneId zoneId2) {
        LocalDateTime now = LocalDateTime.now();
        ZoneOffset offset1 = now.atZone(zoneId1).getOffset();
        ZoneOffset offset2 = now.atZone(zoneId2).getOffset();

        return offset1.compareTo(offset2);
    }
}

5. Affichage des fuseaux horaires

Il ne reste plus qu'à rassembler les éléments ci-dessus en appelant la méthodegetTimeZoneList() pour chaque valeur deOffsetBase enum et en affichant les listes:

public class TimezoneDisplayApp {

    public static void main(String... args) {
        TimezoneDisplay display = new TimezoneDisplay();

        System.out.println("Time zones in UTC:");
        List utc = display.getTimeZoneList(
          TimezoneDisplay.OffsetBase.UTC);
        utc.forEach(System.out::println);

        System.out.println("Time zones in GMT:");
        List gmt = display.getTimeZoneList(
          TimezoneDisplay.OffsetBase.GMT);
        gmt.forEach(System.out::println);
    }
}

Lorsque nous exécutons le code ci-dessus, il imprime les fuseaux horaires pour UTC et GMT.

Voici un extrait de ce à quoi ressemblera le résultat:

Time zones in UTC:
(UTC+14:00) Pacific/Apia
(UTC+14:00) Pacific/Kiritimati
(UTC+14:00) Pacific/Tongatapu
(UTC+14:00) Etc/GMT-14

6. Java 7 et avant

Java 8 facilite cette tâche en utilisant les APIStream etDate and Time.

Cependant, si nous avons un Java 7 et avant un projet, nous pouvons toujours obtenir le même résultat en nous appuyant sur la classejava.util.TimeZone avec sa méthodegetAvailableIDs():

public List getTimeZoneList(OffsetBase base) {
    String[] availableZoneIds = TimeZone.getAvailableIDs();
    List result = new ArrayList<>(availableZoneIds.length);

    for (String zoneId : availableZoneIds) {
        TimeZone curTimeZone = TimeZone.getTimeZone(zoneId);
        String offset = calculateOffset(curTimeZone.getRawOffset());
        result.add(String.format("(%s%s) %s", base, offset, zoneId));
    }
    Collections.sort(result);
    return result;
}

La principale différence avec le code Java 8 réside dans le calcul de l'offset.

LesrawOffset que nous obtenons deTimeZone()‘s getRawOffset() method expresses the time zone’s offset in milliseconds.

Par conséquent, nous devons convertir cela en heures et minutes en utilisant la classeTimeUnit:

private String calculateOffset(int rawOffset) {
    if (rawOffset == 0) {
        return "+00:00";
    }
    long hours = TimeUnit.MILLISECONDS.toHours(rawOffset);
    long minutes = TimeUnit.MILLISECONDS.toMinutes(rawOffset);
    minutes = Math.abs(minutes - TimeUnit.HOURS.toMinutes(hours));

    return String.format("%+03d:%02d", hours, Math.abs(minutes));
}

7. Conclusion

Dans ce rapide tutoriel, nous avons vu comment nous pouvons compiler une liste de tous les fuseaux horaires disponibles avec leurs décalages UTC et GMT.

Et, comme toujours, le code source complet des exemples est disponibleover on GitHub.