web-dev-qa-db-fra.com

JSR 310 :: System.currentTimeMillis () vs Instant.toEpochMilli () :: TimeZone

Pourriez-vous s'il vous plaît nous éclairer sur la façon d'obtenir l'heure d'époque correcte en millisecondes pour un fuseau horaire système et donné.

Donné

1. TimeZone: GMT + 3

2. L'extrait de code suivant:

import Java.time.*;

public class Main {        
    public static void main(String[] args) {
        System.out.println(LocalDateTime
            .now()
            .atZone(ZoneOffset.UTC)
            .toInstant()
            .toEpochMilli()
        );
        System.out.println(LocalDateTime
            .now()
            .atZone(ZoneOffset.of("+3"))
            .toInstant()
            .toEpochMilli()
        );
        System.out.println(System.currentTimeMillis());
    }
}

3. Sortie:

1444158955508
1444148155508
1444148155508

4. JavaDoc pour System.currentTimeMillis () qui indique que la valeur renvoyée sera la différence, mesurée en millisecondes, entre l'heure actuelle et minuit, le 1er janvier 1970 UTC.

Alors pourquoi

  1. la sortie de LocalDateTime at GMT+3 est identique à celle de System.currentTimeMillis(), bien que la documentation de System.currentTimeMillis() mentionne UTC?
  2. la sortie de LocalDateTime à UTC diffère de System.currentTimeMillis(), bien que la documentation de System.currentTimeMillis() mentionne UTC?
17
szhem

System.currentTimeMillis() et Instant.toEpochMilli() renvoient le nombre de millisecondes écoulées depuis l'époque Unix. Ce n'est pas "dans" un fuseau horaire particulier, bien que l'époque Unix soit normalement exprimée par "minuit le 1er janvier 1970, UTC". Mais un instant n’est qu’un instant, et est le même quel que soit le fuseau horaire dans lequel vous vous trouvez, mais il correspond à une heure locale différente.

La sortie de LocalDateTime.atZone(UTC) diffère parce que vous dites "Prenez la date et l'heure locales et convertissez-les en un instant comme si c'était dans le fuseau horaire UTC " - même si vous avez implicitement créé LocalDateTime dans le fuseau horaire UTC + 3 ... c'est pourquoi c'est "faux".

LocalDateTime.now() prend la date et l'heure locales dans le fuseau horaire par défaut du système . Donc, si votre fuseau horaire est UTC + 3, l'instant actuel est 2015-10-06T16: 57: 00Z, alors LocalDateTime.now() renverra .2015-10-06T19:57:00. Appelons cela localNow...

Donc localNow.atZone(ZoneOffset.of("+3")) retournera une ZonedDateTime représentant le 2015-10-06T19: 57: 00 + 03 - en d'autres termes, la même date/heure locale, mais en "sachant" qu'il a 3 heures d'avance sur UTC ... donc toInstant() renverra une Instant représentant 2015-10-06T16: 57: 00Z. Génial - nous avons toujours la date et l'heure actuelles.

Mais localNow.atZone(ZoneOffset.UTC) renverra une ZonedDateTime représentant le 2015-10-06T19: 57: 00Z - en d'autres termes, la même date/heure locale, mais "pensant" qu'il est déjà en UTC ... donc toInstant() renverra une Instant représentant 2015-10 -06T19: 57: 00Z .. qui n'est pas du tout l'heure actuelle (c'est dans trois heures).

31
Jon Skeet

Version courte:

Il n'y a aucun moyen de calculer LocalDateTime -> Instant, vous devez spécifier un fuseau horaire . Avec un fuseau horaire, vous obtenez une ZonedDateTime et pouvez calculer ZonedDateTime -> Instant.

Instant == System.currentTimeMillis() si le fuseau horaire de ZonedDateTime est égal au fuseau horaire par défaut du système.

Version longue:

LocalDateTime est l'heure sur votre horloge (plus les informations de date). Ce qui ne suffit pas si vous ne nous indiquez pas le fuseau horaire où vous vous trouvez. 13h00 à Tokyo n’est pas le même Instant à 13h00 à Paris.

Une fois que vous ajoutez un fuseau horaire à votre heure locale, vous obtenez une heure zonée et nous pouvons savoir dans quel instant instantané vous vous trouvez. Par exemple. Vous êtes 13 heures à Tokyo ou à Paris?

Pour obtenir le bon Instant, le fuseau horaire de ZonedDateTime doit être correct. S'il est 13 heures à Tokyo mais que vous prétendez être à 13 heures à Paris, vous obtiendrez un faux instant.

LocalDateTime :

Il ne peut pas représenter un instant sur la ligne de temps sans informations supplémentaires telles qu'un décalage ou un fuseau horaire.

(ZonedDateTime }:

Cette classe gère la conversion de la chronologie locale de LocalDateTime en chronologie instantanée de Instant. La différence entre les deux calendriers correspond au décalage par rapport à UTC/Greenwich, représenté par un ZoneOffset.

Pour obtenir un Instant , vous devez d'abord convertir LocalDateTime en ZonedDateTime. Si vous avez fait cela correctement (en indiquant le fuseau horaire correct), votre Instant sera d’accord avec System.currentTimeMillis ().

System.currentTimeMillis () :

la différence, mesurée en millisecondes, entre l'heure actuelle et minuit, le 1er janvier 1970 UTC.

  1. la sortie de LocalDateTime à GMT + 3 est identique à celle de System.currentTimeMillis (), bien que la documentation de System.currentTimeMillis () mentionne UTC?

Si votre fuseau horaire est GMT + 3, alors (ZonedDateTime.toInstant () } _ vous donnera l'instantané correct et vous serez donc d'accord avec System.currentTimeMillis ()

  1. la sortie de LocalDateTime à l'heure UTC diffère de System.currentTimeMillis (), bien que la documentation de System.currentTimeMillis () mentionne UTC?

Si votre fuseau horaire est pas UTC, alors ZonedDateTime.toInstant () vous donnera un incorrect Instant.

0
Roland