web-dev-qa-db-fra.com

Existe-t-il un moyen de convertir ZoneId en ZoneOffset dans Java 8?

J'ai une seconde Epoch et une zoneId, par method1.Il peut être converti en LocalDateTime avec zoneId par défaut du système, mais je ne trouve pas le moyen de convertir Epoch en seconde en LocalDateTime par method2, car il n'y a pas de ZoneOffset.systemDefault. Je pense que c'est obscur .

import Java.time.{Instant, LocalDateTime, ZoneId, ZoneOffset}

val epochSecond = System.currentTimeMillis() / 1000

LocalDateTime.ofInstant(Instant.ofEpochSecond(epochSecond), ZoneId.systemDefault())//method1
LocalDateTime.ofEpochSecond(epochSecond, 0, ZoneOffset.MAX)//method2
51
Renkai

Voici comment vous pouvez obtenir ZoneOffset à partir de ZoneId:

Instant instant = Instant.now(); //can be LocalDateTime
ZoneId systemZone = ZoneId.systemDefault(); // my timezone
ZoneOffset currentOffsetForMyZone = systemZone.getRules().getOffset(instant);

NB: ZoneId peut avoir un décalage différent en fonction du moment et de l'historique du lieu. Donc, choisir différents instants entraînerait des décalages différents.

67

Il n'y a pas de mappage un à un. Un ZoneId définit une étendue géographique dans laquelle un ensemble de différents ZoneOffsets est utilisé au fil du temps. Si le fuseau horaire utilise l'heure d'été, son ZoneOffset sera différent entre été et hiver.

En outre, les règles d’heure d’été peuvent avoir changé au fil du temps, de sorte que ZoneOffset peut être différent, par exemple. 13/10/2015 comparé à 13/10/1980.

Ainsi, vous ne pouvez trouver que ZoneOffset pour un ZoneId sur un Instant particulier.

Voir aussi https://en.wikipedia.org/wiki/Tz_database

33
Geert Pante

tl; dr

ZonedDateTime.now( 
    ZoneId.of( "America/Montreal" ) 
)

… Du fuseau horaire par défaut actuel…

ZonedDateTime.now( 
    ZoneId.systemDefault() 
)

Détails

Le réponse de Stanislav Bshkyrtsev répond correctement et directement à votre question.

Mais, il y a des problèmes plus importants impliqués, comme suggéré dans la Réponse de Jon Skeet .

LocalDateTime

Je ne trouve pas le moyen de convertir Epoch Second à LocalDateTime

LocalDateTime n'a délibérément aucune notion de fuseau horaire ni de décalage par rapport à UTC. Probablement pas ce que vous voulez. Le Local… signifie une localité, pas une localité en particulier. Cette classe ne pas représente un moment, seulement des moments potentiels sur une plage d'environ 26 à 27 heures (la plage de fuseaux horaires dans le monde). 

Instant

Pas besoin de commencer par Epoch secondes si vous essayez d’obtenir l’heure actuelle. Obtenez la Instant actuelle. La classe Instant représente un moment sur la ligne temporelle en UTC avec une résolution de nanosecondes (jusqu'à neuf (9) chiffres d'une fraction décimale). 

Instant instant = Instant.now();

À l'intérieur de cette Instant se trouve un nombre de nanosecondes - de-époque. Mais nous ne nous en soucions pas vraiment. 

ZonedDateTime

Si vous voulez voir ce moment à travers l’objectif de l’horloge de la région, appliquez ZoneId pour obtenir ZonedDateTime

ZoneId z = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdt = instant.atZone( z );

En tant que raccourci, vous pouvez faire directement à la ZonedDateTime.

ZonedDateTime zdt = ZonedDateTime.now( z );  

Une ZonedDateTime a une Instant à l'intérieur. Appelez zdt.toInstant() pour obtenir le même moment qu'une valeur de base dans UTC . Même nombre de nanosecondes depuis Epoch dans les deux sens, en tant que ZonedDateTime ou en tant que Instant.

Secondes depuis l'époque donnée

Si on vous donne un nombre de secondes depuis Epoch, et que Epoch est le premier moment de 1970 dans UTC (1970-01-01T00:00:00Z), entrez ce nombre dans Instant.

long secondsSinceEpoch = 1_484_063_246L ;
Instant instant = Instant.ofEpochSecond( secondsSinceEpoch ) ;

À propos de Java.time

Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes gênantes héritées _ date-heure telles que Java.util.Date , Calendar _, & SimpleDateFormat .

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

Le projet Joda-Time , désormais en mode { 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 une version ultérieure. Pas besoin de chaînes, pas besoin de Java.sql.* classes.

Où obtenir les classes Java.time? 

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour d'éventuels ajouts à Java.time. Vous pouvez y trouver des classes utiles telles que Interval _, YearWeek , YearQuarter _ et plus _.

15
Basil Bourque

Comme l'indique la documentation , "Ceci est principalement destiné aux conversions de bas niveau plutôt qu'à l'utilisation générale des applications".

Passer par Instant me semble tout à fait logique - votre seconde Epoch est en réalité une représentation différente d’un Instant, convertissez-le donc en Instant et convertissez-le ensuite en un fuseau horaire particulier.

8
Jon Skeet

J'espère que les deux premières lignes de ma solution ci-dessous sont utiles. Mon problème était que j'avais une LocalDateTime et le nom d'un fuseau horaire et qu'il me fallait une instant pour pouvoir créer un Java.util.Date, car c'est ce que voulait MongoDB. Mon code est Scala, mais il est si proche de Java que je ne vois aucun problème à le comprendre:

val zid = ZoneId.of(tzName)                                // "America/Los_Angeles"
val zo: ZoneOffset = zid.getRules.getOffset(localDateTime) // ⇒ -07:00
                                         // 2017-03-16T18:03

val odt = OffsetDateTime.of(localDateTime, zo) // ⇒ 2017-03-16T18:03:00-07:00
val instant = odt.toInstant                    // ⇒ 2017-03-17T01:03:00Z
val issued = Date.from(instant)
6
gknauth

Ce qui suit renvoie le temps en millisecondes à ajouter à l'heure UTC pour obtenir l'heure standard dans ce fuseau horaire:

TimeZone.getTimeZone(ZoneId.of("Europe/Amsterdam")).getRawOffset()
0
Jelmer