Comment obtenir la date UTC + 0 dans Java 8?

108

J'ai des problèmes avec la classe Date en Java. La classe de date renvoie la date de la machine locale mais j'ai besoin de UTC-0.

J'ai cherché sur Google et trouvé une excellente solution pour JavaScript mais pour Java rien d'utile.

Comment obtenir la date UTC + 0 dans Java 8?

marque
la source
12
java.util.Daten'est jamais une date de machine locale. Il est toujours défini en millisecondes écoulées depuis le 01/01/1970 par rapport à UTC + 00: 00. Peut-être que le comportement de sa méthode toString()vous déroute qui utilise en effet une représentation dans le fuseau horaire local.
Meno Hochschild
Une réponse probable peut être trouvée dans la question: stackoverflow.com/questions/45350095/…
Priya Jain

Réponses:

146

Avec Java 8, vous pouvez écrire:

OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);

Pour répondre à votre commentaire, vous pouvez ensuite le convertir en date (sauf si vous dépendez du code hérité je ne vois aucune raison pour laquelle) ou en millis depuis les époques:

Date date = Date.from(utc.toInstant());
long epochMillis = utc.toEpochSecond() * 1000;
assylies
la source
1
Merci. il est possible de convertir ZonedDateTime en date ou en long (ms)?
Marquez
7
Bien que le code de cette réponse fonctionne techniquement, ne serait-il pas plus approprié d'utiliser OffsetDateTimeplutôt que ZonedDateTimeétant donné que nous travaillons avec un simple décalage par rapport à UTC plutôt qu'un fuseau horaire complet?
Basil Bourque
179

tl; dr

Instant.now()

java.time

Les anciennes classes de date-heure gênantes fournies avec les premières versions de Java ont été remplacées par les classes java.time intégrées à Java 8 et versions ultérieures. Voir le didacticiel Oracle . Une grande partie des fonctionnalités a été rétroportée sur Java 6 et 7 dans ThreeTen-Backport et adaptée à Android dans ThreeTenABP .

Instant

An Instantreprésente un moment sur la chronologie en UTC avec une résolution allant jusqu'à nanosecondes .

Instant instant = Instant.now();

La toStringméthode génère un objet String avec du texte représentant la valeur date-heure en utilisant l'un des formats standard ISO 8601 .

String output = instant.toString();  

2016-06-27T19: 15: 25.864Z

La Instantclasse est une classe élémentaire de base dans java.time. Cela devrait être votre classe préférée lors de la gestion de la date et de l'heure, car la meilleure pratique consiste généralement à suivre, stocker et échanger des valeurs de date et d'heure en UTC.

OffsetDateTime

Mais Instanta des limitations telles que l'absence d'options de formatage pour générer des chaînes dans d'autres formats. Pour plus de flexibilité, passez de Instantà OffsetDateTime. Spécifiez un décalage par rapport à UTC . En java.time, cela signifie un ZoneOffsetobjet. Ici, nous voulons nous en tenir à UTC (+00) afin de pouvoir utiliser la constante pratique ZoneOffset.UTC.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC );

2016-06-27T19: 15: 25.864Z

Ou sautez le Instantcours.

OffsetDateTime.now( ZoneOffset.UTC )

Maintenant, avec un OffsetDateTimeobjet en main, vous pouvez utiliser DateTimeFormatterpour créer des objets String avec du texte dans d'autres formats. Recherchez Stack Overflow pour de nombreux exemples d'utilisation DateTimeFormatter.

ZonedDateTime

Lorsque vous souhaitez afficher l' heure de l'horloge murale pour un fuseau horaire particulier, appliquez a ZoneIdpour obtenir un ZonedDateTime.

Dans cet exemple, nous appliquons le fuseau horaire de Montréal. En été, sous le non-sens de l' heure d'été (DST) , la zone a un décalage de -04:00. Notez donc que l'heure du jour est quatre heures plus tôt dans la sortie, 15au lieu d' 19heures. Instantet les ZonedDateTimedeux représentent le même moment simultané, juste vu à travers deux lentilles différentes.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

2016-06-27T15: 15: 25.864-04: 00 [Amérique / Montréal]

Conversion

Bien que vous deviez éviter les anciennes classes date-heure, si vous le devez, vous pouvez convertir en utilisant de nouvelles méthodes ajoutées aux anciennes classes. Ici, nous utilisons java.util.Date.from( Instant )et java.util.Date::toInstant.

java.util.Date utilDate = java.util.Date.from( instant );

Et aller dans l'autre sens.

Instant instant= utilDate.toInstant();

De même, recherchez de nouvelles méthodes ajoutées à GregorianCalendar(sous-classe de Calendar) pour convertir vers et depuis java.time.ZonedDateTime.

Tableau des types de classes date-heure dans java.time moderne et hérité.

À propos de java.time

Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciens gênants hérités des classes date-heure tels que java.util.Date, Calendar, et SimpleDateFormat.

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

Le projet Joda-Time , désormais en mode maintenance , conseille la migration vers les classes java.time .

Vous pouvez échanger des objets java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou version ultérieure. Pas besoin de chaînes, pas besoin de java.sql.*classes. Hibernate 5 et JPA 2.2 prennent en charge java.time .

Où obtenir les classes java.time?

Basil Bourque
la source
3
J'apprécie de dire que l'heure d'été est un non-sens :-)
prash
Donc, si l'heure d'été n'existait pas, ZonedDateTimece ne serait pas nécessaire puisque tout ZoneIdserait mappé à celui que ZoneOffsetnous pourrions simplement utiliser OffsetDateTime?
wilmol
1
@wilmol Non. L'heure d'été (DST) n'est qu'une des nombreuses raisons pour lesquelles les politiciens choisissent de redéfinir les limites et les décalages des fuseaux horaires dans ces zones. Récemment, la Corée du Nord a changé son horloge d'une demi-heure pour se synchroniser avec la Corée du Sud pour des raisons diplomatiques. En temps de guerre, les envahisseurs / occupants peuvent modifier le décalage pour correspondre à celui du pays d'origine. Actuellement, il y a une nouvelle mode où les gouvernements choisissent d'arrêter les changements d'heure d'été, mais restent en permanence sur l' heure d' été plutôt que de revenir à leur heure standard précédente. Prévoyez toujours le décalage de chaque changement de zone, sinon votre application finira par s'arrêter.
Basil Bourque
1
Réponse fantastique! J'apprécie vraiment le temps que vous y consacrez. :)
drognisep
ZoneId.of ("Amérique / Montréal"); pourquoi quelqu'un inventerait-il une telle chose dans jdk? c'est moche, dégoûtant, ne pas dire s'il y a quelque chose qui ne va pas jusqu'au moment de l'exécution, qui peut se souvenir de tous ces codes durs? pourquoi ne pas l'impliquer dans la classe ENUM?
workplaylifecycle
4

En java8, j'utiliserais la Instantclasse qui est déjà en UTC et avec laquelle il est pratique de travailler.

import java.time.Instant;

Instant ins = Instant.now();
long ts = ins.toEpochMilli();

Instant ins2 = Instant.ofEpochMilli(ts)

Vous pouvez également utiliser les éléments suivants:

import java.time.*;

Instant ins = Instant.now(); 

OffsetDateTime odt = ins.atOffset(ZoneOffset.UTC);
ZonedDateTime zdt = ins.atZone(ZoneId.of("UTC"));

Retour à Instant

Instant ins4 = Instant.from(odt);
Abel Terefe
la source
3
Non, ce Instantn'est pas à l'heure locale. Un Instantpar définition est en UTC. Donc pas besoin des machinations vues dans cette réponse essayant d'entrer dans UTC; le Instantdéjà est en UTC. Voir ma réponse pour plus d'informations et un code beaucoup plus simple.
Basil Bourque
Merci pour le commentaire.
Abel Terefe
0

Solution 1 ligne en Java 8:

public Date getCurrentUtcTime() {
    return Date.from(Instant.now());
}
Abhijeet Ashok Muneshwar
la source