web-dev-qa-db-fra.com

Comment puis-je retourner LocalDate.now () en millisecondes?

Je crée une date maintenant:

ZoneId gmt = ZoneId.of("GMT");
LocalDateTime localDateTime = LocalDateTime.now();
LocalDate localDateNow = localDateTime.toLocalDate();

Ensuite, je veux retourner cette date en millisecondes:

localDateNow.atStartOfDay(gmt) - 22.08.2017
localDateNow.atStartOfDay(gmt).toEpochSecond(); - 1503360000 (18.01.70)

Comment puis-je retourner LocalDate.now() en millisecondes?

12
user5620472

Appeler toInstant().toEpochMilli(), comme suggéré par @ JB Nizet's commentaire , est la bonne réponse, mais il y a un petit détail délicat sur l'utilisation des dates locales que vous devez connaître.

Mais avant cela, quelques autres détails mineurs:

  • Au lieu de ZoneId.of("GMT"), vous pouvez utiliser la constante intégrée ZoneOffset.UTC. Ils sont équivalents, mais il n'est pas nécessaire de créer des objets redondants supplémentaires si l'API en fournit déjà un qui fait exactement la même chose.
  • Au lieu d'appeler LocalDateTime.now() puis .toLocalDate(), vous pouvez appeler LocalDate.now() directement - ils sont équivalents.

Maintenant, les détails délicats: lorsque vous appelez la méthode now() (pour LocalDateTime ou LocalDate), elle utilise le fuseau horaire par défaut de la JVM pour obtenir les valeurs de la date actuelle, et cette valeur peut être différente selon le fuseau horaire configuré dans la JVM.

Dans la machine virtuelle Java que j'utilise, le fuseau horaire par défaut est America/Sao_Paulo Et l'heure locale ici est 09:37 AM . Donc LocalDate.now() renvoie 2017-08-22 (Août 22e 2017).

Mais si je change le fuseau horaire par défaut en Pacific/Kiritimati , il renvoie 2017-08-23. C'est parce qu'à Kiritimati, en ce moment c'est déjà août 23e 2017 (et l'heure locale là, au moment où j'écris ceci, est 02:37 AM ).

Donc, si j'exécute ce code lorsque le fuseau horaire par défaut est Pacific/Kiritimati:

LocalDate dtNow = LocalDate.now(); // 2017-08-23
System.out.println(dtNow.atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli());

La sortie est:

1503446400000

Ce qui équivaut à août 23e 2017 à minuit en UTC.

Si j'exécute le même code lorsque le fuseau horaire par défaut est America/Sao_Paulo, Le résultat sera:

1503360000000

Ce qui équivaut à août 22e 2017 à minuit en UTC.

L'utilisation de now() fait que votre code dépend du fuseau horaire par défaut de la JVM. Et cette configuration peut être modifiée sans préavis, même au moment de l'exécution , ce qui fait que votre code renvoie des résultats différents lorsqu'un tel changement se produit.

Et vous n'avez pas besoin d'un cas aussi extrême (comme quelqu'un qui a mal configuré la JVM sur un fuseau horaire "très éloigné"). Dans mon cas, par exemple, dans le fuseau horaire America/Sao_Paulo, Si j'exécute le code à 23 h 00 , LocalDate sera retour août 22e, mais la date actuelle en UTC sera déjà août 23e. C'est parce que 11 PM à São Paulo est le même que 2 heures du matin le lendemain en UTC:

// August 22th 2017, at 11 PM in Sao Paulo
ZonedDateTime z = ZonedDateTime.of(2017, 8, 22, 23, 0, 0, 0, ZoneId.of("America/Sao_Paulo"));
System.out.println(z); // 2017-08-22T23:00-03:00[America/Sao_Paulo]
System.out.println(z.toInstant()); // 2017-08-23T02:00:00Z (in UTC is already August 23th)

Donc, utiliser une LocalDate.now() n'est pas pas une garantie que j'aurai toujours la date courante en UTC .


Si vous souhaitez que la date actuelle en UTC (quel que soit le fuseau horaire par défaut de la JVM) et définissez l'heure sur minuit, il est préférable d'utiliser un ZonedDateTime:

// current date in UTC, no matter what the JVM default timezone is 
ZonedDateTime zdtNow = ZonedDateTime.now(ZoneOffset.UTC);
// set time to midnight and get the epochMilli
System.out.println(zdtNow.with(LocalTime.MIDNIGHT).toInstant().toEpochMilli());

La sortie est:

1503360000000

Ce qui équivaut à août 22e 2017 à minuit en UTC.

Une autre alternative consiste à passer le fuseau horaire à LocalDate.now, Afin qu'il puisse obtenir les valeurs correctes pour la date actuelle sur la zone spécifiée:

// current date in UTC, no matter what the JVM default timezone is 
LocalDate dtNowUtc = LocalDate.now(ZoneOffset.UTC);
// set time to midnight and get the epochMilli
System.out.println(dtNow.atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli());
17
user7605325